From eeaffe5c3da4ff720402ff6aab13e76c6c273403 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 20 Aug 2018 14:22:29 +0200
Subject: [PATCH 01/21] build: Remove bogus rpath

If anything it should be `pkglibdir`, but as it looks like nobody
lost their volume controls, it's apparently not needed at all.

https://gitlab.gnome.org/GNOME/libgnome-volume-control/merge_requests/1
---
 meson.build | 1 -
 1 file changed, 1 deletion(-)

diff --git a/subprojects/gvc/meson.build b/subprojects/gvc/meson.build
index 00121e7..9608df1 100644
--- a/subprojects/gvc/meson.build
+++ b/subprojects/gvc/meson.build
@@ -90,7 +90,6 @@ else
     sources: libgvc_gir_sources + libgvc_no_gir_sources,
     dependencies: libgvc_deps,
     c_args: c_args,
-    install_rpath: pkgdatadir,
     install_dir: pkglibdir,
     install: true
   )
-- 
2.28.0


From 172ccc40bb02b4190ead945b628aa3de9414f0a0 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Fri, 7 Sep 2018 15:31:14 +0200
Subject: [PATCH 02/21] README: Add README

Closes: #1
---
 README.md | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 README.md

diff --git a/subprojects/gvc/README.md b/subprojects/gvc/README.md
new file mode 100644
index 0000000..2fabe49
--- /dev/null
+++ b/subprojects/gvc/README.md
@@ -0,0 +1,12 @@
+# libgnome-volume-control
+
+libgnome-volume-control is a copy library that's supposed to be used as
+a git sub-module. If your project uses some of libgnome-volume-control's
+strings in a user-facing manner, don't forget to add those files to your
+POTFILES.in for translation.
+
+## Projects using libgnome-volume-control
+
+- [gnome-shell](https://gitlab.gnome.org/GNOME/gnome-shell)
+- [gnome-settings-daemon](https://gitlab.gnome.org/GNOME/gnome-settings-daemon)
+- [gnome-control-center](https://gitlab.gnome.org/GNOME/gnome-control-center)
-- 
2.28.0


From 13a4a9a5c2badae9d18b9b437573be5c65b772d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= <alberts.muktupavels@gmail.com>
Date: Sat, 8 Sep 2018 23:54:47 +0300
Subject: [PATCH 03/21] avoid deprecated g_type_class_add_private

---
 gvc-channel-map.c         | 8 ++------
 gvc-mixer-card.c          | 8 ++------
 gvc-mixer-control.c       | 7 ++-----
 gvc-mixer-event-role.c    | 8 ++------
 gvc-mixer-sink-input.c    | 8 ++------
 gvc-mixer-sink.c          | 8 ++------
 gvc-mixer-source-output.c | 8 ++------
 gvc-mixer-source.c        | 8 ++------
 gvc-mixer-stream.c        | 7 ++-----
 gvc-mixer-ui-device.c     | 8 ++------
 10 files changed, 20 insertions(+), 58 deletions(-)

diff --git a/subprojects/gvc/gvc-channel-map.c b/subprojects/gvc/gvc-channel-map.c
index b37fe17..bf4d737 100644
--- a/subprojects/gvc/gvc-channel-map.c
+++ b/subprojects/gvc/gvc-channel-map.c
@@ -32,8 +32,6 @@
 #include "gvc-channel-map.h"
 #include "gvc-channel-map-private.h"
 
-#define GVC_CHANNEL_MAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapPrivate))
-
 struct GvcChannelMapPrivate
 {
         pa_channel_map        pa_map;
@@ -53,7 +51,7 @@ static guint signals [LAST_SIGNAL] = { 0, };
 
 static void     gvc_channel_map_finalize   (GObject            *object);
 
-G_DEFINE_TYPE (GvcChannelMap, gvc_channel_map, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcChannelMap, gvc_channel_map, G_TYPE_OBJECT)
 
 guint
 gvc_channel_map_get_num_channels (const GvcChannelMap *map)
@@ -171,8 +169,6 @@ gvc_channel_map_class_init (GvcChannelMapClass *klass)
                               NULL, NULL,
                               g_cclosure_marshal_VOID__BOOLEAN,
                               G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
-        g_type_class_add_private (klass, sizeof (GvcChannelMapPrivate));
 }
 
 void
@@ -199,7 +195,7 @@ gvc_channel_map_volume_changed (GvcChannelMap     *map,
 static void
 gvc_channel_map_init (GvcChannelMap *map)
 {
-        map->priv = GVC_CHANNEL_MAP_GET_PRIVATE (map);
+        map->priv = gvc_channel_map_get_instance_private (map);
         map->priv->pa_volume_is_set = FALSE;
 }
 
diff --git a/subprojects/gvc/gvc-mixer-card.c b/subprojects/gvc/gvc-mixer-card.c
index b2e1614..ba31ab2 100644
--- a/subprojects/gvc/gvc-mixer-card.c
+++ b/subprojects/gvc/gvc-mixer-card.c
@@ -34,8 +34,6 @@
 #include "gvc-mixer-card.h"
 #include "gvc-mixer-card-private.h"
 
-#define GVC_MIXER_CARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardPrivate))
-
 static guint32 card_serial = 1;
 
 struct GvcMixerCardPrivate
@@ -67,7 +65,7 @@ enum
 
 static void     gvc_mixer_card_finalize   (GObject            *object);
 
-G_DEFINE_TYPE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT)
 
 static guint32
 get_next_card_serial (void)
@@ -509,14 +507,12 @@ gvc_mixer_card_class_init (GvcMixerCardClass *klass)
                                                               "Name of current profile for this card in human readable form",
                                                               NULL,
                                                               G_PARAM_READABLE));
-
-        g_type_class_add_private (klass, sizeof (GvcMixerCardPrivate));
 }
 
 static void
 gvc_mixer_card_init (GvcMixerCard *card)
 {
-        card->priv = GVC_MIXER_CARD_GET_PRIVATE (card);
+        card->priv = gvc_mixer_card_get_instance_private (card);
 }
 
 GvcMixerCard *
diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index 24daff8..78d5cf2 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -50,8 +50,6 @@
 #include "gvc-mixer-control-private.h"
 #include "gvc-mixer-ui-device.h"
 
-#define GVC_MIXER_CONTROL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlPrivate))
-
 #define RECONNECT_DELAY 5
 
 enum {
@@ -134,7 +132,7 @@ static guint signals [LAST_SIGNAL] = { 0, };
 
 static void     gvc_mixer_control_finalize   (GObject              *object);
 
-G_DEFINE_TYPE (GvcMixerControl, gvc_mixer_control, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerControl, gvc_mixer_control, G_TYPE_OBJECT)
 
 pa_context *
 gvc_mixer_control_get_pa_context (GvcMixerControl *control)
@@ -3671,14 +3669,13 @@ gvc_mixer_control_class_init (GvcMixerControlClass *klass)
                               NULL, NULL,
                               g_cclosure_marshal_VOID__UINT,
                               G_TYPE_NONE, 1, G_TYPE_UINT);
-        g_type_class_add_private (klass, sizeof (GvcMixerControlPrivate));
 }
 
 
 static void
 gvc_mixer_control_init (GvcMixerControl *control)
 {
-        control->priv = GVC_MIXER_CONTROL_GET_PRIVATE (control);
+        control->priv = gvc_mixer_control_get_instance_private (control);
 
         control->priv->pa_mainloop = pa_glib_mainloop_new (g_main_context_default ());
         g_assert (control->priv->pa_mainloop);
diff --git a/subprojects/gvc/gvc-mixer-event-role.c b/subprojects/gvc/gvc-mixer-event-role.c
index 35e8c9c..9f5e26a 100644
--- a/subprojects/gvc/gvc-mixer-event-role.c
+++ b/subprojects/gvc/gvc-mixer-event-role.c
@@ -34,8 +34,6 @@
 #include "gvc-mixer-stream-private.h"
 #include "gvc-channel-map-private.h"
 
-#define GVC_MIXER_EVENT_ROLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRolePrivate))
-
 struct GvcMixerEventRolePrivate
 {
         char          *device;
@@ -49,7 +47,7 @@ enum
 
 static void     gvc_mixer_event_role_finalize   (GObject            *object);
 
-G_DEFINE_TYPE (GvcMixerEventRole, gvc_mixer_event_role, GVC_TYPE_MIXER_STREAM)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerEventRole, gvc_mixer_event_role, GVC_TYPE_MIXER_STREAM)
 
 static gboolean
 update_settings (GvcMixerEventRole *role,
@@ -178,14 +176,12 @@ gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass)
                                                               "Device",
                                                               NULL,
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
-
-        g_type_class_add_private (klass, sizeof (GvcMixerEventRolePrivate));
 }
 
 static void
 gvc_mixer_event_role_init (GvcMixerEventRole *event_role)
 {
-        event_role->priv = GVC_MIXER_EVENT_ROLE_GET_PRIVATE (event_role);
+        event_role->priv = gvc_mixer_event_role_get_instance_private (event_role);
 
 }
 
diff --git a/subprojects/gvc/gvc-mixer-sink-input.c b/subprojects/gvc/gvc-mixer-sink-input.c
index a9bf176..a359daf 100644
--- a/subprojects/gvc/gvc-mixer-sink-input.c
+++ b/subprojects/gvc/gvc-mixer-sink-input.c
@@ -33,8 +33,6 @@
 #include "gvc-mixer-stream-private.h"
 #include "gvc-channel-map-private.h"
 
-#define GVC_MIXER_SINK_INPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputPrivate))
-
 struct GvcMixerSinkInputPrivate
 {
         gpointer dummy;
@@ -42,7 +40,7 @@ struct GvcMixerSinkInputPrivate
 
 static void     gvc_mixer_sink_input_finalize   (GObject                *object);
 
-G_DEFINE_TYPE (GvcMixerSinkInput, gvc_mixer_sink_input, GVC_TYPE_MIXER_STREAM)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerSinkInput, gvc_mixer_sink_input, GVC_TYPE_MIXER_STREAM)
 
 static gboolean
 gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op)
@@ -114,14 +112,12 @@ gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass)
 
         stream_class->push_volume = gvc_mixer_sink_input_push_volume;
         stream_class->change_is_muted = gvc_mixer_sink_input_change_is_muted;
-
-        g_type_class_add_private (klass, sizeof (GvcMixerSinkInputPrivate));
 }
 
 static void
 gvc_mixer_sink_input_init (GvcMixerSinkInput *sink_input)
 {
-        sink_input->priv = GVC_MIXER_SINK_INPUT_GET_PRIVATE (sink_input);
+        sink_input->priv = gvc_mixer_sink_input_get_instance_private (sink_input);
 }
 
 static void
diff --git a/subprojects/gvc/gvc-mixer-sink.c b/subprojects/gvc/gvc-mixer-sink.c
index 35c2c7f..a6115c6 100644
--- a/subprojects/gvc/gvc-mixer-sink.c
+++ b/subprojects/gvc/gvc-mixer-sink.c
@@ -33,8 +33,6 @@
 #include "gvc-mixer-stream-private.h"
 #include "gvc-channel-map-private.h"
 
-#define GVC_MIXER_SINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkPrivate))
-
 struct GvcMixerSinkPrivate
 {
         gpointer dummy;
@@ -42,7 +40,7 @@ struct GvcMixerSinkPrivate
 
 static void     gvc_mixer_sink_finalize   (GObject           *object);
 
-G_DEFINE_TYPE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM)
 
 static gboolean
 gvc_mixer_sink_push_volume (GvcMixerStream *stream, gpointer *op)
@@ -143,14 +141,12 @@ gvc_mixer_sink_class_init (GvcMixerSinkClass *klass)
         stream_class->push_volume = gvc_mixer_sink_push_volume;
         stream_class->change_port = gvc_mixer_sink_change_port;
         stream_class->change_is_muted = gvc_mixer_sink_change_is_muted;
-
-        g_type_class_add_private (klass, sizeof (GvcMixerSinkPrivate));
 }
 
 static void
 gvc_mixer_sink_init (GvcMixerSink *sink)
 {
-        sink->priv = GVC_MIXER_SINK_GET_PRIVATE (sink);
+        sink->priv = gvc_mixer_sink_get_instance_private (sink);
 }
 
 static void
diff --git a/subprojects/gvc/gvc-mixer-source-output.c b/subprojects/gvc/gvc-mixer-source-output.c
index 664bb94..c4a275a 100644
--- a/subprojects/gvc/gvc-mixer-source-output.c
+++ b/subprojects/gvc/gvc-mixer-source-output.c
@@ -33,8 +33,6 @@
 #include "gvc-mixer-stream-private.h"
 #include "gvc-channel-map-private.h"
 
-#define GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputPrivate))
-
 struct GvcMixerSourceOutputPrivate
 {
         gpointer dummy;
@@ -42,7 +40,7 @@ struct GvcMixerSourceOutputPrivate
 
 static void     gvc_mixer_source_output_finalize   (GObject            *object);
 
-G_DEFINE_TYPE (GvcMixerSourceOutput, gvc_mixer_source_output, GVC_TYPE_MIXER_STREAM)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerSourceOutput, gvc_mixer_source_output, GVC_TYPE_MIXER_STREAM)
 
 static gboolean
 gvc_mixer_source_output_push_volume (GvcMixerStream *stream, gpointer *op)
@@ -114,14 +112,12 @@ gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass)
 
         stream_class->push_volume = gvc_mixer_source_output_push_volume;
         stream_class->change_is_muted = gvc_mixer_source_output_change_is_muted;
-
-        g_type_class_add_private (klass, sizeof (GvcMixerSourceOutputPrivate));
 }
 
 static void
 gvc_mixer_source_output_init (GvcMixerSourceOutput *source_output)
 {
-        source_output->priv = GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE (source_output);
+        source_output->priv = gvc_mixer_source_output_get_instance_private (source_output);
 
 }
 
diff --git a/subprojects/gvc/gvc-mixer-source.c b/subprojects/gvc/gvc-mixer-source.c
index 051b795..434eec3 100644
--- a/subprojects/gvc/gvc-mixer-source.c
+++ b/subprojects/gvc/gvc-mixer-source.c
@@ -33,8 +33,6 @@
 #include "gvc-mixer-stream-private.h"
 #include "gvc-channel-map-private.h"
 
-#define GVC_MIXER_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourcePrivate))
-
 struct GvcMixerSourcePrivate
 {
         gpointer dummy;
@@ -42,7 +40,7 @@ struct GvcMixerSourcePrivate
 
 static void     gvc_mixer_source_finalize   (GObject            *object);
 
-G_DEFINE_TYPE (GvcMixerSource, gvc_mixer_source, GVC_TYPE_MIXER_STREAM)
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerSource, gvc_mixer_source, GVC_TYPE_MIXER_STREAM)
 
 static gboolean
 gvc_mixer_source_push_volume (GvcMixerStream *stream, gpointer *op)
@@ -143,14 +141,12 @@ gvc_mixer_source_class_init (GvcMixerSourceClass *klass)
         stream_class->push_volume = gvc_mixer_source_push_volume;
         stream_class->change_is_muted = gvc_mixer_source_change_is_muted;
         stream_class->change_port = gvc_mixer_source_change_port;
-
-        g_type_class_add_private (klass, sizeof (GvcMixerSourcePrivate));
 }
 
 static void
 gvc_mixer_source_init (GvcMixerSource *source)
 {
-        source->priv = GVC_MIXER_SOURCE_GET_PRIVATE (source);
+        source->priv = gvc_mixer_source_get_instance_private (source);
 }
 
 static void
diff --git a/subprojects/gvc/gvc-mixer-stream.c b/subprojects/gvc/gvc-mixer-stream.c
index 076b505..5de71d1 100644
--- a/subprojects/gvc/gvc-mixer-stream.c
+++ b/subprojects/gvc/gvc-mixer-stream.c
@@ -33,8 +33,6 @@
 #include "gvc-mixer-stream-private.h"
 #include "gvc-channel-map-private.h"
 
-#define GVC_MIXER_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamPrivate))
-
 static guint32 stream_serial = 1;
 
 struct GvcMixerStreamPrivate
@@ -86,7 +84,7 @@ enum
 
 static void     gvc_mixer_stream_finalize   (GObject            *object);
 
-G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT)
 
 static void
 free_port (GvcMixerStreamPort *p)
@@ -993,13 +991,12 @@ gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
                                                              "The index of the card for this stream",
                                                              PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX,
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
-        g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
 }
 
 static void
 gvc_mixer_stream_init (GvcMixerStream *stream)
 {
-        stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
+        stream->priv = gvc_mixer_stream_get_instance_private (stream);
 }
 
 static void
diff --git a/subprojects/gvc/gvc-mixer-ui-device.c b/subprojects/gvc/gvc-mixer-ui-device.c
index 285a0c0..a22afc2 100644
--- a/subprojects/gvc/gvc-mixer-ui-device.c
+++ b/subprojects/gvc/gvc-mixer-ui-device.c
@@ -23,8 +23,6 @@
 #include "gvc-mixer-ui-device.h"
 #include "gvc-mixer-card.h"
 
-#define GVC_MIXER_UI_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDevicePrivate))
-
 struct GvcMixerUIDevicePrivate
 {
         gchar                      *first_line_desc;
@@ -64,7 +62,7 @@ static void     gvc_mixer_ui_device_finalize   (GObject               *object);
 static void     gvc_mixer_ui_device_set_icon_name (GvcMixerUIDevice *device,
                                                    const char       *icon_name);
 
-G_DEFINE_TYPE (GvcMixerUIDevice, gvc_mixer_ui_device, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_PRIVATE (GvcMixerUIDevice, gvc_mixer_ui_device, G_TYPE_OBJECT)
 
 static guint32
 get_next_output_serial (void)
@@ -192,7 +190,7 @@ gvc_mixer_ui_device_constructor (GType                  type,
 static void
 gvc_mixer_ui_device_init (GvcMixerUIDevice *device)
 {
-        device->priv = GVC_MIXER_UI_DEVICE_GET_PRIVATE (device);
+        device->priv = gvc_mixer_ui_device_get_instance_private (device);
 }
 
 static void
@@ -290,8 +288,6 @@ gvc_mixer_ui_device_class_init (GvcMixerUIDeviceClass *klass)
                                      NULL,
                                      G_PARAM_READWRITE|G_PARAM_CONSTRUCT);
         g_object_class_install_property (object_class, PROP_ICON_NAME, pspec);
-
-        g_type_class_add_private (klass, sizeof (GvcMixerUIDevicePrivate));
 }
 
 /* Removes the part of the string that starts with skip_prefix
-- 
2.28.0


From 4e9205d6f39ea2d492717fa2c6db4c2b142fb4e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= <alberts.muktupavels@gmail.com>
Date: Sat, 8 Sep 2018 23:58:21 +0300
Subject: [PATCH 04/21] fix cast-function-type warnings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

gvc-mixer-card.c: In function ‘gvc_mixer_card_finalize’:
gvc-mixer-card.c:571:53: warning: cast between incompatible function types from ‘void (*)(GvcMixerCardProfile *)’ {aka ‘void (*)(struct <anonymous> *)’} to ‘void (*)(void *, void *)’ [-Wcast-function-type]
         g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL);

gvc-mixer-stream.c: In function ‘gvc_mixer_stream_finalize’:
gvc-mixer-stream.c:1044:52: warning: cast between incompatible function types from ‘void (*)(GvcMixerStreamPort *)’ {aka ‘void (*)(struct <anonymous> *)’} to ‘void (*)(void *, void *)’ [-Wcast-function-type]
         g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
---
 gvc-mixer-card.c   | 3 +--
 gvc-mixer-stream.c | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/subprojects/gvc/gvc-mixer-card.c b/subprojects/gvc/gvc-mixer-card.c
index ba31ab2..0856493 100644
--- a/subprojects/gvc/gvc-mixer-card.c
+++ b/subprojects/gvc/gvc-mixer-card.c
@@ -564,8 +564,7 @@ gvc_mixer_card_finalize (GObject *object)
         g_free (mixer_card->priv->human_profile);
         mixer_card->priv->human_profile = NULL;
 
-        g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL);
-        g_list_free (mixer_card->priv->profiles);
+        g_list_free_full (mixer_card->priv->profiles, (GDestroyNotify) free_profile);
         mixer_card->priv->profiles = NULL;
 
         g_list_free_full (mixer_card->priv->ports, (GDestroyNotify) free_port);
diff --git a/subprojects/gvc/gvc-mixer-stream.c b/subprojects/gvc/gvc-mixer-stream.c
index 5de71d1..b136a14 100644
--- a/subprojects/gvc/gvc-mixer-stream.c
+++ b/subprojects/gvc/gvc-mixer-stream.c
@@ -1038,8 +1038,7 @@ gvc_mixer_stream_finalize (GObject *object)
         g_free (mixer_stream->priv->human_port);
         mixer_stream->priv->human_port = NULL;
 
-        g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
-        g_list_free (mixer_stream->priv->ports);
+        g_list_free_full (mixer_stream->priv->ports, (GDestroyNotify) free_port);
         mixer_stream->priv->ports = NULL;
 
        if (mixer_stream->priv->change_volume_op) {
-- 
2.28.0


From 3513d3751067fba0fb9b0dfabd43b0b430d22d9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
Date: Fri, 7 Dec 2018 15:05:34 +0100
Subject: [PATCH 05/21] gvc-mixer-ui-device: Trim additional newlines in debug
 output

GVC logs a lot aready. No need to make it consume more screen space
with additional newlines.
---
 gvc-mixer-ui-device.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/subprojects/gvc/gvc-mixer-ui-device.c b/subprojects/gvc/gvc-mixer-ui-device.c
index a22afc2..67fb792 100644
--- a/subprojects/gvc/gvc-mixer-ui-device.c
+++ b/subprojects/gvc/gvc-mixer-ui-device.c
@@ -129,29 +129,29 @@ gvc_mixer_ui_device_set_property  (GObject      *object,
         case PROP_DESC_LINE_1:
                 g_free (self->priv->first_line_desc);
                 self->priv->first_line_desc = g_value_dup_string (value);
-                g_debug ("gvc-mixer-output-set-property - 1st line: %s\n",
+                g_debug ("gvc-mixer-output-set-property - 1st line: %s",
                          self->priv->first_line_desc);
                 break;
         case PROP_DESC_LINE_2:
                 g_free (self->priv->second_line_desc);
                 self->priv->second_line_desc = g_value_dup_string (value);
-                g_debug ("gvc-mixer-output-set-property - 2nd line: %s\n",
+                g_debug ("gvc-mixer-output-set-property - 2nd line: %s",
                          self->priv->second_line_desc);
                 break;
         case PROP_CARD:
                 self->priv->card = g_value_get_pointer (value);
-                g_debug ("gvc-mixer-output-set-property - card: %p\n",
+                g_debug ("gvc-mixer-output-set-property - card: %p",
                          self->priv->card);
                 break;
         case PROP_PORT_NAME:
                 g_free (self->priv->port_name);
                 self->priv->port_name = g_value_dup_string (value);
-                g_debug ("gvc-mixer-output-set-property - card port name: %s\n",
+                g_debug ("gvc-mixer-output-set-property - card port name: %s",
                          self->priv->port_name);
                 break;
         case PROP_STREAM_ID:
                 self->priv->stream_id = g_value_get_uint (value);
-                g_debug ("gvc-mixer-output-set-property - sink/source id: %i\n",
+                g_debug ("gvc-mixer-output-set-property - sink/source id: %i",
                          self->priv->stream_id);
                 break;
         case PROP_UI_DEVICE_TYPE:
@@ -159,7 +159,7 @@ gvc_mixer_ui_device_set_property  (GObject      *object,
                 break;
         case PROP_PORT_AVAILABLE:
                 self->priv->port_available = g_value_get_boolean (value);
-                g_debug ("gvc-mixer-output-set-property - port available %i, value passed in %i \n",
+                g_debug ("gvc-mixer-output-set-property - port available %i, value passed in %i",
                          self->priv->port_available, g_value_get_boolean (value));
                 break;
         case PROP_ICON_NAME:
-- 
2.28.0


From ae1a34aafce7026b8c0f65a43c9192d756fe1057 Mon Sep 17 00:00:00 2001
From: Andre Klapper <a9016009@gmx.de>
Date: Sun, 16 Dec 2018 01:22:53 +0100
Subject: [PATCH 06/21] Comment invalid <category> in DOAP file to pass git
 pre-receive hook

---
 libgnome-volume-control.doap | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/subprojects/gvc/libgnome-volume-control.doap b/subprojects/gvc/libgnome-volume-control.doap
index b87a90f..2fcc8e1 100644
--- a/subprojects/gvc/libgnome-volume-control.doap
+++ b/subprojects/gvc/libgnome-volume-control.doap
@@ -13,7 +13,7 @@
     as a submodule.
   </description>
 
-  <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
+  <!-- <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" /> -->
 
   <maintainer>
     <foaf:Person>
-- 
2.28.0


From 0e1b4bdafc364d5b62ffd14847e9e6ecfefbf2c9 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 27 Feb 2019 14:20:31 +0100
Subject: [PATCH 07/21] ci: Add CI

This just builds the "what-did-you-plugin" test application, but it's
good enough to catch the worst failures.
---
 .gitlab-ci.yml | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 .gitlab-ci.yml

diff --git a/subprojects/gvc/.gitlab-ci.yml b/subprojects/gvc/.gitlab-ci.yml
new file mode 100644
index 0000000..35b568c
--- /dev/null
+++ b/subprojects/gvc/.gitlab-ci.yml
@@ -0,0 +1,11 @@
+stages:
+- test
+
+build-fedora:
+  image: fedora:latest
+  stage: test
+  before_script:
+    - dnf install -y redhat-rpm-config gcc make pulseaudio-libs-devel alsa-lib-devel gtk3-devel
+  script:
+    - make -f Makefile.tests
+
-- 
2.28.0


From b28ae07ae1a96a98d4363fd8eacb69ab9bb6a806 Mon Sep 17 00:00:00 2001
From: Robert Ancell <robert.ancell@canonical.com>
Date: Fri, 15 Mar 2019 09:47:00 +1300
Subject: [PATCH 08/21] Add missing allow-none annotations

---
 gvc-mixer-card.c      | 9 +++++++++
 gvc-mixer-control.c   | 2 +-
 gvc-mixer-ui-device.c | 2 +-
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/subprojects/gvc/gvc-mixer-card.c b/subprojects/gvc/gvc-mixer-card.c
index 0856493..93be4da 100644
--- a/subprojects/gvc/gvc-mixer-card.c
+++ b/subprojects/gvc/gvc-mixer-card.c
@@ -220,6 +220,15 @@ _pa_context_set_card_profile_by_index_cb (pa_context                       *cont
         card->priv->profile_op = NULL;
 }
 
+/**
+ * gvc_mixer_card_change_profile:
+ * @card: a #GvcMixerCard
+ * @profile: (allow-none): the profile to change to or %NULL.
+ *
+ * Change the profile in use on this card.
+ *
+ * Returns: %TRUE if profile successfully changed or already using this profile.
+ */
 gboolean
 gvc_mixer_card_change_profile (GvcMixerCard *card,
                                const char *profile)
diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index 78d5cf2..de1c574 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -518,7 +518,7 @@ gvc_mixer_control_get_stream_from_device (GvcMixerControl *control,
  * gvc_mixer_control_change_profile_on_selected_device:
  * @control:
  * @device:
- * @profile: Can be null if any profile present on this port is okay
+ * @profile: (allow-none): Can be %NULL if any profile present on this port is okay
  *
  * Returns: This method will attempt to swap the profile on the card of
  * the device with given profile name.  If successfull it will set the
diff --git a/subprojects/gvc/gvc-mixer-ui-device.c b/subprojects/gvc/gvc-mixer-ui-device.c
index 67fb792..9b6addc 100644
--- a/subprojects/gvc/gvc-mixer-ui-device.c
+++ b/subprojects/gvc/gvc-mixer-ui-device.c
@@ -447,7 +447,7 @@ gvc_mixer_ui_device_set_profiles (GvcMixerUIDevice *device,
 
 /**
  * gvc_mixer_ui_device_get_best_profile:
- * @selected: The selected profile or its canonical name or %NULL for any profile
+ * @selected: (allow-none): The selected profile or its canonical name or %NULL for any profile
  * @current: The currently selected profile
  *
  * Returns: (transfer none): a profile name, valid as long as the UI device profiles are.
-- 
2.28.0


From 3f457453f031a2936ff267348107e6513be3aa27 Mon Sep 17 00:00:00 2001
From: Robert Ancell <robert.ancell@canonical.com>
Date: Fri, 15 Mar 2019 09:48:04 +1300
Subject: [PATCH 09/21] Add missing guards for inputs to functions

---
 gvc-mixer-control.c   | 18 +++++++++++++++++-
 gvc-mixer-stream.c    |  2 ++
 gvc-mixer-ui-device.c | 11 +++++++++++
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index de1c574..f16829d 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -235,6 +235,9 @@ gvc_mixer_control_lookup_device_from_stream (GvcMixerControl *control,
         const GList             *ports;
         GvcMixerUIDevice        *ret;
 
+        g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL);
+        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
+
         if (GVC_IS_MIXER_SOURCE (stream))
                devices = g_hash_table_get_values (control->priv->ui_inputs);
         else
@@ -534,6 +537,9 @@ gvc_mixer_control_change_profile_on_selected_device (GvcMixerControl  *control,
         GvcMixerCardProfile *current_profile;
         GvcMixerCard        *card;
 
+        g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
+        g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), FALSE);
+
         g_object_get (G_OBJECT (device), "card", &card, NULL);
         current_profile = gvc_mixer_card_get_profile (card);
 
@@ -588,6 +594,9 @@ gvc_mixer_control_change_output (GvcMixerControl *control,
         const GvcMixerStreamPort *active_port;
         const gchar              *output_port;
 
+        g_return_if_fail (GVC_IS_MIXER_CONTROL (control));
+        g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (output));
+
         g_debug ("control change output");
 
         stream = gvc_mixer_control_get_stream_from_device (control, output);
@@ -677,6 +686,9 @@ gvc_mixer_control_change_input (GvcMixerControl *control,
         const GvcMixerStreamPort *active_port;
         const gchar              *input_port;
 
+        g_return_if_fail (GVC_IS_MIXER_CONTROL (control));
+        g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (input));
+
         stream = gvc_mixer_control_get_stream_from_device (control, input);
         if (stream == NULL) {
                 gvc_mixer_control_change_profile_on_selected_device (control,
@@ -908,7 +920,7 @@ dec_outstanding (GvcMixerControl *control)
 GvcMixerControlState
 gvc_mixer_control_get_state (GvcMixerControl *control)
 {
-        g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
+        g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), GVC_STATE_CLOSED);
 
         return control->priv->state;
 }
@@ -2184,6 +2196,8 @@ gvc_mixer_control_set_headset_port (GvcMixerControl      *control,
                                     guint                 id,
                                     GvcHeadsetPortChoice  choice)
 {
+        g_return_if_fail (GVC_IS_MIXER_CONTROL (control));
+
 #ifdef HAVE_ALSA
         switch (choice) {
         case GVC_HEADSET_PORT_CHOICE_HEADPHONES:
@@ -3730,11 +3744,13 @@ gvc_mixer_control_new (const char *name)
 gdouble
 gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control)
 {
+	g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), 0);
 	return (gdouble) PA_VOLUME_NORM;
 }
 
 gdouble
 gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control)
 {
+	g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), 0);
 	return (gdouble) PA_VOLUME_UI_MAX;
 }
diff --git a/subprojects/gvc/gvc-mixer-stream.c b/subprojects/gvc/gvc-mixer-stream.c
index b136a14..af13ba3 100644
--- a/subprojects/gvc/gvc-mixer-stream.c
+++ b/subprojects/gvc/gvc-mixer-stream.c
@@ -839,6 +839,8 @@ gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
 gboolean
 gvc_mixer_stream_is_running (GvcMixerStream *stream)
 {
+        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
         if (stream->priv->change_volume_op == NULL)
                 return FALSE;
 
diff --git a/subprojects/gvc/gvc-mixer-ui-device.c b/subprojects/gvc/gvc-mixer-ui-device.c
index 9b6addc..f7dd33e 100644
--- a/subprojects/gvc/gvc-mixer-ui-device.c
+++ b/subprojects/gvc/gvc-mixer-ui-device.c
@@ -339,6 +339,9 @@ gvc_mixer_ui_device_get_matching_profile (GvcMixerUIDevice *device, const gchar
         GList *l;
         gchar *result = NULL;
 
+        g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL);
+        g_return_val_if_fail (profile != NULL, NULL);
+
         for (l = device->priv->profiles; l != NULL; l = l->next) {
                 gchar *canonical_name;
                 GvcMixerCardProfile* p = l->data;
@@ -424,6 +427,8 @@ gvc_mixer_ui_device_set_profiles (GvcMixerUIDevice *device,
         GHashTable *added_profiles;
         const gchar *skip_prefix = device->priv->type == UIDeviceInput ? "output:" : "input:";
 
+        g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (device));
+
         g_debug ("Set profiles for '%s'", gvc_mixer_ui_device_get_description(device));
 
         if (in_profiles == NULL)
@@ -462,6 +467,9 @@ gvc_mixer_ui_device_get_best_profile (GvcMixerUIDevice *device,
         const gchar *skip_prefix;
         gchar *canonical_name_selected;
 
+        g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL);
+        g_return_val_if_fail (current != NULL, NULL);
+
         if (device->priv->type == UIDeviceInput)
                 skip_prefix = "output:";
         else
@@ -657,6 +665,8 @@ gvc_mixer_ui_device_get_gicon (GvcMixerUIDevice *device)
 {
         const char *icon_name;
 
+        g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL);
+
         icon_name = gvc_mixer_ui_device_get_icon_name (device);
 
         if (icon_name != NULL)
@@ -700,6 +710,7 @@ gvc_mixer_ui_device_set_user_preferred_profile (GvcMixerUIDevice *device,
                                                 const gchar      *profile)
 {
         g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (device));
+        g_return_if_fail (profile != NULL);
 
         g_free (device->priv->user_preferred_profile);
         device->priv->user_preferred_profile = g_strdup (profile);
-- 
2.28.0


From 468022b708fc1a56154f3b0cc5af3b938fb3e9fb Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Fri, 14 Jun 2019 15:02:17 -0300
Subject: [PATCH 10/21] mixer-control: Use the "emblem-system-symbolic" icon

As suggested by the last round of design review [1], use the
"emblem-system-symbolic" icon with system sounds.

[1] https://gitlab.gnome.org/GNOME/gnome-control-center/issues/548
---
 gvc-mixer-control.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index f16829d..c611a41 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -2748,7 +2748,7 @@ update_event_role_stream (GvcMixerControl                  *control,
         max_volume = pa_cvolume_max (&info->volume);
 
         gvc_mixer_stream_set_name (stream, _("System Sounds"));
-        gvc_mixer_stream_set_icon_name (stream, "multimedia-volume-control");
+        gvc_mixer_stream_set_icon_name (stream, "emblem-system-symbolic");
         gvc_mixer_stream_set_volume (stream, (guint)max_volume);
         gvc_mixer_stream_set_is_muted (stream, info->mute);
 
-- 
2.28.0


From 78d3f49f798799782eff5ab5d0c454b661d885b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 22 Nov 2019 19:34:06 +0100
Subject: [PATCH 11/21] ci: Use meson for CI build

All consumers of the submodule switched to meson, except the CI build.
It neither seems useful to maintain a second build system just for that
purpose, nor to test a configuation that isn't used by anybody.

So set up a small fake project that includes gvc as a subproject, and
build that during CI.

https://gitlab.gnome.org/GNOME/libgnome-volume-control/merge_requests/9
---
 .gitlab-ci.yml             |  6 ++++--
 .gitlab-ci/meson.build     | 23 +++++++++++++++++++++++
 .gitlab-ci/subprojects/gvc |  1 +
 3 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 .gitlab-ci/meson.build
 create mode 120000 .gitlab-ci/subprojects/gvc

diff --git a/subprojects/gvc/.gitlab-ci.yml b/subprojects/gvc/.gitlab-ci.yml
index 35b568c..ad894f0 100644
--- a/subprojects/gvc/.gitlab-ci.yml
+++ b/subprojects/gvc/.gitlab-ci.yml
@@ -5,7 +5,9 @@ build-fedora:
   image: fedora:latest
   stage: test
   before_script:
-    - dnf install -y redhat-rpm-config gcc make pulseaudio-libs-devel alsa-lib-devel gtk3-devel
+    - dnf install -y redhat-rpm-config gcc meson pulseaudio-libs-devel alsa-lib-devel gtk3-devel
   script:
-    - make -f Makefile.tests
+    - cd .gitlab-ci
+    - meson _build
+    - ninja -C _build
 
diff --git a/subprojects/gvc/.gitlab-ci/meson.build b/subprojects/gvc/.gitlab-ci/meson.build
new file mode 100644
index 0000000..d54e1dd
--- /dev/null
+++ b/subprojects/gvc/.gitlab-ci/meson.build
@@ -0,0 +1,23 @@
+project('gnome-volume-control-ci', 'c',
+  version: '1.0.0',
+  meson_version: '>= 0.47.0',
+  license: 'GPLv2+'
+)
+
+prefix = get_option('prefix')
+
+datadir = join_paths(prefix, get_option('datadir'))
+libdir = join_paths(prefix, get_option('libdir'))
+
+pkgdatadir = join_paths(datadir, meson.project_name())
+pkglibdir = join_paths(libdir, meson.project_name())
+
+libgvc = subproject('gvc',
+  default_options: [
+    'package_name=' + meson.project_name(),
+    'package_version=' + meson.project_version(),
+    'pkgdatadir=' + pkgdatadir,
+    'pkglibdir=' + pkglibdir,
+    'alsa=true'
+  ]
+)
diff --git a/subprojects/gvc/.gitlab-ci/subprojects/gvc b/subprojects/gvc/.gitlab-ci/subprojects/gvc
new file mode 120000
index 0000000..6581736
--- /dev/null
+++ b/subprojects/gvc/.gitlab-ci/subprojects/gvc
@@ -0,0 +1 @@
+../../
\ No newline at end of file
-- 
2.28.0


From 43be5d272ca2d5d9e9bed4b5ad3ac28719f07a2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 22 Nov 2019 19:22:16 +0100
Subject: [PATCH 12/21] build: Drop autotools support

All of gnome-control-center, gnome-settings-daemon and gnome-shell
are meson-only nowadays, so there seems little point in supporting
two build systems.

https://gitlab.gnome.org/GNOME/libgnome-volume-control/merge_requests/9
---
 Makefile.am            | 64 ------------------------------------------
 Makefile.tests         | 43 ----------------------------
 tests-include/config.h |  3 --
 3 files changed, 110 deletions(-)
 delete mode 100644 Makefile.am
 delete mode 100644 Makefile.tests
 delete mode 100644 tests-include/config.h

diff --git a/subprojects/gvc/Makefile.am b/subprojects/gvc/Makefile.am
deleted file mode 100644
index 63468a0..0000000
--- a/subprojects/gvc/Makefile.am
+++ /dev/null
@@ -1,64 +0,0 @@
-
-noinst_LTLIBRARIES = libgvc.la
-
-INTROSPECTION_SCANNER_ARGS = --warn-all
-
-libgvc_la_CPPFLAGS =			\
-	$(WARN_CFLAGS)			\
-	$(GVC_CFLAGS)			\
-	-I$(srcdir)			\
-	-DWITH_INTROSPECTION		\
-	-DG_LOG_DOMAIN="\"Gvc\""
-
-libgvc_la_gir_sources = 			\
-	gvc-mixer-card.h			\
-	gvc-mixer-card.c			\
-	gvc-mixer-stream.h			\
-	gvc-mixer-stream.c			\
-	gvc-channel-map.h			\
-	gvc-channel-map.c			\
-	gvc-mixer-ui-device.h			\
-	gvc-mixer-ui-device.c			\
-	gvc-mixer-sink.h			\
-	gvc-mixer-sink.c			\
-	gvc-mixer-source.h			\
-	gvc-mixer-source.c			\
-	gvc-mixer-sink-input.h			\
-	gvc-mixer-sink-input.c			\
-	gvc-mixer-source-output.h		\
-	gvc-mixer-source-output.c		\
-	gvc-mixer-event-role.h			\
-	gvc-mixer-event-role.c			\
-	gvc-mixer-control.h			\
-	gvc-mixer-control.c			\
-	$(NULL)
-
-libgvc_la_SOURCES =				\
-	$(libgvc_la_gir_sources)		\
-	gvc-mixer-card-private.h		\
-	gvc-mixer-stream-private.h		\
-	gvc-channel-map-private.h		\
-	gvc-mixer-control-private.h		\
-	gvc-pulseaudio-fake.h			\
-	$(NULL)
-
-libgvc_la_LIBADD = 	\
-	$(GVC_LIBS)	\
-	$(NULL)
-
-if HAVE_INTROSPECTION
-include $(INTROSPECTION_MAKEFILE)
-
-Gvc-1.0.gir: libgvc.la
-Gvc_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0
-Gvc_1_0_gir_CFLAGS = $(INCLUDES) -I$(srcdir) -DWITH_INTROSPECTION
-Gvc_1_0_gir_LIBS = libgvc.la
-Gvc_1_0_gir_FILES = $(addprefix $(srcdir)/,$(libgvc_la_gir_sources))
-INTROSPECTION_GIRS = Gvc-1.0.gir
-
-typelibdir = $(pkglibdir)
-typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
-
-CLEANFILES = Gvc-1.0.gir $(typelib_DATA)
-
-endif
diff --git a/subprojects/gvc/Makefile.tests b/subprojects/gvc/Makefile.tests
deleted file mode 100644
index a05689c..0000000
--- a/subprojects/gvc/Makefile.tests
+++ /dev/null
@@ -1,43 +0,0 @@
-LIBGVC_SOURCES =				\
-	gvc-mixer-card.h			\
-	gvc-mixer-card.c			\
-	gvc-mixer-stream.h			\
-	gvc-mixer-stream.c			\
-	gvc-channel-map.h			\
-	gvc-channel-map.c			\
-	gvc-mixer-ui-device.h			\
-	gvc-mixer-ui-device.c			\
-	gvc-mixer-sink.h			\
-	gvc-mixer-sink.c			\
-	gvc-mixer-source.h			\
-	gvc-mixer-source.c			\
-	gvc-mixer-sink-input.h			\
-	gvc-mixer-sink-input.c			\
-	gvc-mixer-source-output.h		\
-	gvc-mixer-source-output.c		\
-	gvc-mixer-event-role.h			\
-	gvc-mixer-event-role.c			\
-	gvc-mixer-control.h			\
-	gvc-mixer-control.c			\
-	gvc-mixer-card-private.h		\
-	gvc-mixer-stream-private.h		\
-	gvc-channel-map-private.h		\
-	gvc-mixer-control-private.h		\
-	gvc-pulseaudio-fake.h
-
-GVC_CFLAGS = `pkg-config --cflags gtk+-3.0 libpulse libpulse-mainloop-glib alsa`
-GVC_LIBS = `pkg-config --libs gtk+-3.0 libpulse libpulse-mainloop-glib alsa`
-
-all: test-audio-device-selection $(LIBGVC_SOURCES) tests-include/config.h
-
-.c.o:
-	$(CC) -g3 -ggdb -c $(GVC_CFLAGS) -I. -Itests-include/ $< -o $@
-
-C_SOURCES = $(filter %.c,$(LIBGVC_SOURCES))
-OBJECTS=$(C_SOURCES:.c=.o)
-
-test-audio-device-selection: $(OBJECTS) test-audio-device-selection.o
-	$(CC) -g3 -ggdb $(GVC_LIBS) $(OBJECTS) test-audio-device-selection.o -o $@
-
-clean:
-	rm -f *.o test-audio-device-selection
diff --git a/subprojects/gvc/tests-include/config.h b/subprojects/gvc/tests-include/config.h
deleted file mode 100644
index 9326f4c..0000000
--- a/subprojects/gvc/tests-include/config.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#define GETTEXT_PACKAGE "libgvc-test"
-#define PACKAGE_VERSION "1.0-test"
-#define HAVE_ALSA       1
-- 
2.28.0


From 647e24625abbf97991f2f2314222904912505d42 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Sat, 23 Nov 2019 02:41:21 +0100
Subject: [PATCH 13/21] build: Don't limit pulseaudio-fake header to
 introspection

We'll soon need the types for glib-mkenums as well.

https://gitlab.gnome.org/GNOME/libgnome-volume-control/merge_requests/8
---
 gvc-pulseaudio-fake.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/subprojects/gvc/gvc-pulseaudio-fake.h b/subprojects/gvc/gvc-pulseaudio-fake.h
index ab8f6b4..92a41b6 100644
--- a/subprojects/gvc/gvc-pulseaudio-fake.h
+++ b/subprojects/gvc/gvc-pulseaudio-fake.h
@@ -21,14 +21,10 @@
 #ifndef __GVC_PULSEAUDIO_FAKE_H
 #define __GVC_PULSEAUDIO_FAKE_H
 
-#ifdef WITH_INTROSPECTION
-
 #ifndef PA_API_VERSION
 #define pa_channel_position_t int
 #define pa_volume_t guint32
 #define pa_context gpointer
 #endif /* PA_API_VERSION */
 
-#endif /* WITH_INTROSPECTION */
-
 #endif /* __GVC_PULSEAUDIO_FAKE_H */
-- 
2.28.0


From ec5cf3e0de6715803e64b65abb059e2155b3d6de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 22 Nov 2019 18:09:21 +0100
Subject: [PATCH 14/21] mixer-control: Expose stream state

The state can be used to determine whether audio is currently playing
or not, which can be useful information.

https://gitlab.gnome.org/GNOME/libgnome-volume-control/merge_requests/8
---
 gvc-mixer-control.c | 16 ++++++++++++++++
 gvc-mixer-stream.c  | 38 ++++++++++++++++++++++++++++++++++++++
 gvc-mixer-stream.h  | 11 +++++++++++
 meson.build         | 12 ++++++++----
 4 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index c611a41..21fc233 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -1452,6 +1452,21 @@ set_icon_name_from_proplist (GvcMixerStream *stream,
         gvc_mixer_stream_set_icon_name (stream, t);
 }
 
+static GvcMixerStreamState
+translate_pa_state (pa_sink_state_t state) {
+        switch (state) {
+        case PA_SINK_RUNNING:
+                return GVC_STREAM_STATE_RUNNING;
+        case PA_SINK_IDLE:
+                return GVC_STREAM_STATE_IDLE;
+        case PA_SINK_SUSPENDED:
+                return GVC_STREAM_STATE_SUSPENDED;
+        case PA_SINK_INVALID_STATE:
+        default:
+                return GVC_STREAM_STATE_INVALID;
+        }
+}
+
 /*
  * Called when anything changes with a sink.
  */
@@ -1521,6 +1536,7 @@ update_sink (GvcMixerControl    *control,
         gvc_mixer_stream_set_is_muted (stream, info->mute);
         gvc_mixer_stream_set_can_decibel (stream, !!(info->flags & PA_SINK_DECIBEL_VOLUME));
         gvc_mixer_stream_set_base_volume (stream, (guint32) info->base_volume);
+        gvc_mixer_stream_set_state (stream, translate_pa_state (info->state));
 
         /* Messy I know but to set the port everytime regardless of whether it has changed will cost us a
          * port change notify signal which causes the frontend to resync.
diff --git a/subprojects/gvc/gvc-mixer-stream.c b/subprojects/gvc/gvc-mixer-stream.c
index af13ba3..c324900 100644
--- a/subprojects/gvc/gvc-mixer-stream.c
+++ b/subprojects/gvc/gvc-mixer-stream.c
@@ -32,6 +32,7 @@
 #include "gvc-mixer-stream.h"
 #include "gvc-mixer-stream-private.h"
 #include "gvc-channel-map-private.h"
+#include "gvc-enum-types.h"
 
 static guint32 stream_serial = 1;
 
@@ -57,6 +58,7 @@ struct GvcMixerStreamPrivate
         char          *port;
         char          *human_port;
         GList         *ports;
+        GvcMixerStreamState state;
 };
 
 enum
@@ -80,6 +82,7 @@ enum
         PROP_IS_VIRTUAL,
         PROP_CARD_INDEX,
         PROP_PORT,
+        PROP_STATE,
 };
 
 static void     gvc_mixer_stream_finalize   (GObject            *object);
@@ -580,6 +583,27 @@ gvc_mixer_stream_get_ports (GvcMixerStream *stream)
         return stream->priv->ports;
 }
 
+gboolean
+gvc_mixer_stream_set_state (GvcMixerStream      *stream,
+                            GvcMixerStreamState  state)
+{
+        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
+
+        if (stream->priv->state != state) {
+                stream->priv->state = state;
+                g_object_notify (G_OBJECT (stream), "state");
+        }
+
+        return TRUE;
+}
+
+GvcMixerStreamState
+gvc_mixer_stream_get_state (GvcMixerStream      *stream)
+{
+        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), GVC_STREAM_STATE_INVALID);
+        return stream->priv->state;
+}
+
 static int
 sort_ports (GvcMixerStreamPort *a,
             GvcMixerStreamPort *b)
@@ -686,6 +710,9 @@ gvc_mixer_stream_set_property (GObject       *object,
         case PROP_PORT:
                 gvc_mixer_stream_set_port (self, g_value_get_string (value));
                 break;
+        case PROP_STATE:
+                gvc_mixer_stream_set_state (self, g_value_get_enum (value));
+                break;
         case PROP_CARD_INDEX:
                 self->priv->card_index = g_value_get_long (value);
                 break;
@@ -757,6 +784,9 @@ gvc_mixer_stream_get_property (GObject     *object,
         case PROP_PORT:
                 g_value_set_string (value, self->priv->port);
                 break;
+        case PROP_STATE:
+                g_value_set_enum (value, self->priv->state);
+                break;
         case PROP_CARD_INDEX:
                 g_value_set_long (value, self->priv->card_index);
                 break;
@@ -986,6 +1016,14 @@ gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
                                                               "The name of the current port for this stream",
                                                               NULL,
                                                               G_PARAM_READWRITE));
+        g_object_class_install_property (gobject_class,
+                                         PROP_STATE,
+                                         g_param_spec_enum ("state",
+                                                            "State",
+                                                            "The current state of this stream",
+                                                            GVC_TYPE_MIXER_STREAM_STATE,
+                                                            GVC_STREAM_STATE_INVALID,
+                                                            G_PARAM_READWRITE));
         g_object_class_install_property (gobject_class,
                                          PROP_CARD_INDEX,
                                          g_param_spec_long ("card-index",
diff --git a/subprojects/gvc/gvc-mixer-stream.h b/subprojects/gvc/gvc-mixer-stream.h
index 76cfb43..586ec75 100644
--- a/subprojects/gvc/gvc-mixer-stream.h
+++ b/subprojects/gvc/gvc-mixer-stream.h
@@ -64,6 +64,14 @@ typedef struct
         gboolean available;
 } GvcMixerStreamPort;
 
+typedef enum
+{
+        GVC_STREAM_STATE_INVALID,
+        GVC_STREAM_STATE_RUNNING,
+        GVC_STREAM_STATE_IDLE,
+        GVC_STREAM_STATE_SUSPENDED
+} GvcMixerStreamState;
+
 GType               gvc_mixer_stream_port_get_type   (void) G_GNUC_CONST;
 GType               gvc_mixer_stream_get_type        (void) G_GNUC_CONST;
 
@@ -95,6 +103,7 @@ const char *        gvc_mixer_stream_get_application_id (GvcMixerStream *stream)
 gboolean            gvc_mixer_stream_is_event_stream (GvcMixerStream *stream);
 gboolean            gvc_mixer_stream_is_virtual      (GvcMixerStream *stream);
 guint               gvc_mixer_stream_get_card_index  (GvcMixerStream *stream);
+GvcMixerStreamState gvc_mixer_stream_get_state       (GvcMixerStream *stream);
 
 /* private */
 gboolean            gvc_mixer_stream_set_volume      (GvcMixerStream *stream,
@@ -129,6 +138,8 @@ gboolean            gvc_mixer_stream_set_ports       (GvcMixerStream *stream,
                                                       GList          *ports);
 gboolean            gvc_mixer_stream_set_card_index  (GvcMixerStream *stream,
                                                       guint           card_index);
+gboolean            gvc_mixer_stream_set_state       (GvcMixerStream      *stream,
+                                                      GvcMixerStreamState  state);
 
 G_END_DECLS
 
diff --git a/subprojects/gvc/meson.build b/subprojects/gvc/meson.build
index 9608df1..3118806 100644
--- a/subprojects/gvc/meson.build
+++ b/subprojects/gvc/meson.build
@@ -1,5 +1,5 @@
 project('gvc', 'c',
-  meson_version: '>= 0.38.0',
+  meson_version: '>= 0.42.0',
   default_options: ['static=true']
 )
 
@@ -27,6 +27,10 @@ libgvc_gir_headers = [
   'gvc-mixer-ui-device.h'
 ]
 
+libgvc_enums = gnome.mkenums_simple('gvc-enum-types',
+  sources: libgvc_gir_headers
+)
+
 libgvc_gir_sources = [
   'gvc-channel-map.c',
   'gvc-mixer-card.c',
@@ -75,7 +79,7 @@ endif
 
 if enable_static
   libgvc_static = static_library('gvc',
-    sources: libgvc_gir_sources + libgvc_no_gir_sources,
+    sources: libgvc_gir_sources + libgvc_no_gir_sources + libgvc_enums,
     dependencies: libgvc_deps,
     c_args: c_args
   )
@@ -87,7 +91,7 @@ else
   endif
 
   libgvc_shared = shared_library('gvc',
-    sources: libgvc_gir_sources + libgvc_no_gir_sources,
+    sources: libgvc_gir_sources + libgvc_no_gir_sources + libgvc_enums,
     dependencies: libgvc_deps,
     c_args: c_args,
     install_dir: pkglibdir,
@@ -101,7 +105,7 @@ if enable_introspection
   assert(pkgdatadir != '', 'Installing introspection, but pkgdatadir is unset!')
 
   libgvc_gir = gnome.generate_gir(libgvc,
-    sources: libgvc_gir_sources + libgvc_gir_headers,
+    sources: libgvc_gir_sources + libgvc_gir_headers + libgvc_enums,
     nsversion: '1.0',
     namespace: 'Gvc',
     includes: ['Gio-2.0', 'GObject-2.0'],
-- 
2.28.0


From e2be83ee4a47da9c4c4fbf302a63f04b8d5683b9 Mon Sep 17 00:00:00 2001
From: Carlos Garnacho <carlosg@gnome.org>
Date: Thu, 9 Apr 2020 11:50:14 +0200
Subject: [PATCH 15/21] build: Bump pulseaudio dependency

We need 12.99.3 in order to avoid deadlocks on Xwayland startup, see
https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/commit/79a8efb45cb8304967baa2e8c6d6156478ce19d9

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2599
---
 meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/subprojects/gvc/meson.build b/subprojects/gvc/meson.build
index 3118806..a1a2af5 100644
--- a/subprojects/gvc/meson.build
+++ b/subprojects/gvc/meson.build
@@ -55,7 +55,7 @@ libgvc_no_gir_sources = [
 libgvc_deps = [
   dependency('gio-2.0'),
   dependency('gobject-2.0'),
-  dependency('libpulse', version: '>= 2.0'),
+  dependency('libpulse', version: '>= 12.99.3'),
   dependency('libpulse-mainloop-glib')
 ]
 
-- 
2.28.0


From 342e366eded97df48cef61b71bfd6b3481c69f06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= <alberts.muktupavels@gmail.com>
Date: Wed, 25 Dec 2019 19:14:19 +0200
Subject: [PATCH 16/21] mixer-control: fix -Wswitch-enum warnings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Warnings introduced in ec5cf3e0de6715803e64b65abb059e2155b3d6de:
gvc-mixer-control.c:1457:9: warning: enumeration value ‘PA_SINK_INIT’ not handled in switch [-Wswitch-enum]
gvc-mixer-control.c:1457:9: warning: enumeration value ‘PA_SINK_UNLINKED’ not handled in switch [-Wswitch-enum]

Warning building with alsa:
gvc-mixer-control.c:2218:9: warning: enumeration value ‘GVC_HEADSET_PORT_CHOICE_NONE’ not handled in switch [-Wswitch-enum]
---
 gvc-mixer-control.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index 21fc233..04644d7 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -1461,7 +1461,9 @@ translate_pa_state (pa_sink_state_t state) {
                 return GVC_STREAM_STATE_IDLE;
         case PA_SINK_SUSPENDED:
                 return GVC_STREAM_STATE_SUSPENDED;
+        case PA_SINK_INIT:
         case PA_SINK_INVALID_STATE:
+        case PA_SINK_UNLINKED:
         default:
                 return GVC_STREAM_STATE_INVALID;
         }
@@ -2228,6 +2230,7 @@ gvc_mixer_control_set_headset_port (GvcMixerControl      *control,
                 gvc_mixer_control_set_port_status_for_headset (control, id, "analog-output-speaker", TRUE);
                 gvc_mixer_control_set_port_status_for_headset (control, id, "analog-input-headphone-mic", FALSE);
                 break;
+        case GVC_HEADSET_PORT_CHOICE_NONE:
         default:
                 g_assert_not_reached ();
         }
-- 
2.28.0


From d8ba41f1d2982afdc5579dd2e73b84bd021e6230 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= <alberts.muktupavels@gmail.com>
Date: Wed, 25 Dec 2019 19:20:46 +0200
Subject: [PATCH 17/21] test-audio-device-selection: fix -Wsign-compare warning

---
 test-audio-device-selection.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/subprojects/gvc/test-audio-device-selection.c b/subprojects/gvc/test-audio-device-selection.c
index b276a8c..4b930a1 100644
--- a/subprojects/gvc/test-audio-device-selection.c
+++ b/subprojects/gvc/test-audio-device-selection.c
@@ -51,7 +51,7 @@ audio_selection_needed (GvcMixerControl      *volume,
 		g_print ("What is your choice?\n");
 		if (scanf ("%d", &res) == 1 &&
 		    res > 0 &&
-		    res < g_strv_length (args)) {
+		    res < (int) g_strv_length (args)) {
 			response = res;
 			break;
 		}
-- 
2.28.0


From 15980858d39ac3e4d6954e75c35caf5f8ea18358 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= <alberts.muktupavels@gmail.com>
Date: Wed, 25 Dec 2019 19:23:18 +0200
Subject: [PATCH 18/21] test-audio-device-selection: fix -Wdiscarded-qualifiers
 warnings

---
 test-audio-device-selection.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/subprojects/gvc/test-audio-device-selection.c b/subprojects/gvc/test-audio-device-selection.c
index 4b930a1..8195f9d 100644
--- a/subprojects/gvc/test-audio-device-selection.c
+++ b/subprojects/gvc/test-audio-device-selection.c
@@ -8,7 +8,7 @@
 
 typedef struct {
 	GvcHeadsetPortChoice choice;
-	gchar *name;
+	const char *name;
 } AudioSelectionChoice;
 
 static AudioSelectionChoice audio_selection_choices[] = {
@@ -24,7 +24,7 @@ audio_selection_needed (GvcMixerControl      *volume,
 			GvcHeadsetPortChoice  choices,
 			gpointer              user_data)
 {
-	char *args[G_N_ELEMENTS (audio_selection_choices) + 1];
+	const char *args[G_N_ELEMENTS (audio_selection_choices) + 1];
 	guint i, n;
 	int response = -1;
 
@@ -51,7 +51,7 @@ audio_selection_needed (GvcMixerControl      *volume,
 		g_print ("What is your choice?\n");
 		if (scanf ("%d", &res) == 1 &&
 		    res > 0 &&
-		    res < (int) g_strv_length (args)) {
+		    res < (int) g_strv_length ((char **)  args)) {
 			response = res;
 			break;
 		}
-- 
2.28.0


From 0aab80a78c6eabfe77f81cc30f2b2cade4ea1a58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alberts=20Muktup=C4=81vels?= <alberts.muktupavels@gmail.com>
Date: Wed, 25 Dec 2019 19:56:45 +0200
Subject: [PATCH 19/21] mixer-control: fix -Wsign-compare warnings

headset_card type is changed from int to guint32 to match uint32_t
used in PulseAudio's pa_card_info struct.
---
 gvc-mixer-control.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index 04644d7..a43ae1d 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -2096,7 +2096,7 @@ create_ui_device_from_card (GvcMixerControl *control,
 #ifdef HAVE_ALSA
 typedef struct {
         char *port_name_to_set;
-        int headset_card;
+        guint32 headset_card;
 } PortStatusData;
 
 static void
@@ -2124,7 +2124,7 @@ sink_info_cb (pa_context         *c,
 {
         PortStatusData *data = userdata;
         pa_operation *o;
-        int j;
+        guint j;
         const char *s;
 
         if (eol != 0) {
@@ -2160,7 +2160,7 @@ source_info_cb (pa_context           *c,
 {
         PortStatusData *data = userdata;
         pa_operation *o;
-        int j;
+        guint j;
         const char *s;
 
         if (eol != 0) {
-- 
2.28.0


From 960e01d957a97a752cbdd417ba06a3c8280881b5 Mon Sep 17 00:00:00 2001
From: Hui Wang <hui.wang@canonical.com>
Date: Mon, 2 Dec 2019 13:55:28 +0800
Subject: [PATCH 20/21] mixer-control: consolidate port finding and setting
 with/without ucm

Recently Intel added a new audio driver in the Linux kernel, it is
called sof driver. This driver is needed on the laptops which
connects the digital mic to the PCH instead of the codec. To make the
sof driver work with pulseaudio, the ucm is mandatory.

With the ucm, the multi-function audio jack has different port names
in the pulseaudio from the one without ucm, these are the port names
with the ucm:
[In] Mic1: Digital Microphone
[In] Mic2: Headphones Stereo Microphone
[In] Headset: Headset Mono Microphone
[Out] Headphones: Headphones
[Out] Speaker: Speaker

To make the audio device selection work on the machines using the ucm,
the pulseaudio introduces a change to add 2 new members in the device
port structure from the PA_PROTOCOL_VERSION=34, with these 2 members'
help, we could consolidate the port finding and setting for both with
ucm and without ucm.

And this patch maintains the backward compatibility with the
PA_PROTOCOL_VERSION < 34.
---
 gvc-mixer-control.c | 129 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 110 insertions(+), 19 deletions(-)

diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index a43ae1d..2dc2cb7 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -62,6 +62,7 @@ struct GvcMixerControlPrivate
         pa_glib_mainloop *pa_mainloop;
         pa_mainloop_api  *pa_api;
         pa_context       *pa_context;
+        guint             server_protocol_version;
         int               n_outstanding;
         guint             reconnect_id;
         char             *name;
@@ -104,6 +105,11 @@ struct GvcMixerControlPrivate
         gboolean has_headsetmic;
         gboolean has_headphonemic;
         gboolean headset_plugged_in;
+        char    *headphones_name;
+        char    *headsetmic_name;
+        char    *headphonemic_name;
+        char    *internalspk_name;
+        char    *internalmic_name;
 #endif /* HAVE_ALSA */
 
         GvcMixerControlState state;
@@ -2173,6 +2179,19 @@ source_info_cb (pa_context           *c,
 
         s = data->port_name_to_set;
 
+        for (j = 0; j < i->n_ports; j++) {
+                if (g_str_equal (i->ports[j]->name, s)) {
+                        o = pa_context_set_default_source (c,
+                                                           i->name,
+                                                           NULL,
+                                                           NULL);
+                        if (o == NULL) {
+                                g_warning ("pa_context_set_default_source() failed");
+                                return;
+                        }
+                }
+	}
+
         if (i->active_port && strcmp (i->active_port->name, s) == 0)
                 return;
 
@@ -2196,6 +2215,9 @@ gvc_mixer_control_set_port_status_for_headset (GvcMixerControl *control,
         pa_operation *o;
         PortStatusData *data;
 
+        if (port_name == NULL)
+                return;
+
         data = g_new0 (PortStatusData, 1);
         data->port_name_to_set = g_strdup (port_name);
         data->headset_card = id;
@@ -2209,6 +2231,18 @@ gvc_mixer_control_set_port_status_for_headset (GvcMixerControl *control,
 }
 #endif /* HAVE_ALSA */
 
+static void
+free_priv_port_names (GvcMixerControl    *control)
+{
+#ifdef HAVE_ALSA
+        g_clear_pointer (&control->priv->headphones_name, g_free);
+        g_clear_pointer (&control->priv->headsetmic_name, g_free);
+        g_clear_pointer (&control->priv->headphonemic_name, g_free);
+        g_clear_pointer (&control->priv->internalspk_name, g_free);
+        g_clear_pointer (&control->priv->internalmic_name, g_free);
+#endif
+}
+
 void
 gvc_mixer_control_set_headset_port (GvcMixerControl      *control,
                                     guint                 id,
@@ -2219,16 +2253,16 @@ gvc_mixer_control_set_headset_port (GvcMixerControl      *control,
 #ifdef HAVE_ALSA
         switch (choice) {
         case GVC_HEADSET_PORT_CHOICE_HEADPHONES:
-                gvc_mixer_control_set_port_status_for_headset (control, id, "analog-output-headphones", TRUE);
-                gvc_mixer_control_set_port_status_for_headset (control, id, "analog-input-internal-mic", FALSE);
+                gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headphones_name, TRUE);
+                gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->internalmic_name, FALSE);
                 break;
         case GVC_HEADSET_PORT_CHOICE_HEADSET:
-                gvc_mixer_control_set_port_status_for_headset (control, id, "analog-output-headphones", TRUE);
-                gvc_mixer_control_set_port_status_for_headset (control, id, "analog-input-headset-mic", FALSE);
+                gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headphones_name, TRUE);
+                gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headsetmic_name, FALSE);
                 break;
         case GVC_HEADSET_PORT_CHOICE_MIC:
-                gvc_mixer_control_set_port_status_for_headset (control, id, "analog-output-speaker", TRUE);
-                gvc_mixer_control_set_port_status_for_headset (control, id, "analog-input-headphone-mic", FALSE);
+                gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->internalspk_name, TRUE);
+                gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headphonemic_name, FALSE);
                 break;
         case GVC_HEADSET_PORT_CHOICE_NONE:
         default:
@@ -2244,16 +2278,24 @@ typedef struct {
         const pa_card_port_info *headphones;
         const pa_card_port_info *headsetmic;
         const pa_card_port_info *headphonemic;
+        const pa_card_port_info *internalmic;
+        const pa_card_port_info *internalspk;
 } headset_ports;
 
 /*
    TODO: Check if we still need this with the changed PA port names
 
-   In PulseAudio ports will show up with the following names:
+   In PulseAudio without ucm, ports will show up with the following names:
    Headphones - analog-output-headphones
    Headset mic - analog-input-headset-mic (was: analog-input-microphone-headset)
    Jack in mic-in mode - analog-input-headphone-mic (was: analog-input-microphone)
 
+   In PulseAudio with ucm, the ports name depends on the ucm, with the current
+   ucm2, the ports will show up with the following names:
+   Headphones - [Out] Headphone
+   Headset mic - [In] Headset
+   Jack in mic-in mode - [In] Mic2
+
    However, since regular mics also show up as analog-input-microphone,
    we need to check for certain controls on alsa mixer level too, to know
    if we deal with a separate mic jack, or a multi-function jack with a
@@ -2268,10 +2310,18 @@ typedef struct {
    Headset Mic Jack - indicates headset jack where hardware can distinguish
      between headphones and headsets. There is no use popping up a dialog in
      this case, unless we already need to do this for the mic-in mode.
+
+   From the PA_PROCOTOL_VERSION=34, The device_port structure adds 2 members
+   available_group and type, with the help of these 2 members, we could
+   consolidate the port checking and port setting for non-ucm and with-ucm
+   cases.
 */
 
+#define GET_PORT_NAME(x) (x ? g_strdup (x->name) : NULL)
+
 static headset_ports *
-get_headset_ports (const pa_card_info *c)
+get_headset_ports (GvcMixerControl    *control,
+                   const pa_card_info *c)
 {
         headset_ports *h;
         guint i;
@@ -2280,13 +2330,42 @@ get_headset_ports (const pa_card_info *c)
 
         for (i = 0; i < c->n_ports; i++) {
                 pa_card_port_info *p = c->ports[i];
-
-                if (strcmp (p->name, "analog-output-headphones") == 0)
-                        h->headphones = p;
-                else if (strcmp (p->name, "analog-input-headset-mic") == 0)
-                        h->headsetmic = p;
-                else if (strcmp(p->name, "analog-input-headphone-mic") == 0)
-                        h->headphonemic = p;
+                if (control->priv->server_protocol_version < 34) {
+                        if (g_str_equal (p->name, "analog-output-headphones"))
+                                h->headphones = p;
+                        else if (g_str_equal (p->name, "analog-input-headset-mic"))
+                                h->headsetmic = p;
+                        else if (g_str_equal (p->name, "analog-input-headphone-mic"))
+                                h->headphonemic = p;
+                        else if (g_str_equal (p->name, "analog-input-internal-mic"))
+                                h->internalmic = p;
+                        else if (g_str_equal (p->name, "analog-output-speaker"))
+                                h->internalspk = p;
+                } else {
+#if (PA_PROTOCOL_VERSION >= 34)
+                        if (p->available_group && strcmp (p->available_group, "Headphone Mic") == 0) {
+                                if (p->type == PA_DEVICE_PORT_TYPE_HEADPHONES)
+                                        h->headphones = p;
+                                else if (p->type == PA_DEVICE_PORT_TYPE_HEADSET)
+                                        h->headsetmic = p;
+                                else if (p->type == PA_DEVICE_PORT_TYPE_MIC)
+                                        h->headphonemic = p;
+                        } else if (p->type == PA_DEVICE_PORT_TYPE_SPEAKER) {
+                                if (strcmp (p->name, "analog-output-speaker") == 0 ||
+                                    strcmp (p->name, "[Out] Speaker") == 0 )
+                                        h->internalspk = p;
+                        } else if (p->type == PA_DEVICE_PORT_TYPE_MIC) {
+                                if (strcmp (p->name, "analog-input-internal-mic") == 0 ||
+                                    strcmp (p->name, "[In] Mic1") == 0 )
+                                        h->internalmic = p;
+                        }
+#else
+                        g_warning ("libgnome-volume-control running against PulseAudio %u, "
+                                   "but compiled against older %d, report a bug to your distribution",
+                                   control->priv->server_protocol_version,
+                                   PA_PROTOCOL_VERSION);
+#endif
+                }
         }
         return h;
 }
@@ -2353,7 +2432,7 @@ check_audio_device_selection_needed (GvcMixerControl    *control,
 
         start_dialog = FALSE;
         stop_dialog = FALSE;
-        h = get_headset_ports (info);
+        h = get_headset_ports (control, info);
 
         if (!h->headphones ||
             (!h->headsetmic && !h->headphonemic)) {
@@ -2363,7 +2442,8 @@ check_audio_device_selection_needed (GvcMixerControl    *control,
 
         if (control->priv->headset_card != (int) info->index) {
                 int cardindex;
-                gboolean hsmic, hpmic;
+                gboolean hsmic = TRUE;
+                gboolean hpmic = TRUE;
                 const char *s;
 
                 s = pa_proplist_gets (info->proplist, "alsa.card");
@@ -2374,8 +2454,10 @@ check_audio_device_selection_needed (GvcMixerControl    *control,
                 if (cardindex == 0 && strcmp(s, "0") != 0)
                         goto out;
 
-                if (!verify_alsa_card(cardindex, &hsmic, &hpmic))
-                        goto out;
+                if (control->priv->server_protocol_version < 34) {
+                        if (!verify_alsa_card(cardindex, &hsmic, &hpmic))
+                                goto out;
+                }
 
                 control->priv->headset_card = info->index;
                 control->priv->has_headsetmic = hsmic && h->headsetmic;
@@ -2386,6 +2468,12 @@ check_audio_device_selection_needed (GvcMixerControl    *control,
         }
 
         control->priv->headset_plugged_in = h->headphones->available != PA_PORT_AVAILABLE_NO;
+        free_priv_port_names (control);
+        control->priv->headphones_name = GET_PORT_NAME(h->headphones);
+        control->priv->headsetmic_name = GET_PORT_NAME(h->headsetmic);
+        control->priv->headphonemic_name = GET_PORT_NAME(h->headphonemic);
+        control->priv->internalspk_name = GET_PORT_NAME(h->internalspk);
+        control->priv->internalmic_name = GET_PORT_NAME(h->internalmic);
 
         if (!start_dialog &&
             !stop_dialog)
@@ -3268,6 +3356,7 @@ gvc_mixer_control_ready (GvcMixerControl *control)
         req_update_sink_input_info (control, -1);
         req_update_source_output_info (control, -1);
 
+        control->priv->server_protocol_version = pa_context_get_server_protocol_version (control->priv->pa_context);
 
         control->priv->n_outstanding = 6;
 
@@ -3350,6 +3439,7 @@ idle_reconnect (gpointer data)
         if (control->priv->pa_context) {
                 pa_context_unref (control->priv->pa_context);
                 control->priv->pa_context = NULL;
+                control->priv->server_protocol_version = 0;
                 gvc_mixer_new_pa_context (control);
         }
 
@@ -3503,6 +3593,7 @@ gvc_mixer_control_dispose (GObject *object)
                 control->priv->ui_inputs = NULL;
         }
 
+        free_priv_port_names (control);
         G_OBJECT_CLASS (gvc_mixer_control_parent_class)->dispose (object);
 }
 
-- 
2.28.0


From 7a621180b46421e356b33972e3446775a504139c Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Tue, 2 Jun 2020 12:20:45 +0200
Subject: [PATCH 21/21] mixer-control: do not use port name string to select
 the headset ports

It is a bad idea to use the variable port name to check the port
type. Use only the new port type and availability group string
for the decision.

Also, select the ports by priority, if there multiple ports
with the similar type.
---
 gvc-mixer-control.c | 54 +++++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/subprojects/gvc/gvc-mixer-control.c b/subprojects/gvc/gvc-mixer-control.c
index 2dc2cb7..8b39080 100644
--- a/subprojects/gvc/gvc-mixer-control.c
+++ b/subprojects/gvc/gvc-mixer-control.c
@@ -2283,19 +2283,11 @@ typedef struct {
 } headset_ports;
 
 /*
-   TODO: Check if we still need this with the changed PA port names
-
    In PulseAudio without ucm, ports will show up with the following names:
    Headphones - analog-output-headphones
    Headset mic - analog-input-headset-mic (was: analog-input-microphone-headset)
    Jack in mic-in mode - analog-input-headphone-mic (was: analog-input-microphone)
 
-   In PulseAudio with ucm, the ports name depends on the ucm, with the current
-   ucm2, the ports will show up with the following names:
-   Headphones - [Out] Headphone
-   Headset mic - [In] Headset
-   Jack in mic-in mode - [In] Mic2
-
    However, since regular mics also show up as analog-input-microphone,
    we need to check for certain controls on alsa mixer level too, to know
    if we deal with a separate mic jack, or a multi-function jack with a
@@ -2312,11 +2304,17 @@ typedef struct {
      this case, unless we already need to do this for the mic-in mode.
 
    From the PA_PROCOTOL_VERSION=34, The device_port structure adds 2 members
-   available_group and type, with the help of these 2 members, we could
+   availability_group and type, with the help of these 2 members, we could
    consolidate the port checking and port setting for non-ucm and with-ucm
    cases.
 */
 
+#define HEADSET_PORT_SET(dst, src) \
+        do { \
+                if (!(dst) || (dst)->priority < (src)->priority) \
+                        dst = src; \
+        } while (0)
+
 #define GET_PORT_NAME(x) (x ? g_strdup (x->name) : NULL)
 
 static headset_ports *
@@ -2343,21 +2341,16 @@ get_headset_ports (GvcMixerControl    *control,
                                 h->internalspk = p;
                 } else {
 #if (PA_PROTOCOL_VERSION >= 34)
-                        if (p->available_group && strcmp (p->available_group, "Headphone Mic") == 0) {
-                                if (p->type == PA_DEVICE_PORT_TYPE_HEADPHONES)
-                                        h->headphones = p;
-                                else if (p->type == PA_DEVICE_PORT_TYPE_HEADSET)
-                                        h->headsetmic = p;
-                                else if (p->type == PA_DEVICE_PORT_TYPE_MIC)
-                                        h->headphonemic = p;
+                        /* in the first loop, set only headphones */
+                        /* the microphone ports are assigned in the second loop */
+                        if (p->type == PA_DEVICE_PORT_TYPE_HEADPHONES) {
+                                if (p->availability_group)
+                                        HEADSET_PORT_SET (h->headphones, p);
                         } else if (p->type == PA_DEVICE_PORT_TYPE_SPEAKER) {
-                                if (strcmp (p->name, "analog-output-speaker") == 0 ||
-                                    strcmp (p->name, "[Out] Speaker") == 0 )
-                                        h->internalspk = p;
+                                HEADSET_PORT_SET (h->internalspk, p);
                         } else if (p->type == PA_DEVICE_PORT_TYPE_MIC) {
-                                if (strcmp (p->name, "analog-input-internal-mic") == 0 ||
-                                    strcmp (p->name, "[In] Mic1") == 0 )
-                                        h->internalmic = p;
+                                if (!p->availability_group)
+                                        HEADSET_PORT_SET (h->internalmic, p);
                         }
 #else
                         g_warning ("libgnome-volume-control running against PulseAudio %u, "
@@ -2367,6 +2360,23 @@ get_headset_ports (GvcMixerControl    *control,
 #endif
                 }
         }
+
+#if (PA_PROTOCOL_VERSION >= 34)
+        if (h->headphones && (control->priv->server_protocol_version >= 34)) {
+                for (i = 0; i < c->n_ports; i++) {
+                        pa_card_port_info *p = c->ports[i];
+                        if (g_strcmp0(h->headphones->availability_group, p->availability_group))
+                                continue;
+                        if (p->direction != PA_DIRECTION_INPUT)
+                                continue;
+                        if (p->type == PA_DEVICE_PORT_TYPE_HEADSET)
+                                HEADSET_PORT_SET (h->headsetmic, p);
+                        else if (p->type == PA_DEVICE_PORT_TYPE_MIC)
+                                HEADSET_PORT_SET (h->headphonemic, p);
+                }
+        }
+#endif
+
         return h;
 }
 
-- 
2.28.0

