@@ -122,6 +122,10 @@ static const gchar kb_introspection_xml[] =
122122#define LOGIND_DBUS_PATH "/org/freedesktop/login1"
123123#define LOGIND_DBUS_INTERFACE "org.freedesktop.login1.Manager"
124124
125+ #define AUDIO_SELECTION_DBUS_NAME "org.Cinnamon.AudioDeviceSelection"
126+ #define AUDIO_SELECTION_DBUS_PATH "/org/Cinnamon/AudioDeviceSelection"
127+ #define AUDIO_SELECTION_DBUS_INTERFACE "org.Cinnamon.AudioDeviceSelection"
128+
125129#define CSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (o ) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CSD_TYPE_MEDIA_KEYS_MANAGER, CsdMediaKeysManagerPrivate))
126130
127131typedef struct {
@@ -147,6 +151,11 @@ struct CsdMediaKeysManagerPrivate
147151 GHashTable * streams ; /* key = X device ID, value = stream id */
148152 GUdevClient * udev_client ;
149153#endif /* HAVE_GUDEV */
154+ guint audio_selection_watch_id ;
155+ guint audio_selection_signal_id ;
156+ GDBusConnection * audio_selection_conn ;
157+ gboolean audio_selection_requested ;
158+ guint audio_selection_device_id ;
150159
151160 GtkWidget * dialog ;
152161
@@ -1777,6 +1786,140 @@ update_theme_settings (GSettings *settings,
17771786 }
17781787}
17791788
1789+ typedef struct {
1790+ GvcHeadsetPortChoice choice ;
1791+ gchar * name ;
1792+ } AudioSelectionChoice ;
1793+
1794+ static AudioSelectionChoice audio_selection_choices [] = {
1795+ { GVC_HEADSET_PORT_CHOICE_HEADPHONES , "headphones" },
1796+ { GVC_HEADSET_PORT_CHOICE_HEADSET , "headset" },
1797+ { GVC_HEADSET_PORT_CHOICE_MIC , "microphone" },
1798+ };
1799+
1800+ static void
1801+ audio_selection_done (GDBusConnection * connection ,
1802+ const gchar * sender_name ,
1803+ const gchar * object_path ,
1804+ const gchar * interface_name ,
1805+ const gchar * signal_name ,
1806+ GVariant * parameters ,
1807+ gpointer data )
1808+ {
1809+ CsdMediaKeysManagerPrivate * priv = CSD_MEDIA_KEYS_MANAGER (data )-> priv ;
1810+ const gchar * choice ;
1811+ guint i ;
1812+
1813+ if (!priv -> audio_selection_requested )
1814+ return ;
1815+
1816+ choice = NULL ;
1817+ g_variant_get_child (parameters , 0 , "&s" , & choice );
1818+ if (!choice )
1819+ return ;
1820+
1821+ for (i = 0 ; i < G_N_ELEMENTS (audio_selection_choices ); ++ i ) {
1822+ if (g_str_equal (choice , audio_selection_choices [i ].name )) {
1823+ gvc_mixer_control_set_headset_port (priv -> volume ,
1824+ priv -> audio_selection_device_id ,
1825+ audio_selection_choices [i ].choice );
1826+ break ;
1827+ }
1828+ }
1829+
1830+ priv -> audio_selection_requested = FALSE;
1831+ }
1832+
1833+ static void
1834+ audio_selection_needed (GvcMixerControl * control ,
1835+ guint id ,
1836+ gboolean show_dialog ,
1837+ GvcHeadsetPortChoice choices ,
1838+ CsdMediaKeysManager * manager )
1839+ {
1840+ CsdMediaKeysManagerPrivate * priv = manager -> priv ;
1841+ gchar * args [G_N_ELEMENTS (audio_selection_choices ) + 1 ];
1842+ guint i , n ;
1843+
1844+ if (!priv -> audio_selection_conn )
1845+ return ;
1846+
1847+ if (priv -> audio_selection_requested ) {
1848+ g_dbus_connection_call (priv -> audio_selection_conn ,
1849+ AUDIO_SELECTION_DBUS_NAME ,
1850+ AUDIO_SELECTION_DBUS_PATH ,
1851+ AUDIO_SELECTION_DBUS_INTERFACE ,
1852+ "Close" , NULL , NULL ,
1853+ G_DBUS_CALL_FLAGS_NONE ,
1854+ -1 , NULL , NULL , NULL );
1855+ priv -> audio_selection_requested = FALSE;
1856+ }
1857+
1858+ if (!show_dialog )
1859+ return ;
1860+
1861+ n = 0 ;
1862+ for (i = 0 ; i < G_N_ELEMENTS (audio_selection_choices ); ++ i ) {
1863+ if (choices & audio_selection_choices [i ].choice )
1864+ args [n ++ ] = audio_selection_choices [i ].name ;
1865+ }
1866+ args [n ] = NULL ;
1867+
1868+ priv -> audio_selection_requested = TRUE;
1869+ priv -> audio_selection_device_id = id ;
1870+ g_dbus_connection_call (priv -> audio_selection_conn ,
1871+ AUDIO_SELECTION_DBUS_NAME ,
1872+ AUDIO_SELECTION_DBUS_PATH ,
1873+ AUDIO_SELECTION_DBUS_INTERFACE ,
1874+ "Open" ,
1875+ g_variant_new ("(^as)" , args ),
1876+ NULL ,
1877+ G_DBUS_CALL_FLAGS_NONE ,
1878+ -1 , NULL , NULL , NULL );
1879+ }
1880+
1881+ static void
1882+ audio_selection_appeared (GDBusConnection * connection ,
1883+ const gchar * name ,
1884+ const gchar * name_owner ,
1885+ gpointer data )
1886+ {
1887+ CsdMediaKeysManager * manager = data ;
1888+ manager -> priv -> audio_selection_conn = connection ;
1889+ manager -> priv -> audio_selection_signal_id =
1890+ g_dbus_connection_signal_subscribe (connection ,
1891+ AUDIO_SELECTION_DBUS_NAME ,
1892+ AUDIO_SELECTION_DBUS_INTERFACE ,
1893+ "DeviceSelected" ,
1894+ AUDIO_SELECTION_DBUS_PATH ,
1895+ NULL ,
1896+ G_DBUS_SIGNAL_FLAGS_NONE ,
1897+ audio_selection_done ,
1898+ manager ,
1899+ NULL );
1900+ }
1901+
1902+ static void
1903+ clear_audio_selection (CsdMediaKeysManager * manager )
1904+ {
1905+ CsdMediaKeysManagerPrivate * priv = manager -> priv ;
1906+
1907+ if (priv -> audio_selection_signal_id )
1908+ g_dbus_connection_signal_unsubscribe (priv -> audio_selection_conn ,
1909+ priv -> audio_selection_signal_id );
1910+ priv -> audio_selection_signal_id = 0 ;
1911+ priv -> audio_selection_conn = NULL ;
1912+ }
1913+
1914+ static void
1915+ audio_selection_vanished (GDBusConnection * connection ,
1916+ const gchar * name ,
1917+ gpointer data )
1918+ {
1919+ if (connection )
1920+ clear_audio_selection (data );
1921+ }
1922+
17801923static gboolean
17811924start_media_keys_idle_cb (CsdMediaKeysManager * manager )
17821925{
@@ -1863,6 +2006,19 @@ csd_media_keys_manager_start (CsdMediaKeysManager *manager,
18632006 "stream-removed" ,
18642007 G_CALLBACK (on_control_stream_removed ),
18652008 manager );
2009+ g_signal_connect (manager -> priv -> volume ,
2010+ "audio-device-selection-needed" ,
2011+ G_CALLBACK (audio_selection_needed ),
2012+ manager );
2013+
2014+ manager -> priv -> audio_selection_watch_id =
2015+ g_bus_watch_name (G_BUS_TYPE_SESSION ,
2016+ AUDIO_SELECTION_DBUS_NAME ,
2017+ G_BUS_NAME_WATCHER_FLAGS_NONE ,
2018+ audio_selection_appeared ,
2019+ audio_selection_vanished ,
2020+ manager ,
2021+ NULL );
18662022
18672023 cinnamon_settings_profile_end ("gvc_mixer_control_new" );
18682024
@@ -2037,6 +2193,11 @@ csd_media_keys_manager_stop (CsdMediaKeysManager *manager)
20372193 g_list_free (priv -> media_players );
20382194 priv -> media_players = NULL ;
20392195 }
2196+
2197+ if (priv -> audio_selection_watch_id )
2198+ g_bus_unwatch_name (priv -> audio_selection_watch_id );
2199+ priv -> audio_selection_watch_id = 0 ;
2200+ clear_audio_selection (manager );
20402201}
20412202
20422203static GObject *
0 commit comments