<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[238609] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/238609">238609</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2018-11-28 06:56:11 -0800 (Wed, 28 Nov 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WebRTC][GStreamer] Make sure to have the default microphone on the top of the list
https://bugs.webkit.org/show_bug.cgi?id=192026

Patch by Thibault Saunier <tsaunier@igalia.com> on 2018-11-28
Reviewed by Philippe Normand.

Otherwise we might end up picking a useless one in some applications
(not sure what those application do though).

GStreamer patch proposed as https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/merge_requests/34/diffs

Source/WebCore:

* platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp:
(WebCore::sortDevices):
(WebCore::GStreamerCaptureDeviceManager::addDevice):
(WebCore::GStreamerCaptureDeviceManager::refreshCaptureDevices):
* platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.h:

Tools:

* flatpak/org.webkit.CommonModules.yaml:
* gstreamer/jhbuild.modules:
* gstreamer/patches/gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamgstreamerGStreamerCaptureDeviceManagercpp">trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmediastreamgstreamerGStreamerCaptureDeviceManagerh">trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsflatpakorgwebkitCommonModulesyaml">trunk/Tools/flatpak/org.webkit.CommonModules.yaml</a></li>
<li><a href="#trunkToolsgstreamerjhbuildmodules">trunk/Tools/gstreamer/jhbuild.modules</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkToolsgstreamerpatchesgstpluginsgood0014pulseMarkdefaultdevicesasdefaultpatch">trunk/Tools/gstreamer/patches/gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (238608 => 238609)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2018-11-28 13:50:42 UTC (rev 238608)
+++ trunk/Source/WebCore/ChangeLog      2018-11-28 14:56:11 UTC (rev 238609)
</span><span class="lines">@@ -1,5 +1,23 @@
</span><span class="cx"> 2018-11-28  Thibault Saunier  <tsaunier@igalia.com>
</span><span class="cx"> 
</span><ins>+        [WebRTC][GStreamer] Make sure to have the default microphone on the top of the list
+        https://bugs.webkit.org/show_bug.cgi?id=192026
+
+        Reviewed by Philippe Normand.
+
+        Otherwise we might end up picking a useless one in some applications
+        (not sure what those application do though).
+
+        GStreamer patch proposed as https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/merge_requests/34/diffs
+
+        * platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp:
+        (WebCore::sortDevices):
+        (WebCore::GStreamerCaptureDeviceManager::addDevice):
+        (WebCore::GStreamerCaptureDeviceManager::refreshCaptureDevices):
+        * platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.h:
+
+2018-11-28  Thibault Saunier  <tsaunier@igalia.com>
+
</ins><span class="cx">         [WebRTC][GStreamer] Tag all cameras with as 'Unknown' facing mode
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=192028
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamgstreamerGStreamerCaptureDeviceManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp (238608 => 238609)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp    2018-11-28 13:50:42 UTC (rev 238608)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp       2018-11-28 14:56:11 UTC (rev 238609)
</span><span class="lines">@@ -28,6 +28,26 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+static gint sortDevices(gconstpointer a, gconstpointer b)
+{
+    GstDevice* adev = GST_DEVICE(a), *bdev = GST_DEVICE(b);
+    GUniquePtr<GstStructure> aprops(gst_device_get_properties(adev));
+    GUniquePtr<GstStructure> bprops(gst_device_get_properties(bdev));
+    gboolean aIsDefault = FALSE, bIsDefault = FALSE;
+
+    gst_structure_get_boolean(aprops.get(), "is-default", &aIsDefault);
+    gst_structure_get_boolean(bprops.get(), "is-default", &bIsDefault);
+
+    if (aIsDefault == bIsDefault) {
+        GUniquePtr<char> aName(gst_device_get_display_name(adev));
+        GUniquePtr<char> bName(gst_device_get_display_name(bdev));
+
+        return g_strcmp0(aName.get(), bName.get());
+    }
+
+    return aIsDefault > bIsDefault ? -1 : 1;
+}
+
</ins><span class="cx"> GStreamerAudioCaptureDeviceManager& GStreamerAudioCaptureDeviceManager::singleton()
</span><span class="cx"> {
</span><span class="cx">     static NeverDestroyed<GStreamerAudioCaptureDeviceManager> manager;
</span><span class="lines">@@ -66,7 +86,7 @@
</span><span class="cx">     return m_devices;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void GStreamerCaptureDeviceManager::deviceAdded(GRefPtr<GstDevice>&& device)
</del><ins>+void GStreamerCaptureDeviceManager::addDevice(GRefPtr<GstDevice>&& device)
</ins><span class="cx"> {
</span><span class="cx">     GUniquePtr<GstStructure> properties(gst_device_get_properties(device.get()));
</span><span class="cx">     const char* klass = gst_structure_get_string(properties.get(), "device.class");
</span><span class="lines">@@ -85,8 +105,11 @@
</span><span class="cx">     // This isn't really a UID but should be good enough (libwebrtc
</span><span class="cx">     // itself does that at least for pulseaudio devices).
</span><span class="cx">     GUniquePtr<char> deviceName(gst_device_get_display_name(device.get()));
</span><del>-    String identifier = String::fromUTF8(deviceName.get());
</del><ins>+    gboolean isDefault = FALSE;
+    gst_structure_get_boolean(properties.get(), "is-default", &isDefault);
</ins><span class="cx"> 
</span><ins>+    String identifier = String::format("%s%s", isDefault ? "default: " : "", deviceName.get());
+
</ins><span class="cx">     auto gstCaptureDevice = GStreamerCaptureDevice(WTFMove(device), identifier, type, identifier);
</span><span class="cx">     gstCaptureDevice.setEnabled(true);
</span><span class="cx">     m_gstreamerDevices.append(WTFMove(gstCaptureDevice));
</span><span class="lines">@@ -120,10 +143,11 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    GList* devices = gst_device_monitor_get_devices(m_deviceMonitor.get());
</del><ins>+    GList* devices = g_list_sort(gst_device_monitor_get_devices(m_deviceMonitor.get()), sortDevices);
</ins><span class="cx">     while (devices) {
</span><span class="cx">         GRefPtr<GstDevice> device = adoptGRef(GST_DEVICE_CAST(devices->data));
</span><del>-        deviceAdded(WTFMove(device));
</del><ins>+
+        addDevice(WTFMove(device));
</ins><span class="cx">         devices = g_list_delete_link(devices, devices);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmediastreamgstreamerGStreamerCaptureDeviceManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.h (238608 => 238609)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.h      2018-11-28 13:50:42 UTC (rev 238608)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.h 2018-11-28 14:56:11 UTC (rev 238609)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     virtual CaptureDevice::DeviceType deviceType() = 0;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    void deviceAdded(GRefPtr<GstDevice>&&);
</del><ins>+    void addDevice(GRefPtr<GstDevice>&&);
</ins><span class="cx">     void refreshCaptureDevices();
</span><span class="cx"> 
</span><span class="cx">     GRefPtr<GstDeviceMonitor> m_deviceMonitor;
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (238608 => 238609)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2018-11-28 13:50:42 UTC (rev 238608)
+++ trunk/Tools/ChangeLog       2018-11-28 14:56:11 UTC (rev 238609)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2018-11-28  Thibault Saunier  <tsaunier@igalia.com>
+
+        [WebRTC][GStreamer] Make sure to have the default microphone on the top of the list
+        https://bugs.webkit.org/show_bug.cgi?id=192026
+
+        Reviewed by Philippe Normand.
+
+        Otherwise we might end up picking a useless one in some applications
+        (not sure what those application do though).
+
+        GStreamer patch proposed as https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/merge_requests/34/diffs
+
+        * flatpak/org.webkit.CommonModules.yaml:
+        * gstreamer/jhbuild.modules:
+        * gstreamer/patches/gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch: Added.
+
</ins><span class="cx"> 2018-11-28  Tomas Popela  <tpopela@redhat.com>
</span><span class="cx"> 
</span><span class="cx">         [GTK] Silence compilation warnings in glib unittests
</span></span></pre></div>
<a id="trunkToolsflatpakorgwebkitCommonModulesyaml"></a>
<div class="modfile"><h4>Modified: trunk/Tools/flatpak/org.webkit.CommonModules.yaml (238608 => 238609)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/flatpak/org.webkit.CommonModules.yaml        2018-11-28 13:50:42 UTC (rev 238608)
+++ trunk/Tools/flatpak/org.webkit.CommonModules.yaml   2018-11-28 14:56:11 UTC (rev 238609)
</span><span class="lines">@@ -171,6 +171,8 @@
</span><span class="cx">       path: ../gstreamer/patches/gst-plugins-good-0012-matroskdemux-do-not-use-MapInfo.data-after-unmapping.patch
</span><span class="cx">     - type: patch
</span><span class="cx">       path: ../gstreamer/patches/gst-plugins-good-0013-Avoid-warning-when-reporting-about-decryptors.patch
</span><ins>+    - type: patch
+      path: ../gstreamer/patches/gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch
</ins><span class="cx">   config-opts:
</span><span class="cx">     - -Ddisable_gtkdoc=true
</span><span class="cx"> - name: x264
</span></span></pre></div>
<a id="trunkToolsgstreamerjhbuildmodules"></a>
<div class="modfile"><h4>Modified: trunk/Tools/gstreamer/jhbuild.modules (238608 => 238609)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/gstreamer/jhbuild.modules    2018-11-28 13:50:42 UTC (rev 238608)
+++ trunk/Tools/gstreamer/jhbuild.modules       2018-11-28 14:56:11 UTC (rev 238609)
</span><span class="lines">@@ -90,6 +90,7 @@
</span><span class="cx">       <patch file="gst-plugins-good-0011-matroska-Add-the-WebM-encrypted-content-support-in-m.patch" strip="1" /> <!-- Merged as 0432826950d4d80fe2b50ffd3757dc08155de9e3 -->
</span><span class="cx">       <patch file="gst-plugins-good-0012-matroskdemux-do-not-use-MapInfo.data-after-unmapping.patch" strip="1" /> <!-- Merged as defae350358660e557c74e41a4fe8a8bb327e9c8 -->
</span><span class="cx">       <patch file="gst-plugins-good-0013-Avoid-warning-when-reporting-about-decryptors.patch" strip="1" /> <!-- Merged as 56669205eb2d0887596574eabb7806b31c5ba5cf -->
</span><ins>+      <patch file="gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch" strip="1" />
</ins><span class="cx">     </branch>
</span><span class="cx">   </autotools>
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsgstreamerpatchesgstpluginsgood0014pulseMarkdefaultdevicesasdefaultpatch"></a>
<div class="addfile"><h4>Added: trunk/Tools/gstreamer/patches/gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch (0 => 238609)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/gstreamer/patches/gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch                          (rev 0)
+++ trunk/Tools/gstreamer/patches/gst-plugins-good-0014-pulse-Mark-default-devices-as-default.patch     2018-11-28 14:56:11 UTC (rev 238609)
</span><span class="lines">@@ -0,0 +1,318 @@
</span><ins>+From 32c833ebb42b8e8f46c5a72a16a874bc00fc5553 Mon Sep 17 00:00:00 2001
+From: Thibault Saunier <tsaunier@igalia.com>
+Date: Mon, 26 Nov 2018 13:48:56 -0300
+Subject: [PATCH] pulse: Mark default devices as "default"
+
+---
+ ext/pulse/pulsedeviceprovider.c | 117 +++++++++++++++++++++-----------
+ ext/pulse/pulsedeviceprovider.h |   3 +
+ 2 files changed, 79 insertions(+), 41 deletions(-)
+
+diff --git a/ext/pulse/pulsedeviceprovider.c b/ext/pulse/pulsedeviceprovider.c
+index a1964dab2..9b66a0e33 100644
+--- a/ext/pulse/pulsedeviceprovider.c
++++ b/ext/pulse/pulsedeviceprovider.c
+@@ -40,7 +40,7 @@ GST_DEBUG_CATEGORY_EXTERN (pulse_debug);

+ static GstDevice *gst_pulse_device_new (guint id,
+     const gchar * device_name, GstCaps * caps, const gchar * internal_name,
+-    GstPulseDeviceType type, GstStructure * properties);
++    GstPulseDeviceType type, GstStructure * properties, gboolean is_default);

+ G_DEFINE_TYPE (GstPulseDeviceProvider, gst_pulse_device_provider,
+     GST_TYPE_DEVICE_PROVIDER);
+@@ -65,6 +65,12 @@ enum
+ };


++typedef struct
++{
++  GList *devices;
++  GstPulseDeviceProvider *self;
++} ListDevicesData;
++
+ static void
+ gst_pulse_device_provider_class_init (GstPulseDeviceProviderClass * klass)
+ {
+@@ -114,6 +120,8 @@ gst_pulse_device_provider_finalize (GObject * object)

+   g_free (self->client_name);
+   g_free (self->server);
++  g_free (self->default_sink_name);
++  g_free (self->default_source_name);

+   G_OBJECT_CLASS (gst_pulse_device_provider_parent_class)->finalize (object);
+ }
+@@ -186,7 +194,7 @@ context_state_cb (pa_context * c, void *userdata)
+ }

+ static GstDevice *
+-new_source (const pa_source_info * info)
++new_source (GstPulseDeviceProvider * self, const pa_source_info * info)
+ {
+   GstCaps *caps;
+   GstStructure *props;
+@@ -200,11 +208,12 @@ new_source (const pa_source_info * info)
+   props = gst_pulse_make_structure (info->proplist);

+   return gst_pulse_device_new (info->index, info->description,
+-      caps, info->name, GST_PULSE_DEVICE_TYPE_SOURCE, props);
++      caps, info->name, GST_PULSE_DEVICE_TYPE_SOURCE, props,
++      !g_strcmp0 (info->name, self->default_source_name));
+ }

+ static GstDevice *
+-new_sink (const pa_sink_info * info)
++new_sink (GstPulseDeviceProvider * self, const pa_sink_info * info)
+ {
+   GstCaps *caps;
+   GstStructure *props;
+@@ -218,7 +227,8 @@ new_sink (const pa_sink_info * info)
+   props = gst_pulse_make_structure (info->proplist);

+   return gst_pulse_device_new (info->index, info->description,
+-      caps, info->name, GST_PULSE_DEVICE_TYPE_SINK, props);
++      caps, info->name, GST_PULSE_DEVICE_TYPE_SINK, props,
++      !g_strcmp0 (info->name, self->default_sink_name));
+ }

+ static void
+@@ -233,12 +243,26 @@ get_source_info_cb (pa_context * context,
+     return;
+   }

+-  dev = new_source (info);
++  dev = new_source (self, info);

+   if (dev)
+     gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), dev);
+ }

++static void
++get_server_info_cb (pa_context * context, const pa_server_info * info,
++    void *userdata)
++{
++  GstPulseDeviceProvider *self = userdata;
++
++  g_free (self->default_sink_name);
++  g_free (self->default_source_name);
++  self->default_sink_name = g_strdup (info->default_sink_name);
++  self->default_source_name = g_strdup (info->default_source_name);
++
++  pa_threaded_mainloop_signal (self->mainloop, 0);
++}
++
+ static void
+ get_sink_info_cb (pa_context * context,
+     const pa_sink_info * info, int eol, void *userdata)
+@@ -251,7 +275,7 @@ get_sink_info_cb (pa_context * context,
+     return;
+   }

+-  dev = new_sink (info);
++  dev = new_sink (self, info);

+   if (dev)
+     gst_device_provider_device_add (GST_DEVICE_PROVIDER (self), dev);
+@@ -312,34 +336,38 @@ static void
+ get_source_info_list_cb (pa_context * context, const pa_source_info * info,
+     int eol, void *userdata)
+ {
+-  GList **devices = userdata;
++  ListDevicesData *data = userdata;

+   if (eol)
+     return;

+-  *devices = g_list_prepend (*devices, gst_object_ref_sink (new_source (info)));
++  data->devices =
++      g_list_prepend (data->devices,
++      gst_object_ref_sink (new_source (data->self, info)));
+ }

+ static void
+ get_sink_info_list_cb (pa_context * context, const pa_sink_info * info,
+     int eol, void *userdata)
+ {
+-  GList **devices = userdata;
++  ListDevicesData *data = userdata;

+   if (eol)
+     return;

+-  *devices = g_list_prepend (*devices, gst_object_ref_sink (new_sink (info)));
++  data->devices =
++      g_list_prepend (data->devices, gst_object_ref_sink (new_sink (data->self,
++              info)));
+ }

+ static GList *
+ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
+ {
+   GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
+-  GList *devices = NULL;
+   pa_mainloop *m = NULL;
+   pa_context *c = NULL;
+   pa_operation *o;
++  ListDevicesData data = { NULL, self };

+   if (!(m = pa_mainloop_new ()))
+     return NULL;
+@@ -376,7 +404,7 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
+   }
+   GST_DEBUG_OBJECT (self, "connected");

+-  o = pa_context_get_sink_info_list (c, get_sink_info_list_cb, &devices);
++  o = pa_context_get_sink_info_list (c, get_sink_info_list_cb, &data);
+   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING &&
+       pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
+     if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
+@@ -384,7 +412,7 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
+   }
+   pa_operation_unref (o);

+-  o = pa_context_get_source_info_list (c, get_source_info_list_cb, &devices);
++  o = pa_context_get_source_info_list (c, get_source_info_list_cb, &data);
+   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING &&
+       pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
+     if (pa_mainloop_iterate (m, TRUE, NULL) < 0)
+@@ -395,18 +423,38 @@ gst_pulse_device_provider_probe (GstDeviceProvider * provider)
+   pa_context_disconnect (c);
+   pa_mainloop_free (m);

+-  return devices;
++  return data.devices;

+ failed:

+   return NULL;
+ }

++static gboolean
++run_pulse_operation (GstPulseDeviceProvider * self, pa_operation * operation)
++{
++  if (!operation)
++    return FALSE;
++
++  while (pa_operation_get_state (operation) == PA_OPERATION_RUNNING) {
++    if (!PA_CONTEXT_IS_GOOD (pa_context_get_state ((self->context)))) {
++      pa_operation_cancel (operation);
++      pa_operation_unref (operation);
++      return FALSE;
++    }
++
++    pa_threaded_mainloop_wait (self->mainloop);
++  }
++
++  pa_operation_unref (operation);
++
++  return TRUE;
++}
++
+ static gboolean
+ gst_pulse_device_provider_start (GstDeviceProvider * provider)
+ {
+   GstPulseDeviceProvider *self = GST_PULSE_DEVICE_PROVIDER (provider);
+-  pa_operation *initial_operation;

+   if (!(self->mainloop = pa_threaded_mainloop_new ())) {
+     GST_ERROR_OBJECT (self, "Could not create pulseaudio mainloop");
+@@ -462,27 +510,18 @@ gst_pulse_device_provider_start (GstDeviceProvider * provider)
+   pa_context_subscribe (self->context,
+       PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SINK, NULL, NULL);

+-  initial_operation = pa_context_get_source_info_list (self->context,
+-      get_source_info_cb, self);
+-  while (pa_operation_get_state (initial_operation) == PA_OPERATION_RUNNING) {
+-    if (!PA_CONTEXT_IS_GOOD (pa_context_get_state ((self->context))))
+-      goto cancel_and_fail;
+-
+-    pa_threaded_mainloop_wait (self->mainloop);
+-  }
+-  pa_operation_unref (initial_operation);
++  if (!run_pulse_operation (self, pa_context_get_server_info (self->context,
++              get_server_info_cb, self)))
++    goto unlock_and_fail;

+-  initial_operation = pa_context_get_sink_info_list (self->context,
+-      get_sink_info_cb, self);
+-  if (!initial_operation)
++  if (!run_pulse_operation (self,
++          pa_context_get_source_info_list (self->context, get_source_info_cb,
++              self)))
+     goto unlock_and_fail;
+-  while (pa_operation_get_state (initial_operation) == PA_OPERATION_RUNNING) {
+-    if (!PA_CONTEXT_IS_GOOD (pa_context_get_state ((self->context))))
+-      goto cancel_and_fail;

+-    pa_threaded_mainloop_wait (self->mainloop);
+-  }
+-  pa_operation_unref (initial_operation);
++  if (!run_pulse_operation (self, pa_context_get_sink_info_list (self->context,
++              get_sink_info_cb, self)))
++    goto unlock_and_fail;

+   pa_threaded_mainloop_unlock (self->mainloop);

+@@ -495,11 +534,6 @@ unlock_and_fail:

+ mainloop_failed:
+   return FALSE;
+-
+-cancel_and_fail:
+-  pa_operation_cancel (initial_operation);
+-  pa_operation_unref (initial_operation);
+-  goto unlock_and_fail;
+ }

+ static void
+@@ -611,7 +645,7 @@ gst_pulse_device_reconfigure_element (GstDevice * device, GstElement * element)
+ static GstDevice *
+ gst_pulse_device_new (guint device_index, const gchar * device_name,
+     GstCaps * caps, const gchar * internal_name, GstPulseDeviceType type,
+-    GstStructure * props)
++    GstStructure * props, gboolean is_default)
+ {
+   GstPulseDevice *gstdev;
+   const gchar *element = NULL;
+@@ -636,7 +670,7 @@ gst_pulse_device_new (guint device_index, const gchar * device_name,
+       break;
+   }

+-
++  gst_structure_set (props, "is-default", G_TYPE_BOOLEAN, is_default, NULL);
+   gstdev = g_object_new (GST_TYPE_PULSE_DEVICE,
+       "display-name", device_name, "caps", caps, "device-class", klass,
+       "internal-name", internal_name, "properties", props, NULL);
+@@ -644,6 +678,7 @@ gst_pulse_device_new (guint device_index, const gchar * device_name,
+   gstdev->type = type;
+   gstdev->device_index = device_index;
+   gstdev->element = element;
++  gstdev->is_default = is_default;

+   gst_structure_free (props);
+   gst_caps_unref (caps);
+diff --git a/ext/pulse/pulsedeviceprovider.h b/ext/pulse/pulsedeviceprovider.h
+index 0892ad586..7bcd1bc47 100644
+--- a/ext/pulse/pulsedeviceprovider.h
++++ b/ext/pulse/pulsedeviceprovider.h
+@@ -50,6 +50,8 @@ struct _GstPulseDeviceProvider {

+   gchar *server;
+   gchar *client_name;
++  gchar *default_source_name;
++  gchar *default_sink_name;

+   pa_threaded_mainloop *mainloop;
+   pa_context *context;
+@@ -84,6 +86,7 @@ struct _GstPulseDevice {
+   GstPulseDeviceType type;
+   guint             device_index;
+   gchar            *internal_name;
++  gboolean         is_default;
+   const gchar      *element;
+ };

+-- 
+2.19.1
+
</ins></span></pre>
</div>
</div>

</body>
</html>