mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 09:51:57 -05:00
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:
parent
8f927eaa68
commit
33dbfa3281
1 changed files with 55 additions and 6 deletions
|
@ -27,6 +27,7 @@ struct AudioTask {
|
||||||
Pause,
|
Pause,
|
||||||
Seek,
|
Seek,
|
||||||
Volume,
|
Volume,
|
||||||
|
RecreateAudioDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
|
@ -82,20 +83,64 @@ private:
|
||||||
No,
|
No,
|
||||||
};
|
};
|
||||||
|
|
||||||
void run() override
|
struct AudioDevice {
|
||||||
|
static AudioDevice create()
|
||||||
{
|
{
|
||||||
auto devices = make<QMediaDevices>();
|
auto const& device_info = QMediaDevices::defaultAudioOutput();
|
||||||
auto const& device_info = devices->defaultAudioOutput();
|
|
||||||
|
|
||||||
auto format = device_info.preferredFormat();
|
auto format = device_info.preferredFormat();
|
||||||
format.setChannelCount(2);
|
format.setChannelCount(2);
|
||||||
|
|
||||||
auto audio_output = make<QAudioSink>(device_info, format);
|
auto audio_output = make<QAudioSink>(device_info, format);
|
||||||
auto* io_device = audio_output->start();
|
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 audio_device = AudioDevice::create();
|
||||||
|
|
||||||
|
connect(devices, &QMediaDevices::audioOutputsChanged, this, [this]() {
|
||||||
|
queue_task({ AudioTask::Type::RecreateAudioDevice }).release_value_but_fixme_should_propagate_errors();
|
||||||
|
});
|
||||||
|
|
||||||
auto paused = Paused::Yes;
|
auto paused = Paused::Yes;
|
||||||
|
|
||||||
while (true) {
|
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()) {
|
if (auto result = m_task_queue.dequeue(); result.is_error()) {
|
||||||
VERIFY(result.error() == AudioTaskQueue::QueueStatus::Empty);
|
VERIFY(result.error() == AudioTaskQueue::QueueStatus::Empty);
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,6 +181,10 @@ private:
|
||||||
VERIFY(task.data.has_value());
|
VERIFY(task.data.has_value());
|
||||||
audio_output->setVolume(*task.data);
|
audio_output->setVolume(*task.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AudioTask::Type::RecreateAudioDevice:
|
||||||
|
audio_device = AudioDevice::create();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue