diff --git a/Ladybird/AudioCodecPluginLadybird.cpp b/Ladybird/AudioCodecPluginLadybird.cpp index 534dd4d2c16..eab2e9624e9 100644 --- a/Ladybird/AudioCodecPluginLadybird.cpp +++ b/Ladybird/AudioCodecPluginLadybird.cpp @@ -27,6 +27,7 @@ struct AudioTask { Pause, Seek, Volume, + RecreateAudioDevice, }; Type type; @@ -82,20 +83,64 @@ private: No, }; + struct AudioDevice { + static AudioDevice create() + { + auto const& device_info = QMediaDevices::defaultAudioOutput(); + + auto format = device_info.preferredFormat(); + format.setChannelCount(2); + + auto audio_output = make(device_info, format); + return AudioDevice { move(audio_output) }; + } + + AudioDevice(AudioDevice&&) = default; + + AudioDevice& operator=(AudioDevice&& device) + { + if (audio_output) { + audio_output->stop(); + io_device = nullptr; + } + + swap(audio_output, device.audio_output); + swap(io_device, device.io_device); + return *this; + } + + ~AudioDevice() + { + if (audio_output) + audio_output->stop(); + } + + OwnPtr audio_output; + QIODevice* io_device { nullptr }; + + private: + explicit AudioDevice(NonnullOwnPtr output) + : audio_output(move(output)) + { + io_device = audio_output->start(); + } + }; + void run() override { auto devices = make(); - auto const& device_info = devices->defaultAudioOutput(); + auto audio_device = AudioDevice::create(); - auto format = device_info.preferredFormat(); - format.setChannelCount(2); - - auto audio_output = make(device_info, format); - auto* io_device = audio_output->start(); + connect(devices, &QMediaDevices::audioOutputsChanged, this, [this]() { + queue_task({ AudioTask::Type::RecreateAudioDevice }).release_value_but_fixme_should_propagate_errors(); + }); auto paused = Paused::Yes; while (true) { + auto& audio_output = audio_device.audio_output; + auto* io_device = audio_device.io_device; + if (auto result = m_task_queue.dequeue(); result.is_error()) { VERIFY(result.error() == AudioTaskQueue::QueueStatus::Empty); } else { @@ -136,6 +181,10 @@ private: VERIFY(task.data.has_value()); audio_output->setVolume(*task.data); break; + + case AudioTask::Type::RecreateAudioDevice: + audio_device = AudioDevice::create(); + continue; } }