From 031eb78fd86468e6e621dc5937c3c6ee098fe00c Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 9 Oct 2022 21:28:35 -0230 Subject: [PATCH 1/3] Separate sound mute and enable functionality. Mute simply changes the sound level; disabling sound completely is now done separately. --- src/common/AudioQueue.hxx | 2 +- src/common/SoundNull.hxx | 6 ----- src/common/SoundSDL2.cxx | 42 +++++++++++-------------------- src/common/SoundSDL2.hxx | 20 ++++++--------- src/emucore/Console.cxx | 16 ++++++------ src/emucore/OSystem.cxx | 2 +- src/emucore/Sound.hxx | 6 ----- src/os/libretro/SoundLIBRETRO.hxx | 16 ------------ 8 files changed, 31 insertions(+), 79 deletions(-) diff --git a/src/common/AudioQueue.hxx b/src/common/AudioQueue.hxx index 5dd223489..a57b64ab6 100644 --- a/src/common/AudioQueue.hxx +++ b/src/common/AudioQueue.hxx @@ -24,7 +24,7 @@ #include "StaggeredLogger.hxx" /** - This class implements a an audio queue that acts both like a ring buffer + This class implements an audio queue that acts both like a ring buffer and a pool of audio fragments. The TIA emulation core fills a fragment with samples and then returns it to the queue, receiving a new fragment in return. The sound driver removes fragments for playback from the diff --git a/src/common/SoundNull.hxx b/src/common/SoundNull.hxx index 5007bf49c..d5726d7c4 100644 --- a/src/common/SoundNull.hxx +++ b/src/common/SoundNull.hxx @@ -59,12 +59,6 @@ class SoundNull : public Sound */ void open(shared_ptr, EmulationTiming*) override { } - /** - Should be called to close the sound device. Once called the sound - device can be started again using the initialize method. - */ - void close() override { } - /** Sets the sound mute state; sound processing continues. When turned off, sound volume is 0; when turned on, sound volume returns to diff --git a/src/common/SoundSDL2.cxx b/src/common/SoundSDL2.cxx index 9e07564e3..3bee69bcf 100644 --- a/src/common/SoundSDL2.cxx +++ b/src/common/SoundSDL2.cxx @@ -141,7 +141,6 @@ bool SoundSDL2::openDevice() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SoundSDL2::setEnabled(bool enable) { -cerr << "setEnabled: " << enable << endl; mute(!enable); pause(!enable); } @@ -164,7 +163,6 @@ void SoundSDL2::open(shared_ptr audioQueue, Logger::debug("SoundSDL2::open started ..."); - myAudioSettings.setEnabled(true); audioQueue->ignoreOverflows(!myAudioSettings.enabled()); if(!myAudioSettings.enabled()) { @@ -193,22 +191,9 @@ void SoundSDL2::open(shared_ptr audioQueue, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void SoundSDL2::close() +void SoundSDL2::mute(bool enable) { - if(!myIsInitializedFlag) - return; - - if(myAudioQueue) - myAudioQueue->closeSink(myCurrentFragment); - myAudioQueue.reset(); - myCurrentFragment = nullptr; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void SoundSDL2::mute(bool state) -{ - myAudioSettings.setEnabled(!state); - if(state) + if(enable) myVolumeFactor = 0; else setVolume(myAudioSettings.volume()); @@ -217,27 +202,29 @@ void SoundSDL2::mute(bool state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SoundSDL2::toggleMute() { - const bool state = !myAudioSettings.enabled(); - mute(!state); + const bool wasMuted = myVolumeFactor == 0; + mute(!wasMuted); string message = "Sound "; - message += state ? "unmuted" : "muted"; + message += !myAudioSettings.enabled() + ? "disabled" + : (wasMuted ? "unmuted" : "muted"); myOSystem.frameBuffer().showTextMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool SoundSDL2::pause(bool state) +bool SoundSDL2::pause(bool enable) { ASSERT_MAIN_THREAD; - const bool oldstate = SDL_GetAudioDeviceStatus(myDevice) == SDL_AUDIO_PAUSED; + const bool wasPaused = SDL_GetAudioDeviceStatus(myDevice) == SDL_AUDIO_PAUSED; if(myIsInitializedFlag) { - SDL_PauseAudioDevice(myDevice, state ? 1 : 0); - myWavHandler.pause(state); + SDL_PauseAudioDevice(myDevice, enable ? 1 : 0); + myWavHandler.pause(enable); } - return oldstate; + return wasPaused; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -386,7 +373,7 @@ void SoundSDL2::callback(void* object, uInt8* stream, int len) const uInt32 length = len >> 2; self->myResampler->fillFragment(s, length); - for(uInt32 i = 0; i < length; ++i) // TODO - perhaps move into Resampler + for(uInt32 i = 0; i < length; ++i) s[i] *= SoundSDL2::myVolumeFactor; } else @@ -452,8 +439,9 @@ bool SoundSDL2::WavHandlerSDL2::play( myDevice = SDL_OpenAudioDevice(device, 0, &mySpec, nullptr, 0); if(!myDevice) return false; + // Play audio - SDL_PauseAudioDevice(myDevice, 0); + pause(false); } return true; } diff --git a/src/common/SoundSDL2.hxx b/src/common/SoundSDL2.hxx index 016d1a612..d477dc88b 100644 --- a/src/common/SoundSDL2.hxx +++ b/src/common/SoundSDL2.hxx @@ -66,19 +66,13 @@ class SoundSDL2 : public Sound EmulationTiming* emulationTiming) override; /** - Should be called to close the sound device. Once called the sound - device can be started again using the open method. - */ - void close() override; + Sets the sound mute state; sound processing continues. When enabled, + sound volume is 0; when disabled, sound volume returns to previously + set level. - /** - Sets the sound mute state; sound processing continues. When turned - off, sound volume is 0; when turned on, sound volume returns to - previously set level. - - @param state Mutes sound if true, unmute if false + @param enable Mutes sound if true, unmute if false */ - void mute(bool state) override; + void mute(bool enable) override; /** Toggles the sound mute state; sound processing continues. @@ -91,11 +85,11 @@ class SoundSDL2 : public Sound neither played nor processed (ie, the sound subsystem is temporarily disabled). - @param state Pause sound if true, unpause if false + @param enable Pause sound if true, unpause if false @return The previous (old) pause state */ - bool pause(bool state) override; + bool pause(bool enable) override; /** Sets the volume of the sound device to the specified level. The diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 95064c502..c19d20bdb 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -250,10 +250,12 @@ Console::~Console() myLeftControl->close(); myRightControl->close(); - // Close audio to prevent invalid access to myConsoleTiming from the audio - // callback - myOSystem.sound().close(); - myOSystem.sound().stopWav(); + // Close audio to prevent invalid access in the audio callback + if(myAudioQueue) + { + myAudioQueue->closeSink(nullptr); // TODO: is this needed? + myAudioQueue.reset(); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -335,12 +337,10 @@ void Console::redetectFrameLayout() { Serializer s; - myOSystem.sound().close(); save(s); - autodetectFrameLayout(false); - load(s); + initializeAudio(); } @@ -691,8 +691,6 @@ FBInitStatus Console::initializeVideo(bool full) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::initializeAudio() { - myOSystem.sound().close(); - myEmulationTiming .updatePlaybackRate(myAudioSettings.sampleRate()) .updatePlaybackPeriod(myAudioSettings.fragmentSize()) diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 11ebdd3f0..ff182a041 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -572,7 +572,7 @@ bool OSystem::createLauncher(const string& startdir) closeConsole(); if(mySound) - mySound->close(); + mySound->pause(true); mySettings->setValue("tmpromdir", startdir); bool status = false; diff --git a/src/emucore/Sound.hxx b/src/emucore/Sound.hxx index 6e5543205..29ff70278 100644 --- a/src/emucore/Sound.hxx +++ b/src/emucore/Sound.hxx @@ -55,12 +55,6 @@ class Sound */ virtual void open(shared_ptr, EmulationTiming*) = 0; - /** - Should be called to stop the sound system. Once called the sound - device can be started again using the ::open() method. - */ - virtual void close() = 0; - /** Sets the sound mute state; sound processing continues. When turned off, sound volume is 0; when turned on, sound volume returns to diff --git a/src/os/libretro/SoundLIBRETRO.hxx b/src/os/libretro/SoundLIBRETRO.hxx index aa20237f2..8c1485b3d 100644 --- a/src/os/libretro/SoundLIBRETRO.hxx +++ b/src/os/libretro/SoundLIBRETRO.hxx @@ -80,22 +80,6 @@ class SoundLIBRETRO : public Sound myIsInitializedFlag = true; } - /** - Should be called to close the sound device. Once called the sound - device can be started again using the open method. - */ - void close() override - { - if (!myIsInitializedFlag) - return; - if (myAudioQueue) - myAudioQueue->closeSink(myCurrentFragment); - myAudioQueue.reset(); - myCurrentFragment = nullptr; - - Logger::debug("SoundLIBRETRO::close"); - } - /** Empties the playback buffer. From dc888cf888cfeeda302fca666adfe7b35f63dc28 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sun, 9 Oct 2022 21:50:57 -0230 Subject: [PATCH 2/3] Fix minor warning from clang-tidy. --- src/emucore/PlusROM.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emucore/PlusROM.cxx b/src/emucore/PlusROM.cxx index ccc3c1e2e..9ccb8117d 100644 --- a/src/emucore/PlusROM.cxx +++ b/src/emucore/PlusROM.cxx @@ -99,7 +99,7 @@ class PlusROMRequest { client.set_write_timeout(milliseconds(WRITE_TIMEOUT_MSEC)); auto response = client.Post( - myDestination.path.c_str(), + myDestination.path, headers, reinterpret_cast(myRequest.data()), myRequestSize, From 8ff021d1f8a8ebf27e1578aa712473e7efe6fc28 Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Mon, 10 Oct 2022 19:15:55 +0200 Subject: [PATCH 3/3] Add a GitHub action to build on Linux and macOS (#935) As with Travis CI, the test is only deemed successful on each platform if the Stella build completes successfully. For Linux, the test runs on Ubuntu with the toolchain test build repository, using G++ 9, and the packaged version of SDL2, which is guaranteed to be at least 2.0.10. For macOS, SDL2 2.0.10 is still built from the upstream source code; however that no longer builds with the newer Xcode versions available in GHAs, so the build now uses "Unix-style" ./configure && make. The runners provide two cores on Linux and three cores on macOS, so the compile stages use the appropriate -j setting to build in parallel. Signed-off-by: Stephen Kitt Signed-off-by: Stephen Kitt --- .github/workflows/build.yml | 39 +++++++++++++++++++++++ .travis.yml | 63 ------------------------------------- 2 files changed, 39 insertions(+), 63 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..f5dd58cab --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,39 @@ +--- +name: Build + +on: + pull_request: + +permissions: {} + +jobs: + linux: + name: Linux + runs-on: ubuntu-latest + steps: + - name: Check out the repository + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - name: Install GCC 9 and SDL2 + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo apt update + sudo apt install g++-9 libsdl2-dev + - name: Build Stella + run: | + ./configure && make -j2 all + + macos: + name: macOS + runs-on: macos-latest + steps: + - name: Check out the repository + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - name: Install SDL2 + run: | + curl https://www.libsdl.org/release/SDL2-2.0.10.tar.gz | tar xzf - + mkdir SDL2-2.0.10/build + cd SDL2-2.0.10/build + ../configure && make -j3 && sudo make install + - name: Build Stella + run: | + ./configure && make -j3 all diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bca11dee4..000000000 --- a/.travis.yml +++ /dev/null @@ -1,63 +0,0 @@ -# Build matrix / environment variables are explained on: -# http://about.travis-ci.org/docs/user/build-configuration/ -# This file can be validated on: http://lint.travis-ci.org/ - - -language: cpp - - -matrix: - include: - - os: linux - dist: xenial - compiler: gcc - env: GCC=9 CC=gcc-9 CXX=g++-9 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-9 - - g++-9 - update: true - - - - os: osx - osx_image: xcode11.3 - compiler: clang - addons: - homebrew: - update: true - - -install: - - | - old_cwd=$(pwd) - cd ~ - - if [[ "$HOST" == macosx-* ]]; then - curl -O https://www.libsdl.org/release/SDL2-2.0.10.tar.gz - tar xzf SDL2-2.0.10.tar.gz - cd SDL2-2.0.10/Xcode/SDL - sed -i -e 's/@rpath//g' SDL.xcodeproj/project.pbxproj - xcodebuild -configuration Release - mkdir -p ~/Library/Frameworks/ - ln -s `pwd`/build/Release/SDL2.framework ~/Library/Frameworks/ - else - curl -O https://www.libsdl.org/release/SDL2-2.0.10.tar.gz - tar xzf SDL2-2.0.10.tar.gz - cd SDL2-2.0.10 - mkdir build - cd build - ../configure - make - sudo make install - fi - - cd $old_cwd - - -script: - - | - ./configure - make all