cleaning up audio shutdown

This commit is contained in:
Eric 2023-10-14 23:00:26 -07:00
parent baa09a775d
commit c42318cccc
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
25 changed files with 596 additions and 480 deletions

56
.efrocachemap generated
View File

@ -4056,26 +4056,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "af600306cf8085f909e40a7d2129a73b",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "54f7cdbdbc16601ff1f841e48cecf05c",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "cc6387a5d3a8f36b7bf667f9b7e719df",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "0de15cf59051ba17ee91e3d3ac25be93",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "345c4646377145cf88b30fcba122f42b",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4dae703893e19bed1e8a16029a646104",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "573adb2913309a6c375a6d3b92a20208",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "3db3c7e41182fd05f5f9731fee3002d0",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "1e3e5ee34645928ec3bdc3c52de98839",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "41354efa8cdbb83a3b2e4cd7fce6b308",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "a304c1a0d2d2f5bdbc31a27ec899a95b",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6b236e3246ded0460fcc7ea50fc51b36",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "e26b4e3b5e2bca5606d2ac674fcc7496",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "ae954a12775213c64d45b535b289ebff",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "960c3e2fd9c3e19de75fd92546447890",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "e0c05531b48ec5e36da10783280957fe",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "e1c137fdefcf34a642c0962999973eff",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "bdf75b68e6b0e1c8dcfa76ac04306fbb",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "5f01ab596c3d389c95761db531b1766b",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "4826ca9c757dbf38749710bc94844aca",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "8ea626f6dd70d998ee77c58fffc51545",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "d7ad10904fe7c4d4555366ccb1feedcb",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "a9eea92d521e97b1772b5e44b402ce8a",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "57043f40971d800d27ee6d646aae8d61",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "3e4009d7fa4b90abc526f56361ecab05",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "334cdc0688e66a1bc75cd05bae1729c7",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "95278d80378be5b61026253492cbfa70",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "0a3da8e5264a7b733960e83a0e8c4bba",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a089d4aaa39e18553cf0a70a77b4cfcd",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "e66c4eceb79710b8fda2bfea781e241a",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "6b3021b9a7584da86bbb95324e81e851",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6fe90d50f905a0da9fa52c39a458d1e3",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "afc7ed826486aec82613832865177570",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "ae8b6dad770793188aad8e2966189bb3",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "7622dde1a021152cac42e7db3e803392",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "8a4b1e521bf668cc6ec6a65519defb12",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9a69c0d4c9ae319595843b16f14795fc",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "89c02260fb4781f5e293658cecbb363f",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "3165d4230069c22300abfff8abf1d714",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "41e46dfdbb542e3e823f6aee87e93ac9",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "20cc128ff9d44f9d74e4301c6d49f48f",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "f93bc8f98ee31f39b54ab46264eccb22",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "20cc128ff9d44f9d74e4301c6d49f48f",
@ -4092,14 +4092,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c8715c85010ea431d7346f40f5421819",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "49775819d4ba9af15061080d17377a18",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c8715c85010ea431d7346f40f5421819",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "99e44969ef0f9421f21cb32554464bc7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "a14441d4ff9adae6e015a9f0d107a61a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "90b5c353d5296be7e3b06e8c823564bb",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "84409ce44260a641295c1459e4d3af8f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "35c58dd0a7482bb5f1ef5d6edb647c46",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "a7c2895f59f75b767258277c766e9ed4",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "e0430eeeb324ccfca8ace41d743e069c",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d594057005fc56c8576f555f892b3dc4",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "750c2964308cd3f3e5986fcda9a25706",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "772af7da6a115f53b0b3f6a4afd3baec",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "178c1a53a7ad50297aed68d0ca3a1476",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "b011bc2b6437995f2d33f5215b4ffa36",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a758a4f98336208381b093aacb735878",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "6c86545fab2327105114676a20ca5e68",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "f75525fdc9f7db4a81ca9bae6a79add5",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "2e297069baec404d43ccdb18abeef658",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "ba8ce3ca3858b4c2d20db68f99b788b2",

View File

@ -1,4 +1,4 @@
### 1.7.28 (build 21453, api 8, 2023-10-13)
### 1.7.28 (build 21465, api 8, 2023-10-14)
- Massively cleaned up code related to rendering and window systems (OpenGL,
SDL, etc). This code had been growing into a nasty tangle for 15 years
@ -144,6 +144,8 @@
that you will be cutting off support for older clients if you use 35.
- Fixed a bug with screen-messages animating off screen too fast when frame
rates are high.
- Added a proper graceful shutdown process for the audio server. This should
result in fewer ugly pops and warning messages when the app is quit.
### 1.7.27 (build 21282, api 8, 2023-08-30)

View File

@ -14,7 +14,6 @@
"src/ballistica/core/platform/android/utf8/checked.h",
"src/ballistica/core/platform/android/utf8/unchecked.h",
"src/ballistica/core/platform/android/utf8/core.h",
"src/ballistica/base/platform/apple/sdl_main_mac.h",
"src/ballistica/base/platform/oculus/main_rift.cc",
"src/ballistica/core/platform/android/android_gl3.c"
],

View File

@ -210,7 +210,8 @@ class App:
self._shutdown_task: asyncio.Task[None] | None = None
self._shutdown_tasks: list[Coroutine[None, None, None]] = [
self._wait_for_shutdown_suppressions(),
self._fade_for_shutdown(),
self._fade_and_shutdown_graphics(),
self._fade_and_shutdown_audio(),
]
self._pool_thread_count = 0
@ -798,6 +799,7 @@ class App:
async def _shutdown(self) -> None:
import asyncio
_babase.lock_all_input()
try:
async with asyncio.TaskGroup() as task_group:
for task_coro in self._shutdown_tasks:
@ -898,18 +900,26 @@ class App:
await asyncio.sleep(0.001)
_babase.lifecyclelog('shutdown-suppress wait end')
async def _fade_for_shutdown(self) -> None:
async def _fade_and_shutdown_graphics(self) -> None:
import asyncio
# Kick off a fade, block input, and wait for a short bit.
# Ideally most shutdown activity completes during the fade so
# there's no tangible wait.
_babase.lifecyclelog('fade-for-shutdown begin')
# Kick off a short fade and give it time to complete.
_babase.lifecyclelog('fade-and-shutdown-graphics begin')
_babase.fade_screen(False, time=0.15)
_babase.lock_all_input()
# _babase.getsimplesound('swish2').play()
await asyncio.sleep(0.15)
_babase.lifecyclelog('fade-for-shutdown end')
_babase.lifecyclelog('fade-and-shutdown-graphics end')
async def _fade_and_shutdown_audio(self) -> None:
import asyncio
# Tell the audio system to go down and give it a bit of
# time to do so gracefully.
_babase.lifecyclelog('fade-and-shutdown-audio begin')
_babase.audio_shutdown_begin()
await asyncio.sleep(0.15)
while not _babase.audio_shutdown_is_complete():
await asyncio.sleep(0.01)
_babase.lifecyclelog('fade-and-shutdown-audio end')
def _threadpool_no_wait_done(self, fut: Future) -> None:
try:

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21453
TARGET_BALLISTICA_BUILD = 21465
TARGET_BALLISTICA_VERSION = '1.7.28'

View File

@ -190,13 +190,13 @@ void AppAdapterApple::SetHardwareCursorVisible(bool visible) {
assert(g_core->InMainThread());
#if BA_OSTYPE_MACOS
BallisticaKit::CocoaSupportSetCursorVisible(visible);
BallisticaKit::CocoaFromCppSetCursorVisible(visible);
#endif
}
void AppAdapterApple::TerminateApp() {
#if BA_OSTYPE_MACOS
BallisticaKit::CocoaSupportTerminateApp();
BallisticaKit::CocoaFromCppTerminateApp();
#else
AppAdapter::TerminateApp();
#endif

View File

@ -101,7 +101,7 @@ auto Audio::SourceBeginNew() -> AudioSource* {
#pragma clang diagnostic pop
auto Audio::IsSoundPlaying(uint32_t play_id) -> bool {
uint32_t source_id = AudioServer::source_id_from_play_id(play_id);
uint32_t source_id = AudioServer::SourceIdFromPlayId(play_id);
assert(client_sources_.size() > source_id);
client_sources_[source_id]->Lock(2);
bool result = (client_sources_[source_id]->play_id() == play_id);
@ -112,7 +112,7 @@ auto Audio::IsSoundPlaying(uint32_t play_id) -> bool {
auto Audio::SourceBeginExisting(uint32_t play_id, int debug_id)
-> AudioSource* {
BA_DEBUG_FUNCTION_TIMER_BEGIN();
uint32_t source_id = AudioServer::source_id_from_play_id(play_id);
uint32_t source_id = AudioServer::SourceIdFromPlayId(play_id);
// Ok, the audio thread fills in this source list,
// so theoretically a client could call this before the audio thread

File diff suppressed because it is too large Load Diff

View File

@ -12,14 +12,14 @@
namespace ballistica::base {
/// A module that handles audio processing.
/// Wrangles audio off in its own thread.
class AudioServer {
public:
static auto source_id_from_play_id(uint32_t play_id) -> uint32_t {
static auto SourceIdFromPlayId(uint32_t play_id) -> uint32_t {
return play_id & 0xFFFFu;
}
static auto play_count_from_play_id(uint32_t play_id) -> uint32_t {
static auto PlayCountFromPlayId(uint32_t play_id) -> uint32_t {
return play_id >> 16u;
}
@ -28,10 +28,9 @@ class AudioServer {
void PushSetVolumesCall(float music_volume, float sound_volume);
void PushSetSoundPitchCall(float val);
void PushSetSuspendedCall(bool pause);
static void BeginInterruption();
static void EndInterruption();
// static void BeginInterruption();
// static void EndInterruption();
void PushSetListenerPositionCall(const Vector3f& p);
void PushSetListenerOrientationCall(const Vector3f& forward,
@ -41,10 +40,12 @@ class AudioServer {
void PushComponentUnloadCall(
const std::vector<Object::Ref<Asset>*>& components);
/// For use by g_logic_module().
void ClearSoundRefDeleteList();
auto paused() const -> bool { return paused_; }
auto paused() const -> bool { return suspended_; }
void Shutdown();
auto shutdown_completed() const { return shutdown_completed_; }
// Client sources use these to pass settings to the server.
void PushSourceSetIsMusicCall(uint32_t play_id, bool val);
@ -67,37 +68,36 @@ class AudioServer {
auto event_loop() const -> EventLoop* { return event_loop_; }
private:
class ThreadSource;
struct Impl;
class ThreadSource_;
struct Impl_;
void OnAppStartInThread();
void OnAppStartInThread_();
~AudioServer();
void OnThreadPause();
void OnThreadResume();
void OnThreadSuspend_();
void OnThreadUnsuspend_();
void SetPaused(bool paused);
void SetSuspended_(bool suspended);
void SetMusicVolume(float volume);
void SetSoundVolume(float volume);
void SetSoundPitch(float pitch);
auto music_volume() -> float { return music_volume_; }
auto sound_volume() -> float { return sound_volume_; }
auto sound_pitch() -> float { return sound_pitch_; }
void SetMusicVolume_(float volume);
void SetSoundVolume_(float volume);
void SetSoundPitch_(float pitch);
void CompleteShutdown_();
/// If a sound play id is currently playing, return the sound.
auto GetPlayingSound(uint32_t play_id) -> ThreadSource*;
auto GetPlayingSound_(uint32_t play_id) -> ThreadSource_*;
void Reset();
void Process();
void Reset_();
void Process_();
/// Send a component to the audio thread to delete.
void DeleteAssetComponent(Asset* c);
// void DeleteAssetComponent_(Asset* c);
void UpdateTimerInterval();
void UpdateAvailableSources();
void UpdateMusicPlayState();
void ProcessSoundFades();
void UpdateTimerInterval_();
void UpdateAvailableSources_();
void UpdateMusicPlayState_();
void ProcessSoundFades_();
// Some threads such as audio hold onto allocated Media-Component-Refs to keep
// media components alive that they need. Media-Component-Refs, however, must
@ -107,32 +107,36 @@ class AudioServer {
// Note: should use unique_ptr for this, but build fails on raspberry pi
// (gcc 8.3.0). Works on Ubuntu 9.3 so should try again later.
// std::unique_ptr<Impl> impl_{};
Impl* impl_{};
std::unique_ptr<Impl_> impl_{};
// Impl* impl_{};
EventLoop* event_loop_{};
Timer* process_timer_{};
bool have_pending_loads_{};
bool paused_{};
millisecs_t last_sound_fade_process_time_{};
float sound_volume_{1.0f};
float sound_pitch_{1.0f};
float music_volume_{1.0f};
bool have_pending_loads_ : 1 {};
bool suspended_ : 1 {};
bool shutdown_completed_ : 1 {};
bool shutting_down_ : 1 {};
seconds_t shutdown_start_time_{};
millisecs_t last_sound_fade_process_time_{};
/// Indexed list of sources.
std::vector<ThreadSource*> sources_;
std::vector<ThreadSource*> streaming_sources_;
std::vector<ThreadSource_*> sources_;
std::vector<ThreadSource_*> streaming_sources_;
millisecs_t last_stream_process_time_{};
millisecs_t last_sanity_check_time_{};
// Holds refs to all sources.
// Use sources, not this, for faster iterating.
std::vector<Object::Ref<ThreadSource> > sound_source_refs_;
struct SoundFadeNode;
std::vector<Object::Ref<ThreadSource_>> sound_source_refs_;
struct SoundFadeNode_;
// NOTE: would use unordered_map here but gcc doesn't seem to allow
// forward-declared template params with them.
std::map<int, SoundFadeNode> sound_fade_nodes_;
std::map<int, SoundFadeNode_> sound_fade_nodes_;
// This mutex controls access to our list of media component shared ptrs to
// delete in the main thread.
@ -141,9 +145,7 @@ class AudioServer {
// Our list of sound media components to delete via the main thread.
std::vector<const Object::Ref<SoundAsset>*> sound_ref_delete_list_;
millisecs_t last_sanity_check_time_{};
static int al_source_count_;
int al_source_count_{};
};
} // namespace ballistica::base

View File

@ -15,7 +15,7 @@ AudioSource::AudioSource(int id_in) : id_(id_in) {}
AudioSource::~AudioSource() { assert(client_queue_size_ == 0); }
void AudioSource::MakeAvailable(uint32_t play_id_new) {
assert(AudioServer::source_id_from_play_id(play_id_new) == id_);
assert(AudioServer::SourceIdFromPlayId(play_id_new) == id_);
assert(client_queue_size_ == 0);
assert(locked());
play_id_ = play_id_new;

View File

@ -68,7 +68,9 @@ void AudioStreamer::Stop() {
}
void AudioStreamer::Update() {
if (eof_) return;
if (eof_) {
return;
}
CHECK_AL_ERROR;

View File

@ -23,17 +23,18 @@ class AudioStreamer : public Object {
auto Play() -> bool;
void Stop();
void Update();
enum Format { INVALID_FORMAT, MONO16_FORMAT, STEREO16_FORMAT };
enum class Format : uint8_t { kInvalid, kMono16, kStereo16 };
auto al_format() const -> ALenum {
switch (format_) {
case MONO16_FORMAT:
case Format::kMono16:
return AL_FORMAT_MONO16;
case STEREO16_FORMAT:
case Format::kStereo16:
return AL_FORMAT_STEREO16;
default:
break;
}
return INVALID_FORMAT;
FatalError("Invalid AL format.");
return AL_FORMAT_MONO16;
}
auto loops() const -> bool { return loops_; }
auto file_name() const -> const std::string& { return file_name_; }
@ -46,13 +47,13 @@ class AudioStreamer : public Object {
void set_format(Format format) { format_ = format; }
private:
Format format_ = INVALID_FORMAT;
bool playing_ = false;
Format format_{Format::kInvalid};
bool playing_ : 1 {};
bool loops_ : 1 {};
bool eof_ : 1 {};
ALuint buffers_[kAudioStreamBufferCount]{};
ALuint source_ = 0;
ALuint source_{};
std::string file_name_;
bool loops_ = false;
bool eof_ = false;
};
#endif // BA_ENABLE_AUDIO

View File

@ -53,9 +53,9 @@ OggStream::OggStream(const char* file_name, ALuint source, bool loop)
vorbis_info_ = ov_info(&ogg_file_, -1);
if (vorbis_info_->channels == 1) {
set_format(MONO16_FORMAT);
set_format(Format::kMono16);
} else {
set_format(STEREO16_FORMAT);
set_format(Format::kStereo16);
}
}

View File

@ -4,6 +4,7 @@
#include "ballistica/base/app_adapter/app_adapter.h"
#include "ballistica/base/app_mode/app_mode_empty.h"
#include "ballistica/base/audio/audio_server.h"
#include "ballistica/base/graphics/graphics_server.h"
#include "ballistica/base/logic/logic.h"
#include "ballistica/base/python/base_python.h"
@ -729,11 +730,8 @@ static auto PyEnv(PyObject* self) -> PyObject* {
"ss" // ui_scale
"sO" // on_tv
"sO" // vr_mode
// "sO" // toolbar_test
"sO" // demo_mode
"sO" // arcade_mode
// "sO" // iircade_mode
// "si" // protocol_version
"sO" // headless_mode
"sO" // python_directory_app_site
"ss" // device_name
@ -757,8 +755,6 @@ static auto PyEnv(PyObject* self) -> PyObject* {
"vr_mode", g_core->IsVRMode() ? Py_True : Py_False,
"demo_mode", g_buildconfig.demo_build() ? Py_True : Py_False,
"arcade_mode", g_buildconfig.arcade_build() ? Py_True : Py_False,
// "iircade_mode", g_buildconfig.iircade_build() ? Py_True: Py_False,
// "protocol_version", kProtocolVersion,
"headless_mode", g_core->HeadlessMode() ? Py_True : Py_False,
"python_directory_app_site",
site_py_dir ? *PythonRef::FromString(*site_py_dir) : Py_None,
@ -1603,6 +1599,52 @@ static PyMethodDef PyDevConsoleInputAdapterFinishDef = {
"(internal)\n",
};
// -------------------------- audio_shutdown_begin -----------------------------
static auto PyAudioShutdownBegin(PyObject* self) -> PyObject* {
BA_PYTHON_TRY;
auto* audio_event_loop = g_base->audio_server->event_loop();
BA_PRECONDITION(audio_event_loop);
audio_event_loop->PushCall([] { g_base->audio_server->Shutdown(); });
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyAudioShutdownBeginDef = {
"audio_shutdown_begin", // name
(PyCFunction)PyAudioShutdownBegin, // method
METH_NOARGS, // flags
"audio_shutdown_begin() -> None\n"
"\n"
"(internal)\n",
};
// ----------------------- audio_shutdown_is_complete --------------------------
static auto PyAudioShutdownIsComplete(PyObject* self) -> PyObject* {
BA_PYTHON_TRY;
if (g_base->audio_server->shutdown_completed()) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyAudioShutdownIsCompleteDef = {
"audio_shutdown_is_complete", // name
(PyCFunction)PyAudioShutdownIsComplete, // method
METH_NOARGS, // flags
"audio_shutdown_is_complete() -> bool\n"
"\n"
"(internal)\n",
};
// -----------------------------------------------------------------------------
auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
@ -1658,6 +1700,8 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
PyGetDevConsoleInputTextDef,
PySetDevConsoleInputTextDef,
PyDevConsoleInputAdapterFinishDef,
PyAudioShutdownBeginDef,
PyAudioShutdownIsCompleteDef,
};
}

View File

@ -42,7 +42,7 @@ UI::UI() {
// VR and TV modes always use medium.
scale_ = UIScale::kMedium;
} else {
scale_ = g_core->platform->GetUIScale();
scale_ = g_core->platform->GetDefaultUIScale();
}
}
}

View File

@ -4,8 +4,10 @@
#include "ballistica/core/platform/apple/core_platform_apple.h"
#if BA_XCODE_BUILD
#include <BallisticaKit-Swift.h>
#include <unistd.h>
#endif
#include <uuid/uuid.h>
#if BA_XCODE_BUILD
@ -102,7 +104,7 @@ auto CorePlatformApple::DoGetConfigDirectoryMonolithicDefault()
auto CorePlatformApple::GetLocale() -> std::string {
#if BA_XCODE_BUILD
return base::AppleUtils::GetLocaleString();
return BallisticaKit::FromCppGetLocaleString();
#else
return CorePlatform::GetLocale();
#endif
@ -124,7 +126,7 @@ auto CorePlatformApple::DoHasTouchScreen() -> bool {
#endif
}
auto CorePlatformApple::GetUIScale() -> UIScale {
auto CorePlatformApple::GetDefaultUIScale() -> UIScale {
#if BA_OSTYPE_IOS
if (base::AppleUtils::IsTablet()) {
return UIScale::kMedium;
@ -132,8 +134,8 @@ auto CorePlatformApple::GetUIScale() -> UIScale {
return UIScale::kSmall;
}
#else
// default case handles mac/tvos
return CorePlatform::GetUIScale();
// Default case handles mac & tvos.
return CorePlatform::GetDefaultUIScale();
#endif
}
@ -160,9 +162,8 @@ void CorePlatformApple::DisplayLog(const std::string& name, LogLevel level,
}
auto CorePlatformApple::DoGetDataDirectoryMonolithicDefault() -> std::string {
#if BA_XCODE_BUILD && !BA_HEADLESS_BUILD
// On Apple package-y builds use our resources dir.
return base::AppleUtils::GetResourcesPath();
#if BA_XCODE_BUILD
return BallisticaKit::FromCppGetResourcesPath();
#else
// Fall back to default.
return CorePlatform::DoGetDataDirectoryMonolithicDefault();
@ -292,13 +293,8 @@ void CorePlatformApple::OpenFileExternally(const std::string& path) {
}
void CorePlatformApple::OpenDirExternally(const std::string& path) {
#if BA_OSTYPE_MACOS
std::string cmd = std::string("open \"") + path + "\"";
int result = system(cmd.c_str());
if (result != 0) {
Log(LogLevel::kError, "Got return value " + std::to_string(result)
+ " on open cmd '" + cmd + "'");
}
#if BA_OSTYPE_MACOS && BA_XCODE_BUILD
BallisticaKit::CocoaFromCppOpenDirExternally(path);
#else
CorePlatform::OpenDirExternally(path);
#endif
@ -380,7 +376,7 @@ auto CorePlatformApple::DoClipboardIsSupported() -> bool {
return base::AppleUtils::ClipboardIsSupported();
#else
return CorePlatform::DoClipboardIsSupported();
#endif // BA_XCODE_BUILD
#endif
}
auto CorePlatformApple::DoClipboardHasText() -> bool {
@ -388,7 +384,7 @@ auto CorePlatformApple::DoClipboardHasText() -> bool {
return base::AppleUtils::ClipboardHasText();
#else
return CorePlatform::DoClipboardHasText();
#endif // BA_XCODE_BUILD
#endif
}
void CorePlatformApple::DoClipboardSetText(const std::string& text) {
@ -396,7 +392,7 @@ void CorePlatformApple::DoClipboardSetText(const std::string& text) {
base::AppleUtils::ClipboardSetText(text);
#else
CorePlatform::DoClipboardSetText(text);
#endif // BA_XCODE_BUILD
#endif
}
auto CorePlatformApple::DoClipboardGetText() -> std::string {
@ -404,7 +400,7 @@ auto CorePlatformApple::DoClipboardGetText() -> std::string {
return base::AppleUtils::ClipboardGetText();
#else
return CorePlatform::DoClipboardGetText();
#endif // BA_XCODE_BUILD
#endif
}
} // namespace ballistica::core

View File

@ -24,7 +24,7 @@ class CorePlatformApple : public CorePlatform {
auto GetLocale() -> std::string override;
auto DoGetDeviceName() -> std::string override;
auto DoHasTouchScreen() -> bool override;
auto GetUIScale() -> UIScale override;
auto GetDefaultUIScale() -> UIScale override;
auto IsRunningOnDesktop() -> bool override;
void DisplayLog(const std::string& name, LogLevel level,
const std::string& msg) override;

View File

@ -476,7 +476,7 @@ void CorePlatform::SleepMicrosecs(millisecs_t ms) {
#pragma clang diagnostic push
#pragma ide diagnostic ignored "NullDereferences"
auto CorePlatform::GetUIScale() -> UIScale {
auto CorePlatform::GetDefaultUIScale() -> UIScale {
// Handles mac/pc/linux cases.
return UIScale::kLarge;
}

View File

@ -97,26 +97,22 @@ class CorePlatform {
#pragma mark PRINTING/LOGGING --------------------------------------------------
/// Display a message to any default log for the platform (android log,
/// etc.) Note that this can be called from any thread.
/// etc.) Note that this can be called from any thread. Default
/// implementation does nothing.
virtual void DisplayLog(const std::string& name, LogLevel level,
const std::string& msg);
#pragma mark ENVIRONMENT -------------------------------------------------------
// Return a simple name for the platform: 'mac', 'windows', 'linux', etc.
/// Return a simple name for the platform: 'mac', 'windows', 'linux', etc.
virtual auto GetPlatformName() -> std::string;
// Return a simple name for the subplatform: 'amazon', 'google', etc.
/// Return a simple name for the subplatform: 'amazon', 'google', etc.
virtual auto GetSubplatformName() -> std::string;
// Are we running in event-push-mode? With this on, we return from Main()
// and the system handles the event loop. With it off, we loop in Main()
// ourself.
// virtual auto IsEventPushMode() -> bool;
/// Return the interface type based on the environment (phone, tablet,
/// etc).
virtual auto GetUIScale() -> UIScale;
virtual auto GetDefaultUIScale() -> UIScale;
/// Return default DataDirectory value for monolithic builds.
auto GetDataDirectoryMonolithicDefault() -> std::string;
@ -387,7 +383,7 @@ class CorePlatform {
static void SleepMillisecs(millisecs_t ms);
static void SleepMicrosecs(millisecs_t ms);
static void SleepMicrosecs(microsecs_t ms);
/// Given a C++ symbol, attempt to return a pretty one.
virtual auto DemangleCXXSymbol(const std::string& s) -> std::string;

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21453;
const int kEngineBuildNumber = 21465;
const char* kEngineVersion = "1.7.28";
const int kEngineApiVersion = 8;

View File

@ -248,24 +248,27 @@ void EventLoop::WaitForNextEvent_(bool single_cycle) {
}
}
// void EventLoop::LoopUpkeep_(bool single_cycle) {
// assert(g_core);
// // Keep our autorelease pool clean on mac/ios
// // FIXME: Should define a CorePlatform::ThreadHelper or something
// // so we don't have platform-specific code here.
// #if BA_XCODE_BUILD
// // Let's not do autorelease pools when being called ad-hoc,
// // since in that case we're part of another run loop
// // (and its crashing on drain for some reason)
// if (!single_cycle) {
// if (auto_release_pool_) {
// g_core->platform->DrainAutoReleasePool(auto_release_pool_);
// auto_release_pool_ = nullptr;
// }
// auto_release_pool_ = g_core->platform->NewAutoReleasePool();
// }
// #endif
// }
// Note to self (Oct '23): can probably kill this at some point,
// but am still using some non-ARC objc stuff from logic thread
// so should keep it around just a bit longer just in case.
void EventLoop::LoopUpkeep_(bool single_cycle) {
assert(g_core);
// Keep our autorelease pool clean on mac/ios
// FIXME: Should define a CorePlatform::ThreadHelper or something
// so we don't have platform-specific code here.
#if BA_XCODE_BUILD
// Let's not do autorelease pools when being called ad-hoc,
// since in that case we're part of another run loop
// (and its crashing on drain for some reason)
if (!single_cycle) {
if (auto_release_pool_) {
g_core->platform->DrainAutoReleasePool(auto_release_pool_);
auto_release_pool_ = nullptr;
}
auto_release_pool_ = g_core->platform->NewAutoReleasePool();
}
#endif
}
void EventLoop::RunToCompletion() { Run_(false); }
void EventLoop::RunSingleCycle() { Run_(true); }
@ -273,7 +276,7 @@ void EventLoop::RunSingleCycle() { Run_(true); }
void EventLoop::Run_(bool single_cycle) {
assert(g_core);
while (true) {
// LoopUpkeep_(single_cycle);
LoopUpkeep_(single_cycle);
WaitForNextEvent_(single_cycle);

View File

@ -118,7 +118,6 @@ class EventLoop {
auto CheckPushRunnableSafety_() -> bool;
void SetInternalThreadName_(const std::string& name);
void WaitForNextEvent_(bool single_cycle);
// void LoopUpkeep_(bool single_cycle);
void LogThreadMessageTally_(
std::vector<std::pair<LogLevel, std::string>>* log_entries);
void PushLocalRunnable_(Runnable* runnable, bool* completion_flag);
@ -155,6 +154,13 @@ class EventLoop {
void BootstrapThread_();
void LoopUpkeep_(bool single_cycle);
// FIXME: Should generalize this to some sort of PlatformThreadData class.
#if BA_XCODE_BUILD
void* auto_release_pool_{};
#endif
bool bootstrapped_{};
bool writing_tally_{};
bool suspended_{};

View File

@ -88,8 +88,7 @@ template <typename OUT_TYPE, typename IN_TYPE>
auto static_cast_check_type(IN_TYPE in) -> OUT_TYPE {
auto out_static = static_cast<OUT_TYPE>(in);
if (g_buildconfig.debug_build()) {
auto out_dynamic = dynamic_cast<OUT_TYPE>(in);
assert(out_static == out_dynamic);
assert(out_static == dynamic_cast<OUT_TYPE>(in));
}
return out_static;
}

View File

@ -30,6 +30,7 @@ typedef struct _SDL_Joystick SDL_Joystick;
namespace ballistica {
// Used internally for time values.
typedef double seconds_t;
typedef int64_t millisecs_t;
typedef int64_t microsecs_t;

View File

@ -23,10 +23,6 @@
#include "ballistica/ui_v1/widget/row_widget.h"
#include "ballistica/ui_v1/widget/scroll_widget.h"
// #if !BA_HEADLESS_BUILD && !BA_XCODE_NEW_PROJECT
// extern "C" void SDL_ericf_focus(void);
// #endif
namespace ballistica::ui_v1 {
// Ignore signed bitwise stuff; python macros do it quite a bit.