Ladybird: Detect changes to the default audio device

When the default audio device changes on the host, it's convenient to
automatically switch to that device rather than needing to reload the
page to update.
This commit is contained in:
Timothy Flynn 2023-06-21 10:16:42 -04:00 committed by Andreas Kling
parent 8f927eaa68
commit 33dbfa3281
Notes: sideshowbarker 2024-07-17 22:09:47 +09:00

View file

@ -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<QAudioSink>(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<QAudioSink> audio_output;
QIODevice* io_device { nullptr };
private:
explicit AudioDevice(NonnullOwnPtr<QAudioSink> output)
: audio_output(move(output))
{
io_device = audio_output->start();
}
};
void run() override
{
auto devices = make<QMediaDevices>();
auto const& device_info = devices->defaultAudioOutput();
auto audio_device = AudioDevice::create();
auto format = device_info.preferredFormat();
format.setChannelCount(2);
auto audio_output = make<QAudioSink>(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;
}
}