mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-29 18:53:22 +08:00
cleaning up audio shutdown
This commit is contained in:
parent
baa09a775d
commit
c42318cccc
56
.efrocachemap
generated
56
.efrocachemap
generated
@ -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",
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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"
|
||||
],
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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'
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -68,7 +68,9 @@ void AudioStreamer::Stop() {
|
||||
}
|
||||
|
||||
void AudioStreamer::Update() {
|
||||
if (eof_) return;
|
||||
if (eof_) {
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK_AL_ERROR;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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_{};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user