瀏覽代碼

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.
Timothy Flynn 2 年之前
父節點
當前提交
33dbfa3281
共有 1 個文件被更改,包括 55 次插入6 次删除
  1. 55 6
      Ladybird/AudioCodecPluginLadybird.cpp

+ 55 - 6
Ladybird/AudioCodecPluginLadybird.cpp

@@ -27,6 +27,7 @@ struct AudioTask {
         Pause,
         Pause,
         Seek,
         Seek,
         Volume,
         Volume,
+        RecreateAudioDevice,
     };
     };
 
 
     Type type;
     Type type;
@@ -82,20 +83,64 @@ private:
         No,
         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
     void run() override
     {
     {
         auto devices = make<QMediaDevices>();
         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;
         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;
                 }
                 }
             }
             }