Remove pause callbacks from coretiming
This commit is contained in:
		| @@ -47,16 +47,6 @@ AudioRenderer::ADSP::ADSP& AudioCore::GetADSP() { | ||||
|     return *adsp; | ||||
| } | ||||
|  | ||||
| void AudioCore::PauseSinks(const bool pausing) const { | ||||
|     if (pausing) { | ||||
|         output_sink->PauseStreams(); | ||||
|         input_sink->PauseStreams(); | ||||
|     } else { | ||||
|         output_sink->UnpauseStreams(); | ||||
|         input_sink->UnpauseStreams(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void AudioCore::SetNVDECActive(bool active) { | ||||
|     nvdec_active = active; | ||||
| } | ||||
|   | ||||
| @@ -57,14 +57,6 @@ public: | ||||
|      */ | ||||
|     AudioRenderer::ADSP::ADSP& GetADSP(); | ||||
|  | ||||
|     /** | ||||
|      * Pause the sink. Called from the core. | ||||
|      * | ||||
|      * @param pausing - Is this pause due to an actual pause, or shutdown? | ||||
|      *                  Unfortunately, shutdown also pauses streams, which can cause issues. | ||||
|      */ | ||||
|     void PauseSinks(bool pausing) const; | ||||
|  | ||||
|     /** | ||||
|      * Toggle NVDEC state, used to avoid stall in playback. | ||||
|      * | ||||
|   | ||||
| @@ -22,9 +22,7 @@ SystemManager::SystemManager(Core::System& core_) | ||||
|       thread_event{Core::Timing::CreateEvent( | ||||
|           "AudioRendererSystemManager", [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) { | ||||
|               return ThreadFunc2(time); | ||||
|           })} { | ||||
|     core.CoreTiming().RegisterPauseCallback([this](bool paused) { PauseCallback(paused); }); | ||||
| } | ||||
|           })} {} | ||||
|  | ||||
| SystemManager::~SystemManager() { | ||||
|     Stop(); | ||||
| @@ -125,11 +123,4 @@ std::optional<std::chrono::nanoseconds> SystemManager::ThreadFunc2(s64 time) { | ||||
|     return std::nullopt; | ||||
| } | ||||
|  | ||||
| void SystemManager::PauseCallback(bool paused) { | ||||
|     if (paused && core.IsPoweredOn() && core.IsShuttingDown()) { | ||||
|         update.store(true); | ||||
|         update.notify_all(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace AudioCore::AudioRenderer | ||||
|   | ||||
| @@ -73,13 +73,6 @@ private: | ||||
|      */ | ||||
|     std::optional<std::chrono::nanoseconds> ThreadFunc2(s64 time); | ||||
|  | ||||
|     /** | ||||
|      * Callback from core timing when pausing, used to detect shutdowns and stop ThreadFunc. | ||||
|      * | ||||
|      * @param paused - Are we pausing or resuming? | ||||
|      */ | ||||
|     void PauseCallback(bool paused); | ||||
|  | ||||
|     enum class StreamState { | ||||
|         Filling, | ||||
|         Steady, | ||||
| @@ -106,8 +99,6 @@ private: | ||||
|     std::shared_ptr<Core::Timing::EventType> thread_event; | ||||
|     /// Atomic for main thread to wait on | ||||
|     std::atomic<bool> update{}; | ||||
|     /// Current state of the streams | ||||
|     StreamState state{StreamState::Filling}; | ||||
| }; | ||||
|  | ||||
| } // namespace AudioCore::AudioRenderer | ||||
|   | ||||
| @@ -129,21 +129,14 @@ public: | ||||
|      *                 Default false. | ||||
|      */ | ||||
|     void Start(bool resume = false) override { | ||||
|         if (!ctx) { | ||||
|         if (!ctx || !paused) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (resume && was_playing) { | ||||
|         paused = false; | ||||
|         if (cubeb_stream_start(stream_backend) != CUBEB_OK) { | ||||
|             LOG_CRITICAL(Audio_Sink, "Error starting cubeb stream"); | ||||
|         } | ||||
|             paused = false; | ||||
|         } else if (!resume) { | ||||
|             if (cubeb_stream_start(stream_backend) != CUBEB_OK) { | ||||
|                 LOG_CRITICAL(Audio_Sink, "Error starting cubeb stream"); | ||||
|             } | ||||
|             paused = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -151,16 +144,15 @@ public: | ||||
|      */ | ||||
|     void Stop() override { | ||||
|         Unstall(); | ||||
|         if (!ctx) { | ||||
|  | ||||
|         if (!ctx || paused) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         paused = true; | ||||
|         if (cubeb_stream_stop(stream_backend) != CUBEB_OK) { | ||||
|             LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream"); | ||||
|         } | ||||
|  | ||||
|         was_playing.store(!paused); | ||||
|         paused = true; | ||||
|     } | ||||
|  | ||||
| private: | ||||
| @@ -286,18 +278,6 @@ void CubebSink::CloseStreams() { | ||||
|     sink_streams.clear(); | ||||
| } | ||||
|  | ||||
| void CubebSink::PauseStreams() { | ||||
|     for (auto& stream : sink_streams) { | ||||
|         stream->Stop(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void CubebSink::UnpauseStreams() { | ||||
|     for (auto& stream : sink_streams) { | ||||
|         stream->Start(true); | ||||
|     } | ||||
| } | ||||
|  | ||||
| f32 CubebSink::GetDeviceVolume() const { | ||||
|     if (sink_streams.empty()) { | ||||
|         return 1.0f; | ||||
|   | ||||
| @@ -53,16 +53,6 @@ public: | ||||
|      */ | ||||
|     void CloseStreams() override; | ||||
|  | ||||
|     /** | ||||
|      * Pause all streams. | ||||
|      */ | ||||
|     void PauseStreams() override; | ||||
|  | ||||
|     /** | ||||
|      * Unpause all streams. | ||||
|      */ | ||||
|     void UnpauseStreams() override; | ||||
|  | ||||
|     /** | ||||
|      * Get the device volume. Set from calls to the IAudioDevice service. | ||||
|      * | ||||
|   | ||||
| @@ -44,8 +44,6 @@ public: | ||||
|  | ||||
|     void CloseStream(SinkStream*) override {} | ||||
|     void CloseStreams() override {} | ||||
|     void PauseStreams() override {} | ||||
|     void UnpauseStreams() override {} | ||||
|     f32 GetDeviceVolume() const override { | ||||
|         return 1.0f; | ||||
|     } | ||||
|   | ||||
| @@ -108,17 +108,12 @@ public: | ||||
|      *                 Default false. | ||||
|      */ | ||||
|     void Start(bool resume = false) override { | ||||
|         if (device == 0) { | ||||
|         if (device == 0 || !paused) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (resume && was_playing) { | ||||
|             SDL_PauseAudioDevice(device, 0); | ||||
|         paused = false; | ||||
|         } else if (!resume) { | ||||
|         SDL_PauseAudioDevice(device, 0); | ||||
|             paused = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -126,11 +121,11 @@ public: | ||||
|      */ | ||||
|     void Stop() override { | ||||
|         Unstall(); | ||||
|         if (device == 0) { | ||||
|         if (device == 0 || paused) { | ||||
|             return; | ||||
|         } | ||||
|         SDL_PauseAudioDevice(device, 1); | ||||
|         paused = true; | ||||
|         SDL_PauseAudioDevice(device, 1); | ||||
|     } | ||||
|  | ||||
| private: | ||||
| @@ -207,18 +202,6 @@ void SDLSink::CloseStreams() { | ||||
|     sink_streams.clear(); | ||||
| } | ||||
|  | ||||
| void SDLSink::PauseStreams() { | ||||
|     for (auto& stream : sink_streams) { | ||||
|         stream->Stop(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void SDLSink::UnpauseStreams() { | ||||
|     for (auto& stream : sink_streams) { | ||||
|         stream->Start(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| f32 SDLSink::GetDeviceVolume() const { | ||||
|     if (sink_streams.empty()) { | ||||
|         return 1.0f; | ||||
|   | ||||
| @@ -51,16 +51,6 @@ public: | ||||
|      */ | ||||
|     void CloseStreams() override; | ||||
|  | ||||
|     /** | ||||
|      * Pause all streams. | ||||
|      */ | ||||
|     void PauseStreams() override; | ||||
|  | ||||
|     /** | ||||
|      * Unpause all streams. | ||||
|      */ | ||||
|     void UnpauseStreams() override; | ||||
|  | ||||
|     /** | ||||
|      * Get the device volume. Set from calls to the IAudioDevice service. | ||||
|      * | ||||
|   | ||||
| @@ -39,16 +39,6 @@ public: | ||||
|      */ | ||||
|     virtual void CloseStreams() = 0; | ||||
|  | ||||
|     /** | ||||
|      * Pause all streams. | ||||
|      */ | ||||
|     virtual void PauseStreams() = 0; | ||||
|  | ||||
|     /** | ||||
|      * Unpause all streams. | ||||
|      */ | ||||
|     virtual void UnpauseStreams() = 0; | ||||
|  | ||||
|     /** | ||||
|      * Create a new sink stream, kept within this sink, with a pointer returned for use. | ||||
|      * Do not free the returned pointer. When done with the stream, call CloseStream on the sink. | ||||
|   | ||||
| @@ -145,6 +145,12 @@ void SinkStream::ProcessAudioIn(std::span<const s16> input_buffer, std::size_t n | ||||
|     const std::size_t frame_size_bytes = frame_size * sizeof(s16); | ||||
|     size_t frames_written{0}; | ||||
|  | ||||
|     // If we're paused or going to shut down, we don't want to consume buffers as coretiming is | ||||
|     // paused and we'll desync, so just return. | ||||
|     if (system.IsPaused() || system.IsShuttingDown()) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (queued_buffers > max_queue_size) { | ||||
|         Stall(); | ||||
|     } | ||||
| @@ -195,6 +201,16 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz | ||||
|     const std::size_t frame_size_bytes = frame_size * sizeof(s16); | ||||
|     size_t frames_written{0}; | ||||
|  | ||||
|     // If we're paused or going to shut down, we don't want to consume buffers as coretiming is | ||||
|     // paused and we'll desync, so just play silence. | ||||
|     if (system.IsPaused() || system.IsShuttingDown()) { | ||||
|         constexpr std::array<s16, 6> silence{}; | ||||
|         for (size_t i = frames_written; i < num_frames; i++) { | ||||
|             std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes); | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // Due to many frames being queued up with nvdec (5 frames or so?), a lot of buffers also get | ||||
|     // queued up (30+) but not all at once, which causes constant stalling here, so just let the | ||||
|     // video play out without attempting to stall. | ||||
|   | ||||
| @@ -220,8 +220,6 @@ protected: | ||||
|     u32 device_channels{2}; | ||||
|     /// Is this stream currently paused? | ||||
|     std::atomic<bool> paused{true}; | ||||
|     /// Was this stream previously playing? | ||||
|     std::atomic<bool> was_playing{false}; | ||||
|     /// Name of this stream | ||||
|     std::string name{}; | ||||
|  | ||||
|   | ||||
| @@ -141,8 +141,6 @@ struct System::Impl { | ||||
|         core_timing.SyncPause(false); | ||||
|         is_paused = false; | ||||
|  | ||||
|         audio_core->PauseSinks(false); | ||||
|  | ||||
|         return status; | ||||
|     } | ||||
|  | ||||
| @@ -150,8 +148,6 @@ struct System::Impl { | ||||
|         std::unique_lock<std::mutex> lk(suspend_guard); | ||||
|         status = SystemResultStatus::Success; | ||||
|  | ||||
|         audio_core->PauseSinks(true); | ||||
|  | ||||
|         core_timing.SyncPause(true); | ||||
|         kernel.Suspend(true); | ||||
|         is_paused = true; | ||||
|   | ||||
| @@ -73,7 +73,6 @@ void CoreTiming::Shutdown() { | ||||
|     if (timer_thread) { | ||||
|         timer_thread->join(); | ||||
|     } | ||||
|     pause_callbacks.clear(); | ||||
|     ClearPendingEvents(); | ||||
|     timer_thread.reset(); | ||||
|     has_started = false; | ||||
| @@ -86,10 +85,6 @@ void CoreTiming::Pause(bool is_paused) { | ||||
|     if (!is_paused) { | ||||
|         pause_end_time = GetGlobalTimeNs().count(); | ||||
|     } | ||||
|  | ||||
|     for (auto& cb : pause_callbacks) { | ||||
|         cb(is_paused); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void CoreTiming::SyncPause(bool is_paused) { | ||||
| @@ -110,10 +105,6 @@ void CoreTiming::SyncPause(bool is_paused) { | ||||
|     if (!is_paused) { | ||||
|         pause_end_time = GetGlobalTimeNs().count(); | ||||
|     } | ||||
|  | ||||
|     for (auto& cb : pause_callbacks) { | ||||
|         cb(is_paused); | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool CoreTiming::IsRunning() const { | ||||
| @@ -219,11 +210,6 @@ void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void CoreTiming::RegisterPauseCallback(PauseCallback&& callback) { | ||||
|     std::scoped_lock lock{basic_lock}; | ||||
|     pause_callbacks.emplace_back(std::move(callback)); | ||||
| } | ||||
|  | ||||
| std::optional<s64> CoreTiming::Advance() { | ||||
|     std::scoped_lock lock{advance_lock, basic_lock}; | ||||
|     global_timer = GetGlobalTimeNs().count(); | ||||
|   | ||||
| @@ -22,7 +22,6 @@ namespace Core::Timing { | ||||
| /// A callback that may be scheduled for a particular core timing event. | ||||
| using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>( | ||||
|     std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)>; | ||||
| using PauseCallback = std::function<void(bool paused)>; | ||||
|  | ||||
| /// Contains the characteristics of a particular event. | ||||
| struct EventType { | ||||
| @@ -134,9 +133,6 @@ public: | ||||
|     /// Checks for events manually and returns time in nanoseconds for next event, threadsafe. | ||||
|     std::optional<s64> Advance(); | ||||
|  | ||||
|     /// Register a callback function to be called when coretiming pauses. | ||||
|     void RegisterPauseCallback(PauseCallback&& callback); | ||||
|  | ||||
| private: | ||||
|     struct Event; | ||||
|  | ||||
| @@ -176,8 +172,6 @@ private: | ||||
|     /// Cycle timing | ||||
|     u64 ticks{}; | ||||
|     s64 downcount{}; | ||||
|  | ||||
|     std::vector<PauseCallback> pause_callbacks{}; | ||||
| }; | ||||
|  | ||||
| /// Creates a core timing event with the given name and callback. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user