diff options
Diffstat (limited to 'src')
42 files changed, 2149 insertions, 1511 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ed64aeb..63d6d5a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,7 +72,6 @@ music_bridge_VALAFLAGS = \ --pkg gdk-pixbuf-2.0 \ --pkg libxml-2.0 - $(MAINTAINER_VALAFLAGS) music_bridge_APIFILES = \ @@ -89,8 +88,10 @@ indicator_sound_service_SOURCES = \ common-defs.h \ sound-service.h \ sound-service.c \ - pulse-manager.h \ - pulse-manager.c \ + pulseaudio-mgr.h \ + pulseaudio-mgr.c \ + active-sink.c \ + active-sink.h \ sound-service-dbus.h \ sound-service-dbus.c \ slider-menu-item.h \ @@ -108,7 +109,7 @@ indicator_sound_service_LDADD = $(PULSEAUDIO_LIBS) $(SOUNDSERVICE_LIBS) $(GCONF_ # Service xml compilation ######################### DBUS_SPECS = \ - sound-service.xml + sound-service.xml gen-%.xml.h: %.xml @echo "Building $@ from $<" diff --git a/src/Makefile.in b/src/Makefile.in index e23b0b1..74d3cc9 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -39,10 +39,7 @@ libexec_PROGRAMS = indicator-sound-service$(EXEEXT) subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/intltool.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ - $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -106,7 +103,8 @@ am__objects_1 = indicator_sound_service-music-player-bridge.$(OBJEXT) \ indicator_sound_service-fetch-file.$(OBJEXT) am_indicator_sound_service_OBJECTS = \ indicator_sound_service-sound-service.$(OBJEXT) \ - indicator_sound_service-pulse-manager.$(OBJEXT) \ + indicator_sound_service-pulseaudio-mgr.$(OBJEXT) \ + indicator_sound_service-active-sink.$(OBJEXT) \ indicator_sound_service-sound-service-dbus.$(OBJEXT) \ indicator_sound_service-slider-menu-item.$(OBJEXT) \ indicator_sound_service-mute-menu-item.$(OBJEXT) \ @@ -387,8 +385,10 @@ indicator_sound_service_SOURCES = \ common-defs.h \ sound-service.h \ sound-service.c \ - pulse-manager.h \ - pulse-manager.c \ + pulseaudio-mgr.h \ + pulseaudio-mgr.c \ + active-sink.c \ + active-sink.h \ sound-service-dbus.h \ sound-service-dbus.c \ slider-menu-item.h \ @@ -406,7 +406,7 @@ indicator_sound_service_LDADD = $(PULSEAUDIO_LIBS) $(SOUNDSERVICE_LIBS) $(GCONF_ # Service xml compilation ######################### DBUS_SPECS = \ - sound-service.xml + sound-service.xml EXTRA_DIST = \ $(DBUS_SPECS) \ @@ -549,6 +549,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-active-sink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-fetch-file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-freedesktop-interfaces.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-gen-sound-service.xml.Po@am__quote@ @@ -561,7 +562,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-player-controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-player-item.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-playlists-menu-item.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-pulse-manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-pulseaudio-mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-settings-manager.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-slider-menu-item.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-sound-service-dbus.Po@am__quote@ @@ -672,21 +673,37 @@ indicator_sound_service-sound-service.obj: sound-service.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -c -o indicator_sound_service-sound-service.obj `if test -f 'sound-service.c'; then $(CYGPATH_W) 'sound-service.c'; else $(CYGPATH_W) '$(srcdir)/sound-service.c'; fi` -indicator_sound_service-pulse-manager.o: pulse-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-pulse-manager.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-pulse-manager.Tpo -c -o indicator_sound_service-pulse-manager.o `test -f 'pulse-manager.c' || echo '$(srcdir)/'`pulse-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-pulse-manager.Tpo $(DEPDIR)/indicator_sound_service-pulse-manager.Po +indicator_sound_service-pulseaudio-mgr.o: pulseaudio-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-pulseaudio-mgr.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-pulseaudio-mgr.Tpo -c -o indicator_sound_service-pulseaudio-mgr.o `test -f 'pulseaudio-mgr.c' || echo '$(srcdir)/'`pulseaudio-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-pulseaudio-mgr.Tpo $(DEPDIR)/indicator_sound_service-pulseaudio-mgr.Po @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pulse-manager.c' object='indicator_sound_service-pulse-manager.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pulseaudio-mgr.c' object='indicator_sound_service-pulseaudio-mgr.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -c -o indicator_sound_service-pulse-manager.o `test -f 'pulse-manager.c' || echo '$(srcdir)/'`pulse-manager.c +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -c -o indicator_sound_service-pulseaudio-mgr.o `test -f 'pulseaudio-mgr.c' || echo '$(srcdir)/'`pulseaudio-mgr.c -indicator_sound_service-pulse-manager.obj: pulse-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-pulse-manager.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-pulse-manager.Tpo -c -o indicator_sound_service-pulse-manager.obj `if test -f 'pulse-manager.c'; then $(CYGPATH_W) 'pulse-manager.c'; else $(CYGPATH_W) '$(srcdir)/pulse-manager.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-pulse-manager.Tpo $(DEPDIR)/indicator_sound_service-pulse-manager.Po +indicator_sound_service-pulseaudio-mgr.obj: pulseaudio-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-pulseaudio-mgr.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-pulseaudio-mgr.Tpo -c -o indicator_sound_service-pulseaudio-mgr.obj `if test -f 'pulseaudio-mgr.c'; then $(CYGPATH_W) 'pulseaudio-mgr.c'; else $(CYGPATH_W) '$(srcdir)/pulseaudio-mgr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-pulseaudio-mgr.Tpo $(DEPDIR)/indicator_sound_service-pulseaudio-mgr.Po @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pulse-manager.c' object='indicator_sound_service-pulse-manager.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pulseaudio-mgr.c' object='indicator_sound_service-pulseaudio-mgr.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -c -o indicator_sound_service-pulse-manager.obj `if test -f 'pulse-manager.c'; then $(CYGPATH_W) 'pulse-manager.c'; else $(CYGPATH_W) '$(srcdir)/pulse-manager.c'; fi` +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -c -o indicator_sound_service-pulseaudio-mgr.obj `if test -f 'pulseaudio-mgr.c'; then $(CYGPATH_W) 'pulseaudio-mgr.c'; else $(CYGPATH_W) '$(srcdir)/pulseaudio-mgr.c'; fi` + +indicator_sound_service-active-sink.o: active-sink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-active-sink.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-active-sink.Tpo -c -o indicator_sound_service-active-sink.o `test -f 'active-sink.c' || echo '$(srcdir)/'`active-sink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-active-sink.Tpo $(DEPDIR)/indicator_sound_service-active-sink.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='active-sink.c' object='indicator_sound_service-active-sink.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -c -o indicator_sound_service-active-sink.o `test -f 'active-sink.c' || echo '$(srcdir)/'`active-sink.c + +indicator_sound_service-active-sink.obj: active-sink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-active-sink.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-active-sink.Tpo -c -o indicator_sound_service-active-sink.obj `if test -f 'active-sink.c'; then $(CYGPATH_W) 'active-sink.c'; else $(CYGPATH_W) '$(srcdir)/active-sink.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-active-sink.Tpo $(DEPDIR)/indicator_sound_service-active-sink.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='active-sink.c' object='indicator_sound_service-active-sink.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -c -o indicator_sound_service-active-sink.obj `if test -f 'active-sink.c'; then $(CYGPATH_W) 'active-sink.c'; else $(CYGPATH_W) '$(srcdir)/active-sink.c'; fi` indicator_sound_service-sound-service-dbus.o: sound-service-dbus.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-sound-service-dbus.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-sound-service-dbus.Tpo -c -o indicator_sound_service-sound-service-dbus.o `test -f 'sound-service-dbus.c' || echo '$(srcdir)/'`sound-service-dbus.c diff --git a/src/active-sink.c b/src/active-sink.c new file mode 100644 index 0000000..b7954be --- /dev/null +++ b/src/active-sink.c @@ -0,0 +1,293 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <libdbusmenu-glib/menuitem.h> + +#include "active-sink.h" +#include "slider-menu-item.h" +#include "mute-menu-item.h" + +#include "pulseaudio-mgr.h" + +typedef struct _ActiveSinkPrivate ActiveSinkPrivate; + +struct _ActiveSinkPrivate +{ + SliderMenuItem* volume_slider_menuitem; + MuteMenuItem* mute_menuitem; + SoundState current_sound_state; + SoundServiceDbus* service; + gint index; + gchar* name; + pa_cvolume volume; + pa_channel_map channel_map; + pa_volume_t base_volume; +}; + +#define ACTIVE_SINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ACTIVE_SINK_TYPE, ActiveSinkPrivate)) + +/* Prototypes */ +static void active_sink_class_init (ActiveSinkClass *klass); +static void active_sink_init (ActiveSink *self); +static void active_sink_dispose (GObject *object); +static void active_sink_finalize (GObject *object); + +static SoundState active_sink_get_state_from_volume (ActiveSink* self); +static pa_cvolume active_sink_construct_mono_volume (const pa_cvolume* vol); +static void active_sink_volume_update (ActiveSink* self, gdouble percent); +static void active_sink_mute_update (ActiveSink* self, gboolean muted); + + +G_DEFINE_TYPE (ActiveSink, active_sink, G_TYPE_OBJECT); + +static void +active_sink_class_init (ActiveSinkClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (ActiveSinkPrivate)); + + gobject_class->dispose = active_sink_dispose; + gobject_class->finalize = active_sink_finalize; +} + +static void +active_sink_init (ActiveSink *self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + priv->mute_menuitem = NULL; + priv->volume_slider_menuitem = NULL; + priv->current_sound_state = UNAVAILABLE; + priv->index = -1; + priv->name = NULL; + priv->service = NULL; + + // Init our menu items. + priv->mute_menuitem = g_object_new (MUTE_MENU_ITEM_TYPE, NULL); + priv->volume_slider_menuitem = slider_menu_item_new (self); + mute_menu_item_enable (priv->mute_menuitem, FALSE); + slider_menu_item_enable (priv->volume_slider_menuitem, FALSE); +} + +static void +active_sink_dispose (GObject *object) +{ + G_OBJECT_CLASS (active_sink_parent_class)->dispose (object); +} + +static void +active_sink_finalize (GObject *object) +{ + G_OBJECT_CLASS (active_sink_parent_class)->finalize (object); +} + +void +active_sink_populate (ActiveSink* sink, + const pa_sink_info* update) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE(sink); + + priv->name = g_strdup (update->name); + priv->index = update->index; + active_sink_mute_update (sink, update->mute); + priv->volume = active_sink_construct_mono_volume (&update->volume); + priv->base_volume = update->base_volume; + priv->channel_map = update->channel_map; + + pa_volume_t vol = pa_cvolume_max (&update->volume); + gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; + + active_sink_volume_update (sink, volume_percent); + active_sink_mute_update (sink, update->mute); + mute_menu_item_enable (priv->mute_menuitem, TRUE); + slider_menu_item_enable (priv->volume_slider_menuitem, TRUE); + + g_debug ("Active sink has been populated - volume %f", volume_percent); +} + +void +active_sink_update (ActiveSink* sink, + const pa_sink_info* update) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink); + active_sink_mute_update (sink, update->mute); + priv->volume = active_sink_construct_mono_volume (&update->volume); + priv->base_volume = update->base_volume; + priv->channel_map = update->channel_map; + + pa_volume_t vol = pa_cvolume_max (&update->volume); + gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; + + active_sink_volume_update (sink, volume_percent); + active_sink_mute_update (sink, update->mute); +} + +// To the UI +static void +active_sink_volume_update (ActiveSink* self, gdouble percent) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + slider_menu_item_update (priv->volume_slider_menuitem, percent); + SoundState state = active_sink_get_state_from_volume (self); + if (priv->current_sound_state != state){ + priv->current_sound_state = state; + sound_service_dbus_update_sound_state (priv->service, + priv->current_sound_state); + } +} + +// From the UI +void +active_sink_update_volume (ActiveSink* self, gdouble percent) +{ + pa_cvolume new_volume; + pa_cvolume_init(&new_volume); + new_volume.channels = 1; + pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100); + pa_cvolume_set(&new_volume, 1, new_volume_value); + + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + + pa_cvolume_set(&priv->volume, priv->channel_map.channels, new_volume_value); + pm_update_volume (priv->index, new_volume); +} + + +static void +active_sink_mute_update (ActiveSink* self, gboolean muted) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + mute_menu_item_update (priv->mute_menuitem, muted); + SoundState state = active_sink_get_state_from_volume (self); + + if (muted == TRUE){ + state = MUTED; + } + if (priv->current_sound_state != state){ + priv->current_sound_state = state; + sound_service_dbus_update_sound_state (priv->service, state); + } +} + +void +active_sink_ensure_sink_is_unmuted (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + if (mute_menu_item_is_muted (priv->mute_menuitem)){ + pm_update_mute (FALSE); + } +} + + +static SoundState +active_sink_get_state_from_volume (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + GVariant* v = dbusmenu_menuitem_property_get_variant (DBUSMENU_MENUITEM(priv->volume_slider_menuitem), + DBUSMENU_VOLUME_MENUITEM_LEVEL); + gdouble volume_percent = g_variant_get_double (v); + + SoundState state = LOW_LEVEL; + + if (volume_percent < 30.0 && volume_percent > 0) { + state = LOW_LEVEL; + } + else if (volume_percent < 70.0 && volume_percent >= 30.0) { + state = MEDIUM_LEVEL; + } + else if (volume_percent >= 70.0) { + state = HIGH_LEVEL; + } + else if (volume_percent == 0.0) { + state = ZERO_LEVEL; + } + return state; +} + +static pa_cvolume +active_sink_construct_mono_volume (const pa_cvolume* vol) +{ + pa_cvolume new_volume; + pa_cvolume_init(&new_volume); + new_volume.channels = 1; + pa_volume_t max_vol = pa_cvolume_max(vol); + pa_cvolume_set(&new_volume, 1, max_vol); + return new_volume; +} + +void +active_sink_determine_blocking_state (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + if (mute_menu_item_is_muted (priv->mute_menuitem)){ + /** + We don't want to set the current state to blocking + as this is a fire and forget event. + */ + sound_service_dbus_update_sound_state (priv->service, + BLOCKED); + } +} + +gint +active_sink_get_index (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + return priv->index; +} + +gboolean +active_sink_is_populated (ActiveSink* sink) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink); + return (priv->index != -1); +} + +void +active_sink_deactivate (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + priv->current_sound_state = UNAVAILABLE; + sound_service_dbus_update_sound_state (priv->service, + priv->current_sound_state); + mute_menu_item_enable (priv->mute_menuitem, FALSE); + slider_menu_item_enable (priv->volume_slider_menuitem, FALSE); + priv->index = -1; + g_free(priv->name); + priv->name = NULL; +} + +SoundState +active_sink_get_state (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + return priv->current_sound_state; +} + +ActiveSink* +active_sink_new (SoundServiceDbus* service) +{ + ActiveSink* sink = g_object_new (ACTIVE_SINK_TYPE, NULL); + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink); + priv->service = service; + sound_service_dbus_build_sound_menu (service, + mute_menu_item_get_button (priv->mute_menuitem), + DBUSMENU_MENUITEM (priv->volume_slider_menuitem)); + pm_establish_pulse_connection (sink); + return sink; +} diff --git a/src/active-sink.h b/src/active-sink.h new file mode 100644 index 0000000..ab05ebc --- /dev/null +++ b/src/active-sink.h @@ -0,0 +1,72 @@ +/* + * Copyright 2010 Canonical Ltd. + * + * Authors: + * Conor Curran <conor.curran@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ACTIVE_SINK_H__ +#define __ACTIVE_SINK_H__ + +#include <glib.h> +#include <glib-object.h> + +#include "common-defs.h" +#include "sound-service-dbus.h" + +#include <pulse/pulseaudio.h> + +G_BEGIN_DECLS + +#define ACTIVE_SINK_TYPE (active_sink_get_type ()) +#define ACTIVE_SINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ACTIVE_SINK_TYPE, ActiveSink)) +#define ACTIVE_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), ACTIVE_SINK_TYPE, ActiveSinkClass)) +#define IS_ACTIVE_SINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ACTIVE_SINK_TYPE)) +#define IS_ACTIVE_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ACTIVE_SINK_TYPE)) +#define ACTIVE_SINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ACTIVE_SINK_TYPE, ActiveSinkClass)) + +typedef struct _ActiveSink ActiveSink; +typedef struct _ActiveSinkClass ActiveSinkClass; + +struct _ActiveSink { + GObject parent; +}; + +struct _ActiveSinkClass { + GObjectClass parent_class; +}; + +GType active_sink_get_type (void) G_GNUC_CONST; + +void active_sink_populate (ActiveSink* sink, const pa_sink_info* update); +void active_sink_update (ActiveSink* sink, const pa_sink_info* update); + +gboolean active_sink_is_populated (ActiveSink* sink); +void active_sink_determine_blocking_state (ActiveSink* self); + +gint active_sink_get_index (ActiveSink* self); +SoundState active_sink_get_state (ActiveSink* self); + +void active_sink_deactivate (ActiveSink* self); + +void active_sink_update_mute (ActiveSink* self, gboolean mute_update); +void active_sink_update_volume (ActiveSink* self, gdouble percent); +void active_sink_ensure_sink_is_unmuted (ActiveSink* self); + +ActiveSink* active_sink_new (SoundServiceDbus* service); + +G_END_DECLS + +#endif diff --git a/src/common-defs.h b/src/common-defs.h index 5458dc5..63d9d40 100644 --- a/src/common-defs.h +++ b/src/common-defs.h @@ -64,4 +64,6 @@ typedef enum { #define DBUSMENU_PLAYLISTS_MENUITEM_TITLE "x-canonical-sound-menu-player-playlists-title" #define DBUSMENU_PLAYLISTS_MENUITEM_PLAYLISTS "x-canonical-sound-menu-player-playlists-playlists" +#define DBUSMENU_PLAYLIST_MENUITEM_PATH "x-canonical-sound-menu-player-playlist-path" + #endif diff --git a/src/freedesktop-interfaces.c b/src/freedesktop-interfaces.c index d5bac9a..49d0be2 100644 --- a/src/freedesktop-interfaces.c +++ b/src/freedesktop-interfaces.c @@ -233,21 +233,21 @@ static void free_desktop_object_proxy_class_init (FreeDesktopObjectProxyClass* k static void _dbus_handle_free_desktop_object_name_owner_changed (FreeDesktopObject* self, GVariant* parameters) { GVariantIter _arguments_iter; gchar* name = NULL; - GVariant* _tmp69_; + GVariant* _tmp76_; gchar* old_owner = NULL; - GVariant* _tmp70_; + GVariant* _tmp77_; gchar* new_owner = NULL; - GVariant* _tmp71_; + GVariant* _tmp78_; g_variant_iter_init (&_arguments_iter, parameters); - _tmp69_ = g_variant_iter_next_value (&_arguments_iter); - name = g_variant_dup_string (_tmp69_, NULL); - g_variant_unref (_tmp69_); - _tmp70_ = g_variant_iter_next_value (&_arguments_iter); - old_owner = g_variant_dup_string (_tmp70_, NULL); - g_variant_unref (_tmp70_); - _tmp71_ = g_variant_iter_next_value (&_arguments_iter); - new_owner = g_variant_dup_string (_tmp71_, NULL); - g_variant_unref (_tmp71_); + _tmp76_ = g_variant_iter_next_value (&_arguments_iter); + name = g_variant_dup_string (_tmp76_, NULL); + g_variant_unref (_tmp76_); + _tmp77_ = g_variant_iter_next_value (&_arguments_iter); + old_owner = g_variant_dup_string (_tmp77_, NULL); + g_variant_unref (_tmp77_); + _tmp78_ = g_variant_iter_next_value (&_arguments_iter); + new_owner = g_variant_dup_string (_tmp78_, NULL); + g_variant_unref (_tmp78_); g_signal_emit_by_name (self, "name-owner-changed", name, old_owner, new_owner); _g_free0 (name); _g_free0 (old_owner); @@ -293,13 +293,13 @@ static gchar** free_desktop_object_proxy_list_names_finish (FreeDesktopObject* s GVariantIter _reply_iter; gchar** _result; int _result_length1; - GVariant* _tmp72_; - gchar** _tmp73_; - int _tmp73__length; - int _tmp73__size; - int _tmp73__length1; - GVariantIter _tmp74_; - GVariant* _tmp75_; + GVariant* _tmp79_; + gchar** _tmp80_; + int _tmp80__length; + int _tmp80__size; + int _tmp80__length1; + GVariantIter _tmp81_; + GVariant* _tmp82_; _reply_message = g_dbus_connection_send_message_with_reply_finish (g_dbus_proxy_get_connection ((GDBusProxy *) self), g_simple_async_result_get_op_res_gpointer ((GSimpleAsyncResult *) _res_), error); if (!_reply_message) { return NULL; @@ -311,24 +311,24 @@ static gchar** free_desktop_object_proxy_list_names_finish (FreeDesktopObject* s _reply = g_dbus_message_get_body (_reply_message); g_variant_iter_init (&_reply_iter, _reply); _result_length1 = 0; - _tmp72_ = g_variant_iter_next_value (&_reply_iter); - _tmp73_ = g_new (gchar*, 5); - _tmp73__length = 0; - _tmp73__size = 4; - _tmp73__length1 = 0; - g_variant_iter_init (&_tmp74_, _tmp72_); - for (; (_tmp75_ = g_variant_iter_next_value (&_tmp74_)) != NULL; _tmp73__length1++) { - if (_tmp73__size == _tmp73__length) { - _tmp73__size = 2 * _tmp73__size; - _tmp73_ = g_renew (gchar*, _tmp73_, _tmp73__size + 1); + _tmp79_ = g_variant_iter_next_value (&_reply_iter); + _tmp80_ = g_new (gchar*, 5); + _tmp80__length = 0; + _tmp80__size = 4; + _tmp80__length1 = 0; + g_variant_iter_init (&_tmp81_, _tmp79_); + for (; (_tmp82_ = g_variant_iter_next_value (&_tmp81_)) != NULL; _tmp80__length1++) { + if (_tmp80__size == _tmp80__length) { + _tmp80__size = 2 * _tmp80__size; + _tmp80_ = g_renew (gchar*, _tmp80_, _tmp80__size + 1); } - _tmp73_[_tmp73__length++] = g_variant_dup_string (_tmp75_, NULL); - g_variant_unref (_tmp75_); + _tmp80_[_tmp80__length++] = g_variant_dup_string (_tmp82_, NULL); + g_variant_unref (_tmp82_); } - _result_length1 = _tmp73__length1; - _tmp73_[_tmp73__length] = NULL; - _result = _tmp73_; - g_variant_unref (_tmp72_); + _result_length1 = _tmp80__length1; + _tmp80_[_tmp80__length] = NULL; + _result = _tmp80_; + g_variant_unref (_tmp79_); *result_length1 = _result_length1; g_object_unref (_reply_message); return _result; @@ -356,9 +356,9 @@ static void _dbus_free_desktop_object_list_names_ready (GObject * source_object, GVariantBuilder _reply_builder; gchar** result; int result_length1 = 0; - gchar** _tmp76_; - GVariantBuilder _tmp77_; - int _tmp78_; + gchar** _tmp83_; + GVariantBuilder _tmp84_; + int _tmp85_; invocation = _user_data_; result = free_desktop_object_list_names_finish ((FreeDesktopObject*) source_object, _res_, &result_length1, &error); if (error) { @@ -367,13 +367,13 @@ static void _dbus_free_desktop_object_list_names_ready (GObject * source_object, } _reply_message = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation)); g_variant_builder_init (&_reply_builder, G_VARIANT_TYPE_TUPLE); - _tmp76_ = result; - g_variant_builder_init (&_tmp77_, G_VARIANT_TYPE ("as")); - for (_tmp78_ = 0; _tmp78_ < result_length1; _tmp78_++) { - g_variant_builder_add_value (&_tmp77_, g_variant_new_string (*_tmp76_)); - _tmp76_++; + _tmp83_ = result; + g_variant_builder_init (&_tmp84_, G_VARIANT_TYPE ("as")); + for (_tmp85_ = 0; _tmp85_ < result_length1; _tmp85_++) { + g_variant_builder_add_value (&_tmp84_, g_variant_new_string (*_tmp83_)); + _tmp83_++; } - g_variant_builder_add_value (&_reply_builder, g_variant_builder_end (&_tmp77_)); + g_variant_builder_add_value (&_reply_builder, g_variant_builder_end (&_tmp84_)); result = (_vala_array_free ( result, result_length1, (GDestroyNotify) g_free), NULL); _reply = g_variant_builder_end (&_reply_builder); g_dbus_message_set_body (_reply_message, _reply); @@ -507,7 +507,7 @@ static gchar* free_desktop_introspectable_proxy_Introspect (FreeDesktopIntrospec GVariant *_reply; GVariantIter _reply_iter; gchar* _result; - GVariant* _tmp79_; + GVariant* _tmp86_; G_IO_ERROR; _message = g_dbus_message_new_method_call (g_dbus_proxy_get_name ((GDBusProxy *) self), g_dbus_proxy_get_object_path ((GDBusProxy *) self), "org.freedesktop.DBus.Introspectable", "Introspect"); g_variant_builder_init (&_arguments_builder, G_VARIANT_TYPE_TUPLE); @@ -524,9 +524,9 @@ static gchar* free_desktop_introspectable_proxy_Introspect (FreeDesktopIntrospec } _reply = g_dbus_message_get_body (_reply_message); g_variant_iter_init (&_reply_iter, _reply); - _tmp79_ = g_variant_iter_next_value (&_reply_iter); - _result = g_variant_dup_string (_tmp79_, NULL); - g_variant_unref (_tmp79_); + _tmp86_ = g_variant_iter_next_value (&_reply_iter); + _result = g_variant_dup_string (_tmp86_, NULL); + g_variant_unref (_tmp86_); g_object_unref (_reply_message); return _result; } @@ -671,53 +671,53 @@ static void free_desktop_properties_proxy_class_init (FreeDesktopPropertiesProxy static void _dbus_handle_free_desktop_properties_properties_changed (FreeDesktopProperties* self, GVariant* parameters) { GVariantIter _arguments_iter; gchar* source = NULL; - GVariant* _tmp80_; + GVariant* _tmp87_; GHashTable* changed_properties = NULL; - GVariant* _tmp81_; - GHashTable* _tmp82_; - GVariantIter _tmp83_; - GVariant* _tmp84_; - GVariant* _tmp85_; + GVariant* _tmp88_; + GHashTable* _tmp89_; + GVariantIter _tmp90_; + GVariant* _tmp91_; + GVariant* _tmp92_; gchar** invalid = NULL; int invalid_length1; - GVariant* _tmp86_; - gchar** _tmp87_; - int _tmp87__length; - int _tmp87__size; - int _tmp87__length1; - GVariantIter _tmp88_; - GVariant* _tmp89_; + GVariant* _tmp93_; + gchar** _tmp94_; + int _tmp94__length; + int _tmp94__size; + int _tmp94__length1; + GVariantIter _tmp95_; + GVariant* _tmp96_; g_variant_iter_init (&_arguments_iter, parameters); - _tmp80_ = g_variant_iter_next_value (&_arguments_iter); - source = g_variant_dup_string (_tmp80_, NULL); - g_variant_unref (_tmp80_); - _tmp81_ = g_variant_iter_next_value (&_arguments_iter); - _tmp82_ = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_variant_iter_init (&_tmp83_, _tmp81_); - while (g_variant_iter_loop (&_tmp83_, "{?*}", &_tmp84_, &_tmp85_)) { - g_hash_table_insert (_tmp82_, g_variant_dup_string (_tmp84_, NULL), g_variant_get_variant (_tmp85_)); + _tmp87_ = g_variant_iter_next_value (&_arguments_iter); + source = g_variant_dup_string (_tmp87_, NULL); + g_variant_unref (_tmp87_); + _tmp88_ = g_variant_iter_next_value (&_arguments_iter); + _tmp89_ = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_variant_iter_init (&_tmp90_, _tmp88_); + while (g_variant_iter_loop (&_tmp90_, "{?*}", &_tmp91_, &_tmp92_)) { + g_hash_table_insert (_tmp89_, g_variant_dup_string (_tmp91_, NULL), g_variant_get_variant (_tmp92_)); } - changed_properties = _tmp82_; - g_variant_unref (_tmp81_); + changed_properties = _tmp89_; + g_variant_unref (_tmp88_); invalid_length1 = 0; - _tmp86_ = g_variant_iter_next_value (&_arguments_iter); - _tmp87_ = g_new (gchar*, 5); - _tmp87__length = 0; - _tmp87__size = 4; - _tmp87__length1 = 0; - g_variant_iter_init (&_tmp88_, _tmp86_); - for (; (_tmp89_ = g_variant_iter_next_value (&_tmp88_)) != NULL; _tmp87__length1++) { - if (_tmp87__size == _tmp87__length) { - _tmp87__size = 2 * _tmp87__size; - _tmp87_ = g_renew (gchar*, _tmp87_, _tmp87__size + 1); + _tmp93_ = g_variant_iter_next_value (&_arguments_iter); + _tmp94_ = g_new (gchar*, 5); + _tmp94__length = 0; + _tmp94__size = 4; + _tmp94__length1 = 0; + g_variant_iter_init (&_tmp95_, _tmp93_); + for (; (_tmp96_ = g_variant_iter_next_value (&_tmp95_)) != NULL; _tmp94__length1++) { + if (_tmp94__size == _tmp94__length) { + _tmp94__size = 2 * _tmp94__size; + _tmp94_ = g_renew (gchar*, _tmp94_, _tmp94__size + 1); } - _tmp87_[_tmp87__length++] = g_variant_dup_string (_tmp89_, NULL); - g_variant_unref (_tmp89_); + _tmp94_[_tmp94__length++] = g_variant_dup_string (_tmp96_, NULL); + g_variant_unref (_tmp96_); } - invalid_length1 = _tmp87__length1; - _tmp87_[_tmp87__length] = NULL; - invalid = _tmp87_; - g_variant_unref (_tmp86_); + invalid_length1 = _tmp94__length1; + _tmp94_[_tmp94__length] = NULL; + invalid = _tmp94_; + g_variant_unref (_tmp93_); g_signal_emit_by_name (self, "properties-changed", source, changed_properties, invalid, invalid_length1); _g_free0 (source); _g_hash_table_unref0 (changed_properties); @@ -772,34 +772,34 @@ static void _dbus_free_desktop_properties_properties_changed (GObject* _sender, const gchar * _path; GVariant *_arguments; GVariantBuilder _arguments_builder; - GVariantBuilder _tmp90_; - GHashTableIter _tmp91_; - gpointer _tmp92_; - gpointer _tmp93_; - gchar** _tmp94_; - GVariantBuilder _tmp95_; - int _tmp96_; + GVariantBuilder _tmp97_; + GHashTableIter _tmp98_; + gpointer _tmp99_; + gpointer _tmp100_; + gchar** _tmp101_; + GVariantBuilder _tmp102_; + int _tmp103_; _connection = _data[1]; _path = _data[2]; g_variant_builder_init (&_arguments_builder, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value (&_arguments_builder, g_variant_new_string (source)); - g_hash_table_iter_init (&_tmp91_, changed_properties); - g_variant_builder_init (&_tmp90_, G_VARIANT_TYPE ("a{sv}")); - while (g_hash_table_iter_next (&_tmp91_, &_tmp92_, &_tmp93_)) { + g_hash_table_iter_init (&_tmp98_, changed_properties); + g_variant_builder_init (&_tmp97_, G_VARIANT_TYPE ("a{sv}")); + while (g_hash_table_iter_next (&_tmp98_, &_tmp99_, &_tmp100_)) { gchar* _key; GVariant* _value; - _key = (gchar*) _tmp92_; - _value = (GVariant*) _tmp93_; - g_variant_builder_add (&_tmp90_, "{?*}", g_variant_new_string (_key), g_variant_new_variant (_value)); + _key = (gchar*) _tmp99_; + _value = (GVariant*) _tmp100_; + g_variant_builder_add (&_tmp97_, "{?*}", g_variant_new_string (_key), g_variant_new_variant (_value)); } - g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp90_)); - _tmp94_ = invalid; - g_variant_builder_init (&_tmp95_, G_VARIANT_TYPE ("as")); - for (_tmp96_ = 0; _tmp96_ < invalid_length1; _tmp96_++) { - g_variant_builder_add_value (&_tmp95_, g_variant_new_string (*_tmp94_)); - _tmp94_++; + g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp97_)); + _tmp101_ = invalid; + g_variant_builder_init (&_tmp102_, G_VARIANT_TYPE ("as")); + for (_tmp103_ = 0; _tmp103_ < invalid_length1; _tmp103_++) { + g_variant_builder_add_value (&_tmp102_, g_variant_new_string (*_tmp101_)); + _tmp101_++; } - g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp95_)); + g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp102_)); _arguments = g_variant_builder_end (&_arguments_builder); g_dbus_connection_emit_signal (_connection, NULL, _path, "org.freedesktop.DBus.Properties", "PropertiesChanged", _arguments, NULL); } diff --git a/src/gen-sound-service.xml.c b/src/gen-sound-service.xml.c index 6d7be97..ebd7879 100644 --- a/src/gen-sound-service.xml.c +++ b/src/gen-sound-service.xml.c @@ -3,12 +3,13 @@ const char * _sound_service = "<node name=\"/com/canonical/indicators/sound\">\n" " <interface name=\"com.canonical.indicators.sound\">\n" " <method name = \"BlacklistMediaPlayer\">\n" -" <annotation name=\"org.freedesktop.DBus.GLib.CSymbol\" value=\"sound_service_dbus_blacklist_media_player\"/>\n" +" <annotation name=\"org.freedesktop.DBus.GLib.Async\" value=\"true\"/>\n" " <arg type='s' name='player_desktop_name' direction=\"in\"/>\n" " <arg type='b' name='blacklist' direction=\"in\"/>\n" +" <arg type='b' name='result' direction=\"out\"/>\n" " </method>\n" " <method name = \"GetSoundState\">\n" -" <annotation name=\"org.freedesktop.DBus.GLib.CSymbol\" value=\"sound_service_dbus_get_sink_state\"/>\n" +" <annotation name=\"org.freedesktop.DBus.GLib.Async\" value=\"true\"/>\n" " <arg type='i' name='current_state' direction=\"out\"/>\n" " </method>\n" " <signal name=\"SoundStateUpdate\">\n" diff --git a/src/indicator-sound.c b/src/indicator-sound.c index f259dfd..7e5ebc7 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -133,7 +133,7 @@ indicator_sound_init (IndicatorSound *self) GList* t_list = NULL; priv->transport_widgets_list = t_list; priv->state_manager = g_object_new (SOUND_TYPE_STATE_MANAGER, NULL); - + g_signal_connect ( G_OBJECT(self->service), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_changed), self ); @@ -149,7 +149,6 @@ indicator_sound_dispose (GObject *object) g_object_unref(G_OBJECT(self->service)); self->service = NULL; } - g_list_free ( priv->transport_widgets_list ); G_OBJECT_CLASS (indicator_sound_parent_class)->dispose (object); @@ -402,7 +401,9 @@ new_volume_slider_widget(DbusmenuMenuitem * newitem, newitem, menu_volume_item, parent); - return TRUE; + sound_state_manager_attach_notification_to_volume_widget (priv->state_manager, + volume_widget); + return TRUE; } /*******************************************************************/ @@ -563,7 +564,6 @@ key_release_cb(GtkWidget* widget, GdkEventKey* event, gpointer data) return digested; } - static void indicator_sound_scroll (IndicatorObject *io, gint delta, IndicatorScrollDirection direction) @@ -589,5 +589,7 @@ indicator_sound_scroll (IndicatorObject *io, gint delta, value -= adj->step_increment; } //g_debug("indicator-sound-scroll - update slider with value %f", value); - volume_widget_update(VOLUME_WIDGET(priv->volume_widget), value); + volume_widget_update(VOLUME_WIDGET(priv->volume_widget), value); + + sound_state_manager_show_notification (priv->state_manager, value); } diff --git a/src/indicator-sound.h b/src/indicator-sound.h index ecc38fb..40a3e6f 100644 --- a/src/indicator-sound.h +++ b/src/indicator-sound.h @@ -23,6 +23,8 @@ PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "config.h" + #include <libindicator/indicator.h> #include <libindicator/indicator-object.h> #include <libindicator/indicator-service-manager.h> @@ -51,11 +53,4 @@ struct _IndicatorSound { // GObject Boiler plate GType indicator_sound_get_type (void); -void prepare_state_machine(); -extern void determine_state_from_volume(gdouble volume_percent); -gint get_state(); -gchar* get_state_image_name(gint state); -void prepare_for_tests(IndicatorObject * io); -void tidy_up_hash(); - #endif diff --git a/src/mpris2-controller.c b/src/mpris2-controller.c index fa57af3..08d0722 100644 --- a/src/mpris2-controller.c +++ b/src/mpris2-controller.c @@ -127,10 +127,19 @@ typedef struct _TransportMenuitem TransportMenuitem; typedef struct _TransportMenuitemClass TransportMenuitemClass; #define _g_free0(var) (var = (g_free (var), NULL)) #define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL))) + +#define TYPE_TITLE_MENUITEM (title_menuitem_get_type ()) +#define TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TITLE_MENUITEM, TitleMenuitem)) +#define TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) +#define IS_TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TITLE_MENUITEM)) +#define IS_TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TITLE_MENUITEM)) +#define TITLE_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) + +typedef struct _TitleMenuitem TitleMenuitem; +typedef struct _TitleMenuitemClass TitleMenuitemClass; #define _g_variant_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_unref (var), NULL))) #define TRANSPORT_MENUITEM_TYPE_ACTION (transport_menuitem_action_get_type ()) -#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) #define TYPE_PLAYLISTS_MENUITEM (playlists_menuitem_get_type ()) #define PLAYLISTS_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYLISTS_MENUITEM, PlaylistsMenuitem)) @@ -141,6 +150,7 @@ typedef struct _TransportMenuitemClass TransportMenuitemClass; typedef struct _PlaylistsMenuitem PlaylistsMenuitem; typedef struct _PlaylistsMenuitemClass PlaylistsMenuitemClass; +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) typedef struct _Mpris2ControllerFetchPlaylistsData Mpris2ControllerFetchPlaylistsData; struct _Mpris2Controller { @@ -319,8 +329,6 @@ enum { Mpris2Controller* mpris2_controller_new (PlayerController* ctrl); Mpris2Controller* mpris2_controller_construct (GType object_type, PlayerController* ctrl); void mpris2_controller_property_changed_cb (Mpris2Controller* self, const gchar* interface_source, GHashTable* changed_properties, gchar** invalid, int invalid_length1); -PlayerController* mpris2_controller_get_owner (Mpris2Controller* self); -const gchar* player_controller_get_dbus_name (PlayerController* self); #define MPRIS_PREFIX "org.mpris.MediaPlayer2." MprisPlayer* mpris2_controller_get_player (Mpris2Controller* self); gchar* mpris_player_get_PlaybackStatus (MprisPlayer* self); @@ -328,6 +336,7 @@ static gboolean mpris2_controller_ensure_correct_playback_status (Mpris2Controll static gboolean _mpris2_controller_ensure_correct_playback_status_gsource_func (gpointer self); GType transport_menuitem_state_get_type (void) G_GNUC_CONST; static TransportMenuitemstate mpris2_controller_determine_play_state (Mpris2Controller* self, const gchar* status); +PlayerController* mpris2_controller_get_owner (Mpris2Controller* self); GType player_item_get_type (void) G_GNUC_CONST; GType player_controller_widget_order_get_type (void) G_GNUC_CONST; GType transport_menuitem_get_type (void) G_GNUC_CONST; @@ -338,9 +347,14 @@ GeeHashSet* metadata_menuitem_attributes_format (void); void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes); gboolean player_item_populated (PlayerItem* self, GeeHashSet* attrs); static gboolean _bool_equal (const gboolean* s1, const gboolean* s2); -static void mpris2_controller_fetch_active_playlist (Mpris2Controller* self); +static gboolean mpris2_controller_fetch_active_playlist (Mpris2Controller* self); +static gboolean _mpris2_controller_fetch_active_playlist_gsource_func (gpointer self); void mpris2_controller_fetch_playlists (Mpris2Controller* self, GAsyncReadyCallback _callback_, gpointer _user_data_); void mpris2_controller_fetch_playlists_finish (Mpris2Controller* self, GAsyncResult* _res_); +GType title_menuitem_get_type (void) G_GNUC_CONST; +void title_menuitem_alter_label (TitleMenuitem* self, const gchar* new_title); +MprisRoot* mpris2_controller_get_mpris2_root (Mpris2Controller* self); +gchar* mpris_root_get_Identity (MprisRoot* self); GHashTable* mpris_player_get_Metadata (MprisPlayer* self); static GVariant* _variant_new1 (const gchar* value); static const gchar* _variant_get2 (GVariant* value); @@ -354,10 +368,12 @@ void mpris_player_Previous_finish (MprisPlayer* self, GAsyncResult* _res_, GErro void mpris_player_Next (MprisPlayer* self, GAsyncReadyCallback _callback_, gpointer _user_data_); void mpris_player_Next_finish (MprisPlayer* self, GAsyncResult* _res_, GError** error); gboolean mpris2_controller_connected (Mpris2Controller* self); -MprisRoot* mpris2_controller_get_mpris2_root (Mpris2Controller* self); void mpris2_controller_expose (Mpris2Controller* self); void mpris_root_Raise (MprisRoot* self, GAsyncReadyCallback _callback_, gpointer _user_data_); void mpris_root_Raise_finish (MprisRoot* self, GAsyncResult* _res_, GError** error); +static void mpris2_controller_on_playlistdetails_changed (Mpris2Controller* self, PlaylistDetails* details); +GType playlists_menuitem_get_type (void) G_GNUC_CONST; +void playlists_menuitem_update_individual_playlist (PlaylistsMenuitem* self, PlaylistDetails* new_detail); static void mpris2_controller_fetch_playlists_data_free (gpointer _data); static gboolean mpris2_controller_fetch_playlists_co (Mpris2ControllerFetchPlaylistsData* data); MprisPlaylists* mpris2_controller_get_playlists (Mpris2Controller* self); @@ -365,7 +381,6 @@ void mpris_playlists_GetPlaylists (MprisPlaylists* self, guint32 index, guint32 PlaylistDetails* mpris_playlists_GetPlaylists_finish (MprisPlaylists* self, GAsyncResult* _res_, int* result_length1, GError** error); static void mpris2_controller_fetch_playlists_ready (GObject* source_object, GAsyncResult* _res_, gpointer _user_data_); static void _vala_PlaylistDetails_array_free (PlaylistDetails* array, gint array_length); -GType playlists_menuitem_get_type (void) G_GNUC_CONST; void playlists_menuitem_update (PlaylistsMenuitem* self, PlaylistDetails* playlists, int playlists_length1); static gboolean* _bool_dup (gboolean* self); void mpris_playlists_get_ActivePlaylist (MprisPlaylists* self, ActivePlaylistContainer* result); @@ -380,6 +395,8 @@ FreeDesktopProperties* mpris2_controller_get_properties_interface (Mpris2Control static void mpris2_controller_set_properties_interface (Mpris2Controller* self, FreeDesktopProperties* value); static void mpris2_controller_set_owner (Mpris2Controller* self, PlayerController* value); static GObject * mpris2_controller_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties); +const gchar* player_controller_get_dbus_name (PlayerController* self); +static void _mpris2_controller_on_playlistdetails_changed_mpris_playlists_playlist_changed (MprisPlaylists* _sender, PlaylistDetails* details, gpointer self); static void _mpris2_controller_property_changed_cb_free_desktop_properties_properties_changed (FreeDesktopProperties* _sender, const gchar* source, GHashTable* changed_properties, gchar** invalid, int invalid_length1, gpointer self); static void mpris2_controller_finalize (GObject* obj); static void _vala_mpris2_controller_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); @@ -427,140 +444,164 @@ static gboolean _bool_equal (const gboolean* s1, const gboolean* s2) { } +static gboolean _mpris2_controller_fetch_active_playlist_gsource_func (gpointer self) { + gboolean result; + result = mpris2_controller_fetch_active_playlist (self); + return result; +} + + void mpris2_controller_property_changed_cb (Mpris2Controller* self, const gchar* interface_source, GHashTable* changed_properties, gchar** invalid, int invalid_length1) { - const gchar* _tmp0_ = NULL; - gboolean _tmp1_ = FALSE; - gconstpointer _tmp3_ = NULL; - GVariant* _tmp4_; + gboolean _tmp0_ = FALSE; + gconstpointer _tmp2_ = NULL; + GVariant* _tmp3_; GVariant* play_v; - gconstpointer _tmp10_ = NULL; - GVariant* _tmp11_; + gconstpointer _tmp9_ = NULL; + GVariant* _tmp10_; GVariant* meta_v; - gconstpointer _tmp21_ = NULL; - GVariant* _tmp22_; + gconstpointer _tmp20_ = NULL; + GVariant* _tmp21_; GVariant* playlist_v; - gboolean _tmp23_ = FALSE; - gconstpointer _tmp25_ = NULL; - GVariant* _tmp26_; + gboolean _tmp22_ = FALSE; + gconstpointer _tmp24_ = NULL; + GVariant* _tmp25_; GVariant* playlist_count_v; - gboolean _tmp27_ = FALSE; - gconstpointer _tmp29_ = NULL; - GVariant* _tmp30_; + gboolean _tmp26_ = FALSE; + gconstpointer _tmp28_ = NULL; + GVariant* _tmp29_; GVariant* playlist_orderings_v; - gboolean _tmp31_ = FALSE; + gboolean _tmp30_ = FALSE; + gconstpointer _tmp32_ = NULL; + GVariant* _tmp33_; + GVariant* identity_v; g_return_if_fail (self != NULL); g_return_if_fail (interface_source != NULL); g_return_if_fail (changed_properties != NULL); - _tmp0_ = player_controller_get_dbus_name (self->priv->_owner); - g_debug ("mpris2-controller.vala:66: properties-changed for interface %s and own" \ -"er %s", interface_source, _tmp0_); if (changed_properties == NULL) { - _tmp1_ = TRUE; + _tmp0_ = TRUE; } else { - gboolean _tmp2_; - _tmp2_ = g_str_has_prefix (interface_source, MPRIS_PREFIX); - _tmp1_ = _tmp2_ == FALSE; + gboolean _tmp1_; + _tmp1_ = g_str_has_prefix (interface_source, MPRIS_PREFIX); + _tmp0_ = _tmp1_ == FALSE; } - if (_tmp1_) { - g_warning ("mpris2-controller.vala:69: Property-changed hash is null or this is an" \ + if (_tmp0_) { + g_warning ("mpris2-controller.vala:70: Property-changed hash is null or this is an" \ " interface that doesn't concerns us"); return; } - _tmp3_ = g_hash_table_lookup (changed_properties, "PlaybackStatus"); - _tmp4_ = _g_variant_ref0 ((GVariant*) _tmp3_); - play_v = _tmp4_; + _tmp2_ = g_hash_table_lookup (changed_properties, "PlaybackStatus"); + _tmp3_ = _g_variant_ref0 ((GVariant*) _tmp2_); + play_v = _tmp3_; if (play_v != NULL) { - gchar* _tmp5_ = NULL; + gchar* _tmp4_ = NULL; gchar* state; - TransportMenuitemstate _tmp6_; + TransportMenuitemstate _tmp5_; TransportMenuitemstate p; - gpointer _tmp7_ = NULL; - PlayerItem* _tmp8_; - TransportMenuitem* _tmp9_; - _tmp5_ = mpris_player_get_PlaybackStatus (self->priv->_player); - state = _tmp5_; + gpointer _tmp6_ = NULL; + PlayerItem* _tmp7_; + TransportMenuitem* _tmp8_; + _tmp4_ = mpris_player_get_PlaybackStatus (self->priv->_player); + state = _tmp4_; g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 200, _mpris2_controller_ensure_correct_playback_status_gsource_func, g_object_ref (self), g_object_unref); - _tmp6_ = mpris2_controller_determine_play_state (self, state); - p = (TransportMenuitemstate) _tmp6_; - _tmp7_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT); - _tmp9_ = (_tmp8_ = (PlayerItem*) _tmp7_, IS_TRANSPORT_MENUITEM (_tmp8_) ? ((TransportMenuitem*) _tmp8_) : NULL); - transport_menuitem_change_play_state (_tmp9_, p); - _g_object_unref0 (_tmp9_); + _tmp5_ = mpris2_controller_determine_play_state (self, state); + p = (TransportMenuitemstate) _tmp5_; + _tmp6_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT); + _tmp8_ = (_tmp7_ = (PlayerItem*) _tmp6_, IS_TRANSPORT_MENUITEM (_tmp7_) ? ((TransportMenuitem*) _tmp7_) : NULL); + transport_menuitem_change_play_state (_tmp8_, p); + _g_object_unref0 (_tmp8_); _g_free0 (state); } - _tmp10_ = g_hash_table_lookup (changed_properties, "Metadata"); - _tmp11_ = _g_variant_ref0 ((GVariant*) _tmp10_); - meta_v = _tmp11_; + _tmp9_ = g_hash_table_lookup (changed_properties, "Metadata"); + _tmp10_ = _g_variant_ref0 ((GVariant*) _tmp9_); + meta_v = _tmp10_; if (meta_v != NULL) { - GHashTable* _tmp12_ = NULL; + GHashTable* _tmp11_ = NULL; GHashTable* changed_updates; - gpointer _tmp13_ = NULL; + gpointer _tmp12_ = NULL; PlayerItem* metadata; - GeeHashSet* _tmp14_ = NULL; - GeeHashSet* _tmp15_; - GeeHashSet* _tmp16_ = NULL; - GeeHashSet* _tmp17_; - GeeHashSet* _tmp18_ = NULL; - GeeHashSet* _tmp19_; - gboolean _tmp20_; - _tmp12_ = mpris2_controller_clean_metadata (self); - changed_updates = _tmp12_; - _tmp13_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA); - metadata = (PlayerItem*) _tmp13_; - _tmp14_ = metadata_menuitem_attributes_format (); - _tmp15_ = _tmp14_; - player_item_reset (metadata, _tmp15_); - _g_object_unref0 (_tmp15_); - _tmp16_ = metadata_menuitem_attributes_format (); - _tmp17_ = _tmp16_; - player_item_update (metadata, changed_updates, _tmp17_); - _g_object_unref0 (_tmp17_); - _tmp18_ = metadata_menuitem_attributes_format (); - _tmp19_ = _tmp18_; - _tmp20_ = player_item_populated (metadata, _tmp19_); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) metadata, DBUSMENU_MENUITEM_PROP_VISIBLE, _tmp20_); - _g_object_unref0 (_tmp19_); + GeeHashSet* _tmp13_ = NULL; + GeeHashSet* _tmp14_; + GeeHashSet* _tmp15_ = NULL; + GeeHashSet* _tmp16_; + GeeHashSet* _tmp17_ = NULL; + GeeHashSet* _tmp18_; + gboolean _tmp19_; + _tmp11_ = mpris2_controller_clean_metadata (self); + changed_updates = _tmp11_; + _tmp12_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA); + metadata = (PlayerItem*) _tmp12_; + _tmp13_ = metadata_menuitem_attributes_format (); + _tmp14_ = _tmp13_; + player_item_reset (metadata, _tmp14_); + _g_object_unref0 (_tmp14_); + _tmp15_ = metadata_menuitem_attributes_format (); + _tmp16_ = _tmp15_; + player_item_update (metadata, changed_updates, _tmp16_); + _g_object_unref0 (_tmp16_); + _tmp17_ = metadata_menuitem_attributes_format (); + _tmp18_ = _tmp17_; + _tmp19_ = player_item_populated (metadata, _tmp18_); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) metadata, DBUSMENU_MENUITEM_PROP_VISIBLE, _tmp19_); + _g_object_unref0 (_tmp18_); _g_object_unref0 (metadata); _g_hash_table_unref0 (changed_updates); } - _tmp21_ = g_hash_table_lookup (changed_properties, "ActivePlaylist"); - _tmp22_ = _g_variant_ref0 ((GVariant*) _tmp21_); - playlist_v = _tmp22_; + _tmp20_ = g_hash_table_lookup (changed_properties, "ActivePlaylist"); + _tmp21_ = _g_variant_ref0 ((GVariant*) _tmp20_); + playlist_v = _tmp21_; if (playlist_v != NULL) { - gboolean _tmp24_; - _tmp23_ = _bool_equal (self->priv->_owner->use_playlists, (_tmp24_ = TRUE, &_tmp24_)) == TRUE; + gboolean _tmp23_; + _tmp22_ = _bool_equal (self->priv->_owner->use_playlists, (_tmp23_ = TRUE, &_tmp23_)) == TRUE; } else { - _tmp23_ = FALSE; + _tmp22_ = FALSE; } - if (_tmp23_) { - mpris2_controller_fetch_active_playlist (self); + if (_tmp22_) { + g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 300, _mpris2_controller_fetch_active_playlist_gsource_func, g_object_ref (self), g_object_unref); } - _tmp25_ = g_hash_table_lookup (changed_properties, "PlaylistCount"); - _tmp26_ = _g_variant_ref0 ((GVariant*) _tmp25_); - playlist_count_v = _tmp26_; + _tmp24_ = g_hash_table_lookup (changed_properties, "PlaylistCount"); + _tmp25_ = _g_variant_ref0 ((GVariant*) _tmp24_); + playlist_count_v = _tmp25_; if (playlist_count_v != NULL) { - gboolean _tmp28_; - _tmp27_ = _bool_equal (self->priv->_owner->use_playlists, (_tmp28_ = TRUE, &_tmp28_)) == TRUE; + gboolean _tmp27_; + _tmp26_ = _bool_equal (self->priv->_owner->use_playlists, (_tmp27_ = TRUE, &_tmp27_)) == TRUE; } else { - _tmp27_ = FALSE; + _tmp26_ = FALSE; } - if (_tmp27_) { + if (_tmp26_) { mpris2_controller_fetch_playlists (self, NULL, NULL); mpris2_controller_fetch_active_playlist (self); } - _tmp29_ = g_hash_table_lookup (changed_properties, "Orderings"); - _tmp30_ = _g_variant_ref0 ((GVariant*) _tmp29_); - playlist_orderings_v = _tmp30_; + _tmp28_ = g_hash_table_lookup (changed_properties, "Orderings"); + _tmp29_ = _g_variant_ref0 ((GVariant*) _tmp28_); + playlist_orderings_v = _tmp29_; if (playlist_orderings_v != NULL) { - gboolean _tmp32_; - _tmp31_ = _bool_equal (self->priv->_owner->use_playlists, (_tmp32_ = TRUE, &_tmp32_)) == TRUE; + gboolean _tmp31_; + _tmp30_ = _bool_equal (self->priv->_owner->use_playlists, (_tmp31_ = TRUE, &_tmp31_)) == TRUE; } else { - _tmp31_ = FALSE; + _tmp30_ = FALSE; } - if (_tmp31_) { + if (_tmp30_) { mpris2_controller_fetch_playlists (self, NULL, NULL); mpris2_controller_fetch_active_playlist (self); } + _tmp32_ = g_hash_table_lookup (changed_properties, "Identity"); + _tmp33_ = _g_variant_ref0 ((GVariant*) _tmp32_); + identity_v = _tmp33_; + if (identity_v != NULL) { + gpointer _tmp34_ = NULL; + PlayerItem* _tmp35_; + TitleMenuitem* title; + gchar* _tmp36_ = NULL; + gchar* _tmp37_; + _tmp34_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TITLE); + title = (_tmp35_ = (PlayerItem*) _tmp34_, IS_TITLE_MENUITEM (_tmp35_) ? ((TitleMenuitem*) _tmp35_) : NULL); + _tmp36_ = mpris_root_get_Identity (self->priv->_mpris2_root); + _tmp37_ = _tmp36_; + title_menuitem_alter_label (title, _tmp37_); + _g_free0 (_tmp37_); + _g_object_unref0 (title); + } + _g_variant_unref0 (identity_v); _g_variant_unref0 (playlist_orderings_v); _g_variant_unref0 (playlist_count_v); _g_variant_unref0 (playlist_v); @@ -573,27 +614,21 @@ static gboolean mpris2_controller_ensure_correct_playback_status (Mpris2Controll gboolean result = FALSE; gchar* _tmp0_ = NULL; gchar* _tmp1_; - gchar* _tmp2_ = NULL; - gchar* _tmp3_; - TransportMenuitemstate _tmp4_; - TransportMenuitemstate _tmp5_; + TransportMenuitemstate _tmp2_; + TransportMenuitemstate _tmp3_; TransportMenuitemstate p; - gpointer _tmp6_ = NULL; - PlayerItem* _tmp7_; - TransportMenuitem* _tmp8_; + gpointer _tmp4_ = NULL; + PlayerItem* _tmp5_; + TransportMenuitem* _tmp6_; g_return_val_if_fail (self != NULL, FALSE); _tmp0_ = mpris_player_get_PlaybackStatus (self->priv->_player); _tmp1_ = _tmp0_; - g_debug ("mpris2-controller.vala:109: TEST playback status = %s", _tmp1_); - _g_free0 (_tmp1_); - _tmp2_ = mpris_player_get_PlaybackStatus (self->priv->_player); - _tmp3_ = _tmp2_; - _tmp4_ = mpris2_controller_determine_play_state (self, _tmp3_); - p = (_tmp5_ = (TransportMenuitemstate) _tmp4_, _g_free0 (_tmp3_), _tmp5_); - _tmp6_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT); - _tmp8_ = (_tmp7_ = (PlayerItem*) _tmp6_, IS_TRANSPORT_MENUITEM (_tmp7_) ? ((TransportMenuitem*) _tmp7_) : NULL); - transport_menuitem_change_play_state (_tmp8_, p); - _g_object_unref0 (_tmp8_); + _tmp2_ = mpris2_controller_determine_play_state (self, _tmp1_); + p = (_tmp3_ = (TransportMenuitemstate) _tmp2_, _g_free0 (_tmp1_), _tmp3_); + _tmp4_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT); + _tmp6_ = (_tmp5_ = (PlayerItem*) _tmp4_, IS_TRANSPORT_MENUITEM (_tmp5_) ? ((TransportMenuitem*) _tmp5_) : NULL); + transport_menuitem_change_play_state (_tmp6_, p); + _g_object_unref0 (_tmp6_); result = FALSE; return result; } @@ -645,13 +680,13 @@ static GHashTable* mpris2_controller_clean_metadata (Mpris2Controller* self) { _tmp9_ = _g_variant_ref0 ((GVariant*) _tmp8_); v_artists = (_tmp10_ = _tmp9_, _g_hash_table_unref0 (_tmp7_), _tmp10_); _tmp11_ = g_variant_get_type_string (v_artists); - g_debug ("mpris2-controller.vala:121: artists is of type %s", _tmp11_); + g_debug ("mpris2-controller.vala:129: artists is of type %s", _tmp11_); _tmp12_ = g_variant_get_type_string (v_artists); if (g_strcmp0 (_tmp12_, "s") == 0) { const gchar* _tmp13_ = NULL; gchar* _tmp14_; gchar* _tmp15_; - g_debug ("mpris2-controller.vala:124: SPOTIFY is that you ?"); + g_debug ("mpris2-controller.vala:132: SPOTIFY is that you ?"); _tmp13_ = g_variant_get_string (v_artists, NULL); _tmp14_ = g_strdup (_tmp13_); _tmp15_ = _tmp14_; @@ -678,7 +713,7 @@ static GHashTable* mpris2_controller_clean_metadata (Mpris2Controller* self) { _tmp20_ = g_strdup ("xesam:artist"); g_hash_table_replace (changed_updates, _tmp20_, _variant_new1 (display_artists)); _tmp21_ = g_hash_table_lookup (changed_updates, "xesam:artist"); - g_debug ("mpris2-controller.vala:132: artist : %s", _variant_get2 ((GVariant*) _tmp21_)); + g_debug ("mpris2-controller.vala:140: artist : %s", _variant_get2 ((GVariant*) _tmp21_)); _g_free0 (display_artists); _g_variant_unref0 (v_artists); } @@ -711,39 +746,64 @@ void mpris2_controller_initial_update (Mpris2Controller* self) { gchar* _tmp0_ = NULL; gchar* _tmp1_; gboolean _tmp2_; - TransportMenuitemstate _tmp3_; - gpointer _tmp4_ = NULL; - PlayerItem* _tmp5_; - TransportMenuitem* _tmp6_; - GHashTable* _tmp7_ = NULL; + gchar* _tmp6_ = NULL; + gchar* _tmp7_; + gboolean _tmp8_; + gpointer _tmp13_ = NULL; + PlayerItem* _tmp14_; + TransportMenuitem* _tmp15_; + GHashTable* _tmp16_ = NULL; GHashTable* cleaned_metadata; - gpointer _tmp8_ = NULL; - PlayerItem* _tmp9_; - GeeHashSet* _tmp10_ = NULL; - GeeHashSet* _tmp11_; - gboolean _tmp12_; + gpointer _tmp17_ = NULL; + PlayerItem* _tmp18_; + GeeHashSet* _tmp19_ = NULL; + GeeHashSet* _tmp20_; + gboolean _tmp21_; g_return_if_fail (self != NULL); _tmp0_ = mpris_player_get_PlaybackStatus (self->priv->_player); _tmp1_ = _tmp0_; if ((_tmp2_ = _tmp1_ == NULL, _g_free0 (_tmp1_), _tmp2_)) { update = TRANSPORT_MENUITEM_STATE_PAUSED; + } else { + gchar* _tmp3_ = NULL; + gchar* _tmp4_; + TransportMenuitemstate _tmp5_; + _tmp3_ = mpris_player_get_PlaybackStatus (self->priv->_player); + _tmp4_ = _tmp3_; + _tmp5_ = mpris2_controller_determine_play_state (self, _tmp4_); + update = _tmp5_; + _g_free0 (_tmp4_); } - _tmp3_ = mpris2_controller_determine_play_state (self, NULL); - update = _tmp3_; - _tmp4_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT); - _tmp6_ = (_tmp5_ = (PlayerItem*) _tmp4_, IS_TRANSPORT_MENUITEM (_tmp5_) ? ((TransportMenuitem*) _tmp5_) : NULL); - transport_menuitem_change_play_state (_tmp6_, TRANSPORT_MENUITEM_STATE_PAUSED); - _g_object_unref0 (_tmp6_); - _tmp7_ = mpris2_controller_clean_metadata (self); - cleaned_metadata = _tmp7_; - _tmp8_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA); - _tmp9_ = (PlayerItem*) _tmp8_; - _tmp10_ = metadata_menuitem_attributes_format (); - _tmp11_ = _tmp10_; - player_item_update (_tmp9_, cleaned_metadata, _tmp11_); - _g_object_unref0 (_tmp11_); - _g_object_unref0 (_tmp9_); - if (_bool_equal (self->priv->_owner->use_playlists, (_tmp12_ = TRUE, &_tmp12_)) == TRUE) { + _tmp6_ = mpris_root_get_Identity (self->priv->_mpris2_root); + _tmp7_ = _tmp6_; + if ((_tmp8_ = _tmp7_ != NULL, _g_free0 (_tmp7_), _tmp8_)) { + gpointer _tmp9_ = NULL; + PlayerItem* _tmp10_; + TitleMenuitem* title; + gchar* _tmp11_ = NULL; + gchar* _tmp12_; + _tmp9_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TITLE); + title = (_tmp10_ = (PlayerItem*) _tmp9_, IS_TITLE_MENUITEM (_tmp10_) ? ((TitleMenuitem*) _tmp10_) : NULL); + _tmp11_ = mpris_root_get_Identity (self->priv->_mpris2_root); + _tmp12_ = _tmp11_; + title_menuitem_alter_label (title, _tmp12_); + _g_free0 (_tmp12_); + _g_object_unref0 (title); + } + _tmp13_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT); + _tmp15_ = (_tmp14_ = (PlayerItem*) _tmp13_, IS_TRANSPORT_MENUITEM (_tmp14_) ? ((TransportMenuitem*) _tmp14_) : NULL); + transport_menuitem_change_play_state (_tmp15_, update); + _g_object_unref0 (_tmp15_); + _tmp16_ = mpris2_controller_clean_metadata (self); + cleaned_metadata = _tmp16_; + _tmp17_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA); + _tmp18_ = (PlayerItem*) _tmp17_; + _tmp19_ = metadata_menuitem_attributes_format (); + _tmp20_ = _tmp19_; + player_item_update (_tmp18_, cleaned_metadata, _tmp20_); + _g_object_unref0 (_tmp20_); + _g_object_unref0 (_tmp18_); + if (_bool_equal (self->priv->_owner->use_playlists, (_tmp21_ = TRUE, &_tmp21_)) == TRUE) { mpris2_controller_fetch_playlists (self, NULL, NULL); mpris2_controller_fetch_active_playlist (self); } @@ -753,7 +813,6 @@ void mpris2_controller_initial_update (Mpris2Controller* self) { void mpris2_controller_transport_update (Mpris2Controller* self, TransportMenuitemaction command) { g_return_if_fail (self != NULL); - g_debug ("mpris2-controller.vala:166: transport_event input = %i", (gint) command); if (command == TRANSPORT_MENUITEM_ACTION_PLAY_PAUSE) { mpris_player_PlayPause (self->priv->_player, NULL, NULL); } else { @@ -792,6 +851,18 @@ void mpris2_controller_expose (Mpris2Controller* self) { } +static void mpris2_controller_on_playlistdetails_changed (Mpris2Controller* self, PlaylistDetails* details) { + gpointer _tmp0_ = NULL; + PlayerItem* _tmp1_; + PlaylistsMenuitem* playlists_item; + g_return_if_fail (self != NULL); + _tmp0_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_PLAYLISTS); + playlists_item = (_tmp1_ = (PlayerItem*) _tmp0_, IS_PLAYLISTS_MENUITEM (_tmp1_) ? ((PlaylistsMenuitem*) _tmp1_) : NULL); + playlists_menuitem_update_individual_playlist (playlists_item, details); + _g_object_unref0 (playlists_item); +} + + static void mpris2_controller_fetch_playlists_data_free (gpointer _data) { Mpris2ControllerFetchPlaylistsData* data; data = _data; @@ -895,7 +966,7 @@ static gboolean mpris2_controller_fetch_playlists_co (Mpris2ControllerFetchPlayl { data->e = data->_inner_error_; data->_inner_error_ = NULL; - g_debug ("mpris2-controller.vala:202: Could not fetch playlists because %s", data->e->message); + g_debug ("mpris2-controller.vala:220: Could not fetch playlists because %s", data->e->message); _g_error_free0 (data->e); data->current_playlists = (_vala_PlaylistDetails_array_free (data->current_playlists, data->current_playlists_length1), NULL); if (data->_state_ == 0) { @@ -914,14 +985,13 @@ static gboolean mpris2_controller_fetch_playlists_co (Mpris2ControllerFetchPlayl return FALSE; } if (data->current_playlists != NULL) { - g_debug ("mpris2-controller.vala:207: Size of the playlist array = %i", data->current_playlists_length1); data->_tmp4_ = NULL; data->_tmp4_ = gee_abstract_list_get ((GeeAbstractList*) data->self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_PLAYLISTS); data->playlists_item = (data->_tmp5_ = (PlayerItem*) data->_tmp4_, IS_PLAYLISTS_MENUITEM (data->_tmp5_) ? ((PlaylistsMenuitem*) data->_tmp5_) : NULL); playlists_menuitem_update (data->playlists_item, data->current_playlists, data->current_playlists_length1); _g_object_unref0 (data->playlists_item); } else { - g_warning ("mpris2-controller.vala:212: Playlists are on but its returning no cur" \ + g_warning ("mpris2-controller.vala:230: Playlists are on but its returning no cur" \ "rent_playlists"); data->_tmp7_ = __bool_dup0 ((data->_tmp6_ = FALSE, &data->_tmp6_)); data->_tmp8_ = data->_tmp7_; @@ -939,7 +1009,8 @@ static gboolean mpris2_controller_fetch_playlists_co (Mpris2ControllerFetchPlayl } -static void mpris2_controller_fetch_active_playlist (Mpris2Controller* self) { +static gboolean mpris2_controller_fetch_active_playlist (Mpris2Controller* self) { + gboolean result = FALSE; ActivePlaylistContainer _tmp0_ = {0}; ActivePlaylistContainer _tmp1_; gboolean _tmp2_; @@ -948,11 +1019,11 @@ static void mpris2_controller_fetch_active_playlist (Mpris2Controller* self) { PlaylistsMenuitem* playlists_item; ActivePlaylistContainer _tmp5_ = {0}; ActivePlaylistContainer _tmp6_; - g_return_if_fail (self != NULL); + g_return_val_if_fail (self != NULL, FALSE); mpris_playlists_get_ActivePlaylist (self->priv->_playlists, &_tmp0_); _tmp1_ = _tmp0_; if ((_tmp2_ = _tmp1_.valid == FALSE, active_playlist_container_destroy (&_tmp1_), _tmp2_)) { - g_debug ("mpris2-controller.vala:220: We don't have an active playlist"); + g_debug ("mpris2-controller.vala:238: We don't have an active playlist"); } _tmp3_ = gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_PLAYLISTS); playlists_item = (_tmp4_ = (PlayerItem*) _tmp3_, IS_PLAYLISTS_MENUITEM (_tmp4_) ? ((PlaylistsMenuitem*) _tmp4_) : NULL); @@ -960,7 +1031,9 @@ static void mpris2_controller_fetch_active_playlist (Mpris2Controller* self) { _tmp6_ = _tmp5_; playlists_menuitem_update_active_playlist (playlists_item, &_tmp6_.details); active_playlist_container_destroy (&_tmp6_); + result = FALSE; _g_object_unref0 (playlists_item); + return result; } @@ -975,7 +1048,7 @@ void mpris2_controller_activate_playlist (Mpris2Controller* self, const char* pa GError * e; e = _inner_error_; _inner_error_ = NULL; - g_debug ("mpris2-controller.vala:232: Could not activate playlist %s because %s", (const gchar*) path, e->message); + g_debug ("mpris2-controller.vala:251: Could not activate playlist %s because %s", (const gchar*) path, e->message); _g_error_free0 (e); } __finally12: @@ -1087,6 +1160,11 @@ static void mpris2_controller_set_owner (Mpris2Controller* self, PlayerControlle } +static void _mpris2_controller_on_playlistdetails_changed_mpris_playlists_playlist_changed (MprisPlaylists* _sender, PlaylistDetails* details, gpointer self) { + mpris2_controller_on_playlistdetails_changed (self, details); +} + + static void _mpris2_controller_property_changed_cb_free_desktop_properties_properties_changed (FreeDesktopProperties* _sender, const gchar* source, GHashTable* changed_properties, gchar** invalid, int invalid_length1, gpointer self) { mpris2_controller_property_changed_cb (self, source, changed_properties, invalid, invalid_length1); } @@ -1162,6 +1240,7 @@ static GObject * mpris2_controller_constructor (GType type, guint n_construct_pr _tmp15_ = _tmp14_; mpris2_controller_set_playlists (self, _tmp15_); _g_object_unref0 (_tmp15_); + g_signal_connect_object (self->priv->_playlists, "playlist-changed", (GCallback) _mpris2_controller_on_playlistdetails_changed_mpris_playlists_playlist_changed, self, 0); } _tmp16_ = g_initable_new (TYPE_FREE_DESKTOP_PROPERTIES_PROXY, NULL, &_inner_error_, "g-flags", 0, "g-name", "org.freedesktop.Properties.PropertiesChanged", "g-bus-type", G_BUS_TYPE_SESSION, "g-object-path", "/org/mpris/MediaPlayer2", "g-interface-name", "org.freedesktop.DBus.Properties", NULL); _tmp17_ = (FreeDesktopProperties*) _tmp16_; @@ -1182,7 +1261,7 @@ static GObject * mpris2_controller_constructor (GType type, guint n_construct_pr GError * e; e = _inner_error_; _inner_error_ = NULL; - g_error ("mpris2-controller.vala:58: Problems connecting to the session bus - %s", e->message); + g_error ("mpris2-controller.vala:59: Problems connecting to the session bus - %s", e->message); _g_error_free0 (e); } __finally13: diff --git a/src/mpris2-controller.vala b/src/mpris2-controller.vala index 03571e6..bf930fc 100644 --- a/src/mpris2-controller.vala +++ b/src/mpris2-controller.vala @@ -48,6 +48,7 @@ public class Mpris2Controller : GLib.Object this.playlists = Bus.get_proxy_sync ( BusType.SESSION, this.owner.dbus_name, "/org/mpris/MediaPlayer2" ); + this.playlists.PlaylistChanged.connect (on_playlistdetails_changed); } this.properties_interface = Bus.get_proxy_sync ( BusType.SESSION, "org.freedesktop.Properties.PropertiesChanged", @@ -63,7 +64,7 @@ public class Mpris2Controller : GLib.Object HashTable<string, Variant?> changed_properties, string[] invalid ) { - debug("properties-changed for interface %s and owner %s", interface_source, this.owner.dbus_name); + //debug("properties-changed for interface %s and owner %s", interface_source, this.owner.dbus_name); if ( changed_properties == null || interface_source.has_prefix ( MPRIS_PREFIX ) == false ){ warning("Property-changed hash is null or this is an interface that doesn't concerns us"); @@ -91,7 +92,9 @@ public class Mpris2Controller : GLib.Object } Variant? playlist_v = changed_properties.lookup("ActivePlaylist"); if ( playlist_v != null && this.owner.use_playlists == true ){ - this.fetch_active_playlist(); + // Once again A GDBus race condition, the property_changed signal is sent + // before the value is set on the respective property. + Timeout.add (300, this.fetch_active_playlist); } Variant? playlist_count_v = changed_properties.lookup("PlaylistCount"); if ( playlist_count_v != null && this.owner.use_playlists == true ){ @@ -103,10 +106,15 @@ public class Mpris2Controller : GLib.Object this.fetch_playlists.begin(); this.fetch_active_playlist(); } + Variant? identity_v = changed_properties.lookup("Identity"); + if (identity_v != null){ + TitleMenuitem title = this.owner.custom_items[PlayerController.widget_order.TITLE] as TitleMenuitem; + title.alter_label (this.mpris2_root.Identity); + } } - + private bool ensure_correct_playback_status(){ - debug("TEST playback status = %s", this.player.PlaybackStatus); + //debug("TEST playback status = %s", this.player.PlaybackStatus); TransportMenuitem.state p = (TransportMenuitem.state)this.determine_play_state(this.player.PlaybackStatus); (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(p); return false; @@ -144,15 +152,20 @@ public class Mpris2Controller : GLib.Object public void initial_update() { TransportMenuitem.state update; + if(this.player.PlaybackStatus == null){ update = TransportMenuitem.state.PAUSED; } - - update = determine_play_state(null); - - (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(TransportMenuitem.state.PAUSED); + else{ + update = determine_play_state (this.player.PlaybackStatus); + } + if (this.mpris2_root.Identity != null){ + TitleMenuitem title = this.owner.custom_items[PlayerController.widget_order.TITLE] as TitleMenuitem; + title.alter_label (this.mpris2_root.Identity); + } + (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state (update); GLib.HashTable<string, Value?>? cleaned_metadata = this.clean_metadata(); - this.owner.custom_items[PlayerController.widget_order.METADATA].update(cleaned_metadata, + this.owner.custom_items[PlayerController.widget_order.METADATA].update (cleaned_metadata, MetadataMenuitem.attributes_format()); if ( this.owner.use_playlists == true ){ @@ -163,7 +176,7 @@ public class Mpris2Controller : GLib.Object public void transport_update(TransportMenuitem.action command) { - debug("transport_event input = %i", (int)command); + //debug("transport_event input = %i", (int)command); if(command == TransportMenuitem.action.PLAY_PAUSE){ this.player.PlayPause.begin(); } @@ -175,7 +188,6 @@ public class Mpris2Controller : GLib.Object } } - public bool connected() { return (this.player != null && this.mpris2_root != null); @@ -188,6 +200,12 @@ public class Mpris2Controller : GLib.Object } } + private void on_playlistdetails_changed (PlaylistDetails details) + { + PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; + playlists_item.update_individual_playlist (details); + } + public async void fetch_playlists() { PlaylistDetails[] current_playlists = null; @@ -204,7 +222,7 @@ public class Mpris2Controller : GLib.Object } if( current_playlists != null ){ - debug( "Size of the playlist array = %i", current_playlists.length ); + //debug( "Size of the playlist array = %i", current_playlists.length ); PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; playlists_item.update(current_playlists); } @@ -214,13 +232,14 @@ public class Mpris2Controller : GLib.Object } } - private void fetch_active_playlist() + private bool fetch_active_playlist() { if (this.playlists.ActivePlaylist.valid == false){ - debug("We don't have an active playlist"); - } + debug(" We don't have an active playlist"); + } PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; playlists_item.update_active_playlist ( this.playlists.ActivePlaylist.details ); + return false; } public void activate_playlist (ObjectPath path) diff --git a/src/mpris2-interfaces.c b/src/mpris2-interfaces.c index 90941fa..3243404 100644 --- a/src/mpris2-interfaces.c +++ b/src/mpris2-interfaces.c @@ -256,7 +256,9 @@ guint32 mpris_playlists_get_PlaylistCount (MprisPlaylists* self); void mpris_playlists_set_PlaylistCount (MprisPlaylists* self, guint32 value); void mpris_playlists_get_ActivePlaylist (MprisPlaylists* self, ActivePlaylistContainer* result); void mpris_playlists_set_ActivePlaylist (MprisPlaylists* self, ActivePlaylistContainer* value); +static void g_cclosure_user_marshal_VOID__BOXED (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); static void mpris_playlists_proxy_g_signal (GDBusProxy* proxy, const gchar* sender_name, const gchar* signal_name, GVariant* parameters); +static void _dbus_handle_mpris_playlists_playlist_changed (MprisPlaylists* self, GVariant* parameters); static void mpris_playlists_proxy_ActivatePlaylist_async (MprisPlaylists* self, const char* playlist_id, GAsyncReadyCallback _callback_, gpointer _user_data_); static void mpris_playlists_proxy_ActivatePlaylist_finish (MprisPlaylists* self, GAsyncResult* _res_, GError** error); static void mpris_playlists_proxy_GetPlaylists_async (MprisPlaylists* self, guint32 index, guint32 max_count, const gchar* order, gboolean reverse_order, GAsyncReadyCallback _callback_, gpointer _user_data_); @@ -282,6 +284,7 @@ static gboolean mpris_playlists_dbus_interface_set_property (GDBusConnection* co static void _dbus_mpris_playlists_set_Orderings (MprisPlaylists* self, GVariant* _value); static void _dbus_mpris_playlists_set_PlaylistCount (MprisPlaylists* self, GVariant* _value); static void _dbus_mpris_playlists_set_ActivePlaylist (MprisPlaylists* self, GVariant* _value); +static void _dbus_mpris_playlists_playlist_changed (GObject* _sender, PlaylistDetails* details, gpointer* _data); static void _mpris_playlists_unregister_object (gpointer user_data); static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); @@ -335,7 +338,10 @@ static const GDBusArgInfo * const _mpris_playlists_dbus_arg_info_GetPlaylists_in static const GDBusArgInfo * const _mpris_playlists_dbus_arg_info_GetPlaylists_out[] = {&_mpris_playlists_dbus_arg_info_GetPlaylists_result, NULL}; static const GDBusMethodInfo _mpris_playlists_dbus_method_info_GetPlaylists = {-1, "GetPlaylists", (GDBusArgInfo **) (&_mpris_playlists_dbus_arg_info_GetPlaylists_in), (GDBusArgInfo **) (&_mpris_playlists_dbus_arg_info_GetPlaylists_out)}; static const GDBusMethodInfo * const _mpris_playlists_dbus_method_info[] = {&_mpris_playlists_dbus_method_info_ActivatePlaylist, &_mpris_playlists_dbus_method_info_GetPlaylists, NULL}; -static const GDBusSignalInfo * const _mpris_playlists_dbus_signal_info[] = {NULL}; +static const GDBusArgInfo _mpris_playlists_dbus_arg_info_playlist_changed_details = {-1, "details", "(oss)"}; +static const GDBusArgInfo * const _mpris_playlists_dbus_arg_info_playlist_changed[] = {&_mpris_playlists_dbus_arg_info_playlist_changed_details, NULL}; +static const GDBusSignalInfo _mpris_playlists_dbus_signal_info_playlist_changed = {-1, "PlaylistChanged", (GDBusArgInfo **) (&_mpris_playlists_dbus_arg_info_playlist_changed)}; +static const GDBusSignalInfo * const _mpris_playlists_dbus_signal_info[] = {&_mpris_playlists_dbus_signal_info_playlist_changed, NULL}; static const GDBusPropertyInfo _mpris_playlists_dbus_property_info_Orderings = {-1, "Orderings", "as", G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE}; static const GDBusPropertyInfo _mpris_playlists_dbus_property_info_PlaylistCount = {-1, "PlaylistCount", "u", G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE}; static const GDBusPropertyInfo _mpris_playlists_dbus_property_info_ActivePlaylist = {-1, "ActivePlaylist", "(b(oss))", G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE}; @@ -1745,10 +1751,30 @@ void mpris_playlists_set_ActivePlaylist (MprisPlaylists* self, ActivePlaylistCon } +static void g_cclosure_user_marshal_VOID__BOXED (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__BOXED) (gpointer data1, gpointer arg_1, gpointer data2); + register GMarshalFunc_VOID__BOXED callback; + register GCClosure * cc; + register gpointer data1, data2; + cc = (GCClosure *) closure; + g_return_if_fail (n_param_values == 2); + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = param_values->data[0].v_pointer; + } else { + data1 = param_values->data[0].v_pointer; + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__BOXED) (marshal_data ? marshal_data : cc->callback); + callback (data1, g_value_get_boxed (param_values + 1), data2); +} + + static void mpris_playlists_base_init (MprisPlaylistsIface * iface) { static gboolean initialized = FALSE; if (!initialized) { initialized = TRUE; + g_signal_new ("playlist_changed", TYPE_MPRIS_PLAYLISTS, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__BOXED, G_TYPE_NONE, 1, TYPE_PLAYLIST_DETAILS); } } @@ -1775,7 +1801,38 @@ static void mpris_playlists_proxy_class_init (MprisPlaylistsProxyClass* klass) { } +static void _dbus_handle_mpris_playlists_playlist_changed (MprisPlaylists* self, GVariant* parameters) { + GVariantIter _arguments_iter; + PlaylistDetails details = {0}; + GVariant* _tmp17_; + PlaylistDetails _tmp18_; + GVariantIter _tmp19_; + GVariant* _tmp20_; + GVariant* _tmp21_; + GVariant* _tmp22_; + g_variant_iter_init (&_arguments_iter, parameters); + _tmp17_ = g_variant_iter_next_value (&_arguments_iter); + g_variant_iter_init (&_tmp19_, _tmp17_); + _tmp20_ = g_variant_iter_next_value (&_tmp19_); + _tmp18_.path = g_variant_dup_string (_tmp20_, NULL); + g_variant_unref (_tmp20_); + _tmp21_ = g_variant_iter_next_value (&_tmp19_); + _tmp18_.name = g_variant_dup_string (_tmp21_, NULL); + g_variant_unref (_tmp21_); + _tmp22_ = g_variant_iter_next_value (&_tmp19_); + _tmp18_.icon_path = g_variant_dup_string (_tmp22_, NULL); + g_variant_unref (_tmp22_); + details = _tmp18_; + g_variant_unref (_tmp17_); + g_signal_emit_by_name (self, "playlist-changed", &details); + playlist_details_destroy (&details); +} + + static void mpris_playlists_proxy_g_signal (GDBusProxy* proxy, const gchar* sender_name, const gchar* signal_name, GVariant* parameters) { + if (strcmp (signal_name, "PlaylistChanged") == 0) { + _dbus_handle_mpris_playlists_playlist_changed (proxy, parameters); + } } @@ -1836,13 +1893,13 @@ static PlaylistDetails* mpris_playlists_proxy_GetPlaylists_finish (MprisPlaylist GVariantIter _reply_iter; PlaylistDetails* _result; int _result_length1; - GVariant* _tmp17_; - PlaylistDetails* _tmp18_; - int _tmp18__length; - int _tmp18__size; - int _tmp18__length1; - GVariantIter _tmp19_; - GVariant* _tmp20_; + GVariant* _tmp23_; + PlaylistDetails* _tmp24_; + int _tmp24__length; + int _tmp24__size; + int _tmp24__length1; + GVariantIter _tmp25_; + GVariant* _tmp26_; _reply_message = g_dbus_connection_send_message_with_reply_finish (g_dbus_proxy_get_connection ((GDBusProxy *) self), g_simple_async_result_get_op_res_gpointer ((GSimpleAsyncResult *) _res_), error); if (!_reply_message) { return NULL; @@ -1854,38 +1911,38 @@ static PlaylistDetails* mpris_playlists_proxy_GetPlaylists_finish (MprisPlaylist _reply = g_dbus_message_get_body (_reply_message); g_variant_iter_init (&_reply_iter, _reply); _result_length1 = 0; - _tmp17_ = g_variant_iter_next_value (&_reply_iter); - _tmp18_ = g_new (PlaylistDetails, 5); - _tmp18__length = 0; - _tmp18__size = 4; - _tmp18__length1 = 0; - g_variant_iter_init (&_tmp19_, _tmp17_); - for (; (_tmp20_ = g_variant_iter_next_value (&_tmp19_)) != NULL; _tmp18__length1++) { - PlaylistDetails _tmp21_; - GVariantIter _tmp22_; - GVariant* _tmp23_; - GVariant* _tmp24_; - GVariant* _tmp25_; - if (_tmp18__size == _tmp18__length) { - _tmp18__size = 2 * _tmp18__size; - _tmp18_ = g_renew (PlaylistDetails, _tmp18_, _tmp18__size + 1); + _tmp23_ = g_variant_iter_next_value (&_reply_iter); + _tmp24_ = g_new (PlaylistDetails, 5); + _tmp24__length = 0; + _tmp24__size = 4; + _tmp24__length1 = 0; + g_variant_iter_init (&_tmp25_, _tmp23_); + for (; (_tmp26_ = g_variant_iter_next_value (&_tmp25_)) != NULL; _tmp24__length1++) { + PlaylistDetails _tmp27_; + GVariantIter _tmp28_; + GVariant* _tmp29_; + GVariant* _tmp30_; + GVariant* _tmp31_; + if (_tmp24__size == _tmp24__length) { + _tmp24__size = 2 * _tmp24__size; + _tmp24_ = g_renew (PlaylistDetails, _tmp24_, _tmp24__size + 1); } - g_variant_iter_init (&_tmp22_, _tmp20_); - _tmp23_ = g_variant_iter_next_value (&_tmp22_); - _tmp21_.path = g_variant_dup_string (_tmp23_, NULL); - g_variant_unref (_tmp23_); - _tmp24_ = g_variant_iter_next_value (&_tmp22_); - _tmp21_.name = g_variant_dup_string (_tmp24_, NULL); - g_variant_unref (_tmp24_); - _tmp25_ = g_variant_iter_next_value (&_tmp22_); - _tmp21_.icon_path = g_variant_dup_string (_tmp25_, NULL); - g_variant_unref (_tmp25_); - _tmp18_[_tmp18__length++] = _tmp21_; - g_variant_unref (_tmp20_); - } - _result_length1 = _tmp18__length1; - _result = _tmp18_; - g_variant_unref (_tmp17_); + g_variant_iter_init (&_tmp28_, _tmp26_); + _tmp29_ = g_variant_iter_next_value (&_tmp28_); + _tmp27_.path = g_variant_dup_string (_tmp29_, NULL); + g_variant_unref (_tmp29_); + _tmp30_ = g_variant_iter_next_value (&_tmp28_); + _tmp27_.name = g_variant_dup_string (_tmp30_, NULL); + g_variant_unref (_tmp30_); + _tmp31_ = g_variant_iter_next_value (&_tmp28_); + _tmp27_.icon_path = g_variant_dup_string (_tmp31_, NULL); + g_variant_unref (_tmp31_); + _tmp24_[_tmp24__length++] = _tmp27_; + g_variant_unref (_tmp26_); + } + _result_length1 = _tmp24__length1; + _result = _tmp24_; + g_variant_unref (_tmp23_); *result_length1 = _result_length1; g_object_unref (_reply_message); return _result; @@ -1896,12 +1953,12 @@ static gchar** mpris_playlists_dbus_proxy_get_Orderings (MprisPlaylists* self, i GVariant *_inner_reply; gchar** _result; int _result_length1; - gchar** _tmp26_; - int _tmp26__length; - int _tmp26__size; - int _tmp26__length1; - GVariantIter _tmp27_; - GVariant* _tmp28_; + gchar** _tmp32_; + int _tmp32__length; + int _tmp32__size; + int _tmp32__length1; + GVariantIter _tmp33_; + GVariant* _tmp34_; _inner_reply = g_dbus_proxy_get_cached_property ((GDBusProxy *) self, "Orderings"); if (!_inner_reply) { GVariant *_arguments; @@ -1919,22 +1976,22 @@ static gchar** mpris_playlists_dbus_proxy_get_Orderings (MprisPlaylists* self, i g_variant_unref (_reply); } _result_length1 = 0; - _tmp26_ = g_new (gchar*, 5); - _tmp26__length = 0; - _tmp26__size = 4; - _tmp26__length1 = 0; - g_variant_iter_init (&_tmp27_, _inner_reply); - for (; (_tmp28_ = g_variant_iter_next_value (&_tmp27_)) != NULL; _tmp26__length1++) { - if (_tmp26__size == _tmp26__length) { - _tmp26__size = 2 * _tmp26__size; - _tmp26_ = g_renew (gchar*, _tmp26_, _tmp26__size + 1); + _tmp32_ = g_new (gchar*, 5); + _tmp32__length = 0; + _tmp32__size = 4; + _tmp32__length1 = 0; + g_variant_iter_init (&_tmp33_, _inner_reply); + for (; (_tmp34_ = g_variant_iter_next_value (&_tmp33_)) != NULL; _tmp32__length1++) { + if (_tmp32__size == _tmp32__length) { + _tmp32__size = 2 * _tmp32__size; + _tmp32_ = g_renew (gchar*, _tmp32_, _tmp32__size + 1); } - _tmp26_[_tmp26__length++] = g_variant_dup_string (_tmp28_, NULL); - g_variant_unref (_tmp28_); + _tmp32_[_tmp32__length++] = g_variant_dup_string (_tmp34_, NULL); + g_variant_unref (_tmp34_); } - _result_length1 = _tmp26__length1; - _tmp26_[_tmp26__length] = NULL; - _result = _tmp26_; + _result_length1 = _tmp32__length1; + _tmp32_[_tmp32__length] = NULL; + _result = _tmp32_; *result_length1 = _result_length1; g_variant_unref (_inner_reply); return _result; @@ -1945,20 +2002,20 @@ static void mpris_playlists_dbus_proxy_set_Orderings (MprisPlaylists* self, gcha GVariant *_arguments; GVariant *_reply; GVariantBuilder _arguments_builder; - gchar** _tmp29_; - GVariantBuilder _tmp30_; - int _tmp31_; + gchar** _tmp35_; + GVariantBuilder _tmp36_; + int _tmp37_; g_variant_builder_init (&_arguments_builder, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value (&_arguments_builder, g_variant_new_string ("org.mpris.MediaPlayer2.Playlists")); g_variant_builder_add_value (&_arguments_builder, g_variant_new_string ("Orderings")); g_variant_builder_open (&_arguments_builder, G_VARIANT_TYPE_VARIANT); - _tmp29_ = value; - g_variant_builder_init (&_tmp30_, G_VARIANT_TYPE ("as")); - for (_tmp31_ = 0; _tmp31_ < value_length1; _tmp31_++) { - g_variant_builder_add_value (&_tmp30_, g_variant_new_string (*_tmp29_)); - _tmp29_++; + _tmp35_ = value; + g_variant_builder_init (&_tmp36_, G_VARIANT_TYPE ("as")); + for (_tmp37_ = 0; _tmp37_ < value_length1; _tmp37_++) { + g_variant_builder_add_value (&_tmp36_, g_variant_new_string (*_tmp35_)); + _tmp35_++; } - g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp30_)); + g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp36_)); g_variant_builder_close (&_arguments_builder); _arguments = g_variant_builder_end (&_arguments_builder); _reply = g_dbus_proxy_call_sync ((GDBusProxy *) self, "org.freedesktop.DBus.Properties.Set", _arguments, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); @@ -2015,15 +2072,15 @@ static void mpris_playlists_dbus_proxy_set_PlaylistCount (MprisPlaylists* self, static void mpris_playlists_dbus_proxy_get_ActivePlaylist (MprisPlaylists* self, ActivePlaylistContainer* result) { GVariant *_inner_reply; - ActivePlaylistContainer _tmp32_; - GVariantIter _tmp33_; - GVariant* _tmp34_; - GVariant* _tmp35_; - PlaylistDetails _tmp36_; - GVariantIter _tmp37_; - GVariant* _tmp38_; - GVariant* _tmp39_; + ActivePlaylistContainer _tmp38_; + GVariantIter _tmp39_; GVariant* _tmp40_; + GVariant* _tmp41_; + PlaylistDetails _tmp42_; + GVariantIter _tmp43_; + GVariant* _tmp44_; + GVariant* _tmp45_; + GVariant* _tmp46_; _inner_reply = g_dbus_proxy_get_cached_property ((GDBusProxy *) self, "ActivePlaylist"); if (!_inner_reply) { GVariant *_arguments; @@ -2040,24 +2097,24 @@ static void mpris_playlists_dbus_proxy_get_ActivePlaylist (MprisPlaylists* self, g_variant_get (_reply, "(v)", &_inner_reply); g_variant_unref (_reply); } - g_variant_iter_init (&_tmp33_, _inner_reply); - _tmp34_ = g_variant_iter_next_value (&_tmp33_); - _tmp32_.valid = g_variant_get_boolean (_tmp34_); - g_variant_unref (_tmp34_); - _tmp35_ = g_variant_iter_next_value (&_tmp33_); - g_variant_iter_init (&_tmp37_, _tmp35_); - _tmp38_ = g_variant_iter_next_value (&_tmp37_); - _tmp36_.path = g_variant_dup_string (_tmp38_, NULL); - g_variant_unref (_tmp38_); - _tmp39_ = g_variant_iter_next_value (&_tmp37_); - _tmp36_.name = g_variant_dup_string (_tmp39_, NULL); - g_variant_unref (_tmp39_); - _tmp40_ = g_variant_iter_next_value (&_tmp37_); - _tmp36_.icon_path = g_variant_dup_string (_tmp40_, NULL); + g_variant_iter_init (&_tmp39_, _inner_reply); + _tmp40_ = g_variant_iter_next_value (&_tmp39_); + _tmp38_.valid = g_variant_get_boolean (_tmp40_); g_variant_unref (_tmp40_); - _tmp32_.details = _tmp36_; - g_variant_unref (_tmp35_); - *result = _tmp32_; + _tmp41_ = g_variant_iter_next_value (&_tmp39_); + g_variant_iter_init (&_tmp43_, _tmp41_); + _tmp44_ = g_variant_iter_next_value (&_tmp43_); + _tmp42_.path = g_variant_dup_string (_tmp44_, NULL); + g_variant_unref (_tmp44_); + _tmp45_ = g_variant_iter_next_value (&_tmp43_); + _tmp42_.name = g_variant_dup_string (_tmp45_, NULL); + g_variant_unref (_tmp45_); + _tmp46_ = g_variant_iter_next_value (&_tmp43_); + _tmp42_.icon_path = g_variant_dup_string (_tmp46_, NULL); + g_variant_unref (_tmp46_); + _tmp38_.details = _tmp42_; + g_variant_unref (_tmp41_); + *result = _tmp38_; g_variant_unref (_inner_reply); return; } @@ -2067,20 +2124,20 @@ static void mpris_playlists_dbus_proxy_set_ActivePlaylist (MprisPlaylists* self, GVariant *_arguments; GVariant *_reply; GVariantBuilder _arguments_builder; - GVariantBuilder _tmp41_; - GVariantBuilder _tmp42_; + GVariantBuilder _tmp47_; + GVariantBuilder _tmp48_; g_variant_builder_init (&_arguments_builder, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value (&_arguments_builder, g_variant_new_string ("org.mpris.MediaPlayer2.Playlists")); g_variant_builder_add_value (&_arguments_builder, g_variant_new_string ("ActivePlaylist")); g_variant_builder_open (&_arguments_builder, G_VARIANT_TYPE_VARIANT); - g_variant_builder_init (&_tmp41_, G_VARIANT_TYPE_TUPLE); - g_variant_builder_add_value (&_tmp41_, g_variant_new_boolean ((*value).valid)); - g_variant_builder_init (&_tmp42_, G_VARIANT_TYPE_TUPLE); - g_variant_builder_add_value (&_tmp42_, g_variant_new_object_path ((*value).details.path)); - g_variant_builder_add_value (&_tmp42_, g_variant_new_string ((*value).details.name)); - g_variant_builder_add_value (&_tmp42_, g_variant_new_string ((*value).details.icon_path)); - g_variant_builder_add_value (&_tmp41_, g_variant_builder_end (&_tmp42_)); - g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp41_)); + g_variant_builder_init (&_tmp47_, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add_value (&_tmp47_, g_variant_new_boolean ((*value).valid)); + g_variant_builder_init (&_tmp48_, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add_value (&_tmp48_, g_variant_new_object_path ((*value).details.path)); + g_variant_builder_add_value (&_tmp48_, g_variant_new_string ((*value).details.name)); + g_variant_builder_add_value (&_tmp48_, g_variant_new_string ((*value).details.icon_path)); + g_variant_builder_add_value (&_tmp47_, g_variant_builder_end (&_tmp48_)); + g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp47_)); g_variant_builder_close (&_arguments_builder); _arguments = g_variant_builder_end (&_arguments_builder); _reply = g_dbus_proxy_call_sync ((GDBusProxy *) self, "org.freedesktop.DBus.Properties.Set", _arguments, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); @@ -2108,11 +2165,11 @@ static void mpris_playlists_proxy_mpris_playlists_interface_init (MprisPlaylists static void _dbus_mpris_playlists_ActivatePlaylist (MprisPlaylists* self, GVariant* parameters, GDBusMethodInvocation* invocation) { GVariantIter _arguments_iter; char* playlist_id = NULL; - GVariant* _tmp43_; + GVariant* _tmp49_; g_variant_iter_init (&_arguments_iter, parameters); - _tmp43_ = g_variant_iter_next_value (&_arguments_iter); - playlist_id = g_variant_dup_string (_tmp43_, NULL); - g_variant_unref (_tmp43_); + _tmp49_ = g_variant_iter_next_value (&_arguments_iter); + playlist_id = g_variant_dup_string (_tmp49_, NULL); + g_variant_unref (_tmp49_); mpris_playlists_ActivatePlaylist (self, playlist_id, (GAsyncReadyCallback) _dbus_mpris_playlists_ActivatePlaylist_ready, invocation); _g_free0 (playlist_id); } @@ -2143,26 +2200,26 @@ static void _dbus_mpris_playlists_ActivatePlaylist_ready (GObject * source_objec static void _dbus_mpris_playlists_GetPlaylists (MprisPlaylists* self, GVariant* parameters, GDBusMethodInvocation* invocation) { GVariantIter _arguments_iter; guint32 index = 0U; - GVariant* _tmp44_; + GVariant* _tmp50_; guint32 max_count = 0U; - GVariant* _tmp45_; + GVariant* _tmp51_; gchar* order = NULL; - GVariant* _tmp46_; + GVariant* _tmp52_; gboolean reverse_order = FALSE; - GVariant* _tmp47_; + GVariant* _tmp53_; g_variant_iter_init (&_arguments_iter, parameters); - _tmp44_ = g_variant_iter_next_value (&_arguments_iter); - index = g_variant_get_uint32 (_tmp44_); - g_variant_unref (_tmp44_); - _tmp45_ = g_variant_iter_next_value (&_arguments_iter); - max_count = g_variant_get_uint32 (_tmp45_); - g_variant_unref (_tmp45_); - _tmp46_ = g_variant_iter_next_value (&_arguments_iter); - order = g_variant_dup_string (_tmp46_, NULL); - g_variant_unref (_tmp46_); - _tmp47_ = g_variant_iter_next_value (&_arguments_iter); - reverse_order = g_variant_get_boolean (_tmp47_); - g_variant_unref (_tmp47_); + _tmp50_ = g_variant_iter_next_value (&_arguments_iter); + index = g_variant_get_uint32 (_tmp50_); + g_variant_unref (_tmp50_); + _tmp51_ = g_variant_iter_next_value (&_arguments_iter); + max_count = g_variant_get_uint32 (_tmp51_); + g_variant_unref (_tmp51_); + _tmp52_ = g_variant_iter_next_value (&_arguments_iter); + order = g_variant_dup_string (_tmp52_, NULL); + g_variant_unref (_tmp52_); + _tmp53_ = g_variant_iter_next_value (&_arguments_iter); + reverse_order = g_variant_get_boolean (_tmp53_); + g_variant_unref (_tmp53_); mpris_playlists_GetPlaylists (self, index, max_count, order, reverse_order, (GAsyncReadyCallback) _dbus_mpris_playlists_GetPlaylists_ready, invocation); _g_free0 (order); } @@ -2187,9 +2244,9 @@ static void _dbus_mpris_playlists_GetPlaylists_ready (GObject * source_object, G GVariantBuilder _reply_builder; PlaylistDetails* result; int result_length1 = 0; - PlaylistDetails* _tmp48_; - GVariantBuilder _tmp49_; - int _tmp50_; + PlaylistDetails* _tmp54_; + GVariantBuilder _tmp55_; + int _tmp56_; invocation = _user_data_; result = mpris_playlists_GetPlaylists_finish ((MprisPlaylists*) source_object, _res_, &result_length1, &error); if (error) { @@ -2198,18 +2255,18 @@ static void _dbus_mpris_playlists_GetPlaylists_ready (GObject * source_object, G } _reply_message = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation)); g_variant_builder_init (&_reply_builder, G_VARIANT_TYPE_TUPLE); - _tmp48_ = result; - g_variant_builder_init (&_tmp49_, G_VARIANT_TYPE ("a(oss)")); - for (_tmp50_ = 0; _tmp50_ < result_length1; _tmp50_++) { - GVariantBuilder _tmp51_; - g_variant_builder_init (&_tmp51_, G_VARIANT_TYPE_TUPLE); - g_variant_builder_add_value (&_tmp51_, g_variant_new_object_path ((*_tmp48_).path)); - g_variant_builder_add_value (&_tmp51_, g_variant_new_string ((*_tmp48_).name)); - g_variant_builder_add_value (&_tmp51_, g_variant_new_string ((*_tmp48_).icon_path)); - g_variant_builder_add_value (&_tmp49_, g_variant_builder_end (&_tmp51_)); - _tmp48_++; - } - g_variant_builder_add_value (&_reply_builder, g_variant_builder_end (&_tmp49_)); + _tmp54_ = result; + g_variant_builder_init (&_tmp55_, G_VARIANT_TYPE ("a(oss)")); + for (_tmp56_ = 0; _tmp56_ < result_length1; _tmp56_++) { + GVariantBuilder _tmp57_; + g_variant_builder_init (&_tmp57_, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add_value (&_tmp57_, g_variant_new_object_path ((*_tmp54_).path)); + g_variant_builder_add_value (&_tmp57_, g_variant_new_string ((*_tmp54_).name)); + g_variant_builder_add_value (&_tmp57_, g_variant_new_string ((*_tmp54_).icon_path)); + g_variant_builder_add_value (&_tmp55_, g_variant_builder_end (&_tmp57_)); + _tmp54_++; + } + g_variant_builder_add_value (&_reply_builder, g_variant_builder_end (&_tmp55_)); result = (_vala_PlaylistDetails_array_free ( result, result_length1), NULL); _reply = g_variant_builder_end (&_reply_builder); g_dbus_message_set_body (_reply_message, _reply); @@ -2237,18 +2294,18 @@ static void mpris_playlists_dbus_interface_method_call (GDBusConnection* connect static GVariant* _dbus_mpris_playlists_get_Orderings (MprisPlaylists* self) { gchar** result; int result_length1; - gchar** _tmp52_; - GVariantBuilder _tmp53_; - int _tmp54_; + gchar** _tmp58_; + GVariantBuilder _tmp59_; + int _tmp60_; GVariant* _reply; result = mpris_playlists_get_Orderings (self, &result_length1); - _tmp52_ = result; - g_variant_builder_init (&_tmp53_, G_VARIANT_TYPE ("as")); - for (_tmp54_ = 0; _tmp54_ < result_length1; _tmp54_++) { - g_variant_builder_add_value (&_tmp53_, g_variant_new_string (*_tmp52_)); - _tmp52_++; + _tmp58_ = result; + g_variant_builder_init (&_tmp59_, G_VARIANT_TYPE ("as")); + for (_tmp60_ = 0; _tmp60_ < result_length1; _tmp60_++) { + g_variant_builder_add_value (&_tmp59_, g_variant_new_string (*_tmp58_)); + _tmp58_++; } - _reply = g_variant_builder_end (&_tmp53_); + _reply = g_variant_builder_end (&_tmp59_); result = (_vala_array_free ( result, result_length1, (GDestroyNotify) g_free), NULL); return _reply; } @@ -2265,18 +2322,18 @@ static GVariant* _dbus_mpris_playlists_get_PlaylistCount (MprisPlaylists* self) static GVariant* _dbus_mpris_playlists_get_ActivePlaylist (MprisPlaylists* self) { ActivePlaylistContainer result = {0}; - GVariantBuilder _tmp55_; - GVariantBuilder _tmp56_; + GVariantBuilder _tmp61_; + GVariantBuilder _tmp62_; GVariant* _reply; mpris_playlists_get_ActivePlaylist (self, &result); - g_variant_builder_init (&_tmp55_, G_VARIANT_TYPE_TUPLE); - g_variant_builder_add_value (&_tmp55_, g_variant_new_boolean (result.valid)); - g_variant_builder_init (&_tmp56_, G_VARIANT_TYPE_TUPLE); - g_variant_builder_add_value (&_tmp56_, g_variant_new_object_path (result.details.path)); - g_variant_builder_add_value (&_tmp56_, g_variant_new_string (result.details.name)); - g_variant_builder_add_value (&_tmp56_, g_variant_new_string (result.details.icon_path)); - g_variant_builder_add_value (&_tmp55_, g_variant_builder_end (&_tmp56_)); - _reply = g_variant_builder_end (&_tmp55_); + g_variant_builder_init (&_tmp61_, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add_value (&_tmp61_, g_variant_new_boolean (result.valid)); + g_variant_builder_init (&_tmp62_, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add_value (&_tmp62_, g_variant_new_object_path (result.details.path)); + g_variant_builder_add_value (&_tmp62_, g_variant_new_string (result.details.name)); + g_variant_builder_add_value (&_tmp62_, g_variant_new_string (result.details.icon_path)); + g_variant_builder_add_value (&_tmp61_, g_variant_builder_end (&_tmp62_)); + _reply = g_variant_builder_end (&_tmp61_); active_playlist_container_destroy (& result); return _reply; } @@ -2301,28 +2358,28 @@ static GVariant* mpris_playlists_dbus_interface_get_property (GDBusConnection* c static void _dbus_mpris_playlists_set_Orderings (MprisPlaylists* self, GVariant* _value) { gchar** value = NULL; int value_length1; - gchar** _tmp57_; - int _tmp57__length; - int _tmp57__size; - int _tmp57__length1; - GVariantIter _tmp58_; - GVariant* _tmp59_; - _tmp57_ = g_new (gchar*, 5); - _tmp57__length = 0; - _tmp57__size = 4; - _tmp57__length1 = 0; - g_variant_iter_init (&_tmp58_, _value); - for (; (_tmp59_ = g_variant_iter_next_value (&_tmp58_)) != NULL; _tmp57__length1++) { - if (_tmp57__size == _tmp57__length) { - _tmp57__size = 2 * _tmp57__size; - _tmp57_ = g_renew (gchar*, _tmp57_, _tmp57__size + 1); + gchar** _tmp63_; + int _tmp63__length; + int _tmp63__size; + int _tmp63__length1; + GVariantIter _tmp64_; + GVariant* _tmp65_; + _tmp63_ = g_new (gchar*, 5); + _tmp63__length = 0; + _tmp63__size = 4; + _tmp63__length1 = 0; + g_variant_iter_init (&_tmp64_, _value); + for (; (_tmp65_ = g_variant_iter_next_value (&_tmp64_)) != NULL; _tmp63__length1++) { + if (_tmp63__size == _tmp63__length) { + _tmp63__size = 2 * _tmp63__size; + _tmp63_ = g_renew (gchar*, _tmp63_, _tmp63__size + 1); } - _tmp57_[_tmp57__length++] = g_variant_dup_string (_tmp59_, NULL); - g_variant_unref (_tmp59_); + _tmp63_[_tmp63__length++] = g_variant_dup_string (_tmp65_, NULL); + g_variant_unref (_tmp65_); } - value_length1 = _tmp57__length1; - _tmp57_[_tmp57__length] = NULL; - value = _tmp57_; + value_length1 = _tmp63__length1; + _tmp63_[_tmp63__length] = NULL; + value = _tmp63_; mpris_playlists_set_Orderings (self, value, value_length1); value = (_vala_array_free (value, value_length1, (GDestroyNotify) g_free), NULL); } @@ -2337,33 +2394,33 @@ static void _dbus_mpris_playlists_set_PlaylistCount (MprisPlaylists* self, GVari static void _dbus_mpris_playlists_set_ActivePlaylist (MprisPlaylists* self, GVariant* _value) { ActivePlaylistContainer value = {0}; - ActivePlaylistContainer _tmp60_; - GVariantIter _tmp61_; - GVariant* _tmp62_; - GVariant* _tmp63_; - PlaylistDetails _tmp64_; - GVariantIter _tmp65_; - GVariant* _tmp66_; - GVariant* _tmp67_; + ActivePlaylistContainer _tmp66_; + GVariantIter _tmp67_; GVariant* _tmp68_; - g_variant_iter_init (&_tmp61_, _value); - _tmp62_ = g_variant_iter_next_value (&_tmp61_); - _tmp60_.valid = g_variant_get_boolean (_tmp62_); - g_variant_unref (_tmp62_); - _tmp63_ = g_variant_iter_next_value (&_tmp61_); - g_variant_iter_init (&_tmp65_, _tmp63_); - _tmp66_ = g_variant_iter_next_value (&_tmp65_); - _tmp64_.path = g_variant_dup_string (_tmp66_, NULL); - g_variant_unref (_tmp66_); - _tmp67_ = g_variant_iter_next_value (&_tmp65_); - _tmp64_.name = g_variant_dup_string (_tmp67_, NULL); - g_variant_unref (_tmp67_); - _tmp68_ = g_variant_iter_next_value (&_tmp65_); - _tmp64_.icon_path = g_variant_dup_string (_tmp68_, NULL); + GVariant* _tmp69_; + PlaylistDetails _tmp70_; + GVariantIter _tmp71_; + GVariant* _tmp72_; + GVariant* _tmp73_; + GVariant* _tmp74_; + g_variant_iter_init (&_tmp67_, _value); + _tmp68_ = g_variant_iter_next_value (&_tmp67_); + _tmp66_.valid = g_variant_get_boolean (_tmp68_); g_variant_unref (_tmp68_); - _tmp60_.details = _tmp64_; - g_variant_unref (_tmp63_); - value = _tmp60_; + _tmp69_ = g_variant_iter_next_value (&_tmp67_); + g_variant_iter_init (&_tmp71_, _tmp69_); + _tmp72_ = g_variant_iter_next_value (&_tmp71_); + _tmp70_.path = g_variant_dup_string (_tmp72_, NULL); + g_variant_unref (_tmp72_); + _tmp73_ = g_variant_iter_next_value (&_tmp71_); + _tmp70_.name = g_variant_dup_string (_tmp73_, NULL); + g_variant_unref (_tmp73_); + _tmp74_ = g_variant_iter_next_value (&_tmp71_); + _tmp70_.icon_path = g_variant_dup_string (_tmp74_, NULL); + g_variant_unref (_tmp74_); + _tmp66_.details = _tmp70_; + g_variant_unref (_tmp69_); + value = _tmp66_; mpris_playlists_set_ActivePlaylist (self, &value); active_playlist_container_destroy (&value); } @@ -2388,6 +2445,25 @@ static gboolean mpris_playlists_dbus_interface_set_property (GDBusConnection* co } +static void _dbus_mpris_playlists_playlist_changed (GObject* _sender, PlaylistDetails* details, gpointer* _data) { + GDBusConnection * _connection; + const gchar * _path; + GVariant *_arguments; + GVariantBuilder _arguments_builder; + GVariantBuilder _tmp75_; + _connection = _data[1]; + _path = _data[2]; + g_variant_builder_init (&_arguments_builder, G_VARIANT_TYPE_TUPLE); + g_variant_builder_init (&_tmp75_, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add_value (&_tmp75_, g_variant_new_object_path ((*details).path)); + g_variant_builder_add_value (&_tmp75_, g_variant_new_string ((*details).name)); + g_variant_builder_add_value (&_tmp75_, g_variant_new_string ((*details).icon_path)); + g_variant_builder_add_value (&_arguments_builder, g_variant_builder_end (&_tmp75_)); + _arguments = g_variant_builder_end (&_arguments_builder); + g_dbus_connection_emit_signal (_connection, NULL, _path, "org.mpris.MediaPlayer2.Playlists", "PlaylistChanged", _arguments, NULL); +} + + guint mpris_playlists_register_object (gpointer object, GDBusConnection* connection, const gchar* path, GError** error) { guint result; gpointer *data; @@ -2399,6 +2475,7 @@ guint mpris_playlists_register_object (gpointer object, GDBusConnection* connect if (!result) { return 0; } + g_signal_connect (object, "playlist-changed", (GCallback) _dbus_mpris_playlists_playlist_changed, data); return result; } diff --git a/src/mpris2-interfaces.vala b/src/mpris2-interfaces.vala index 0a0909f..5506a47 100644 --- a/src/mpris2-interfaces.vala +++ b/src/mpris2-interfaces.vala @@ -72,4 +72,7 @@ public interface MprisPlaylists : Object { uint32 max_count, string order, bool reverse_order ) throws IOError; + //signals + public signal void PlaylistChanged (PlaylistDetails details); + }
\ No newline at end of file diff --git a/src/mpris2-watcher.c b/src/mpris2-watcher.c index c000e87..7b362d8 100644 --- a/src/mpris2-watcher.c +++ b/src/mpris2-watcher.c @@ -161,8 +161,8 @@ enum { Mpris2Watcher* mpris2_watcher_new (void); Mpris2Watcher* mpris2_watcher_construct (GType object_type); static void mpris2_watcher_check_for_active_clients_data_free (gpointer _data); -static void mpris2_watcher_check_for_active_clients (Mpris2Watcher* self, GAsyncReadyCallback _callback_, gpointer _user_data_); -static void mpris2_watcher_check_for_active_clients_finish (Mpris2Watcher* self, GAsyncResult* _res_); +void mpris2_watcher_check_for_active_clients (Mpris2Watcher* self, GAsyncReadyCallback _callback_, gpointer _user_data_); +void mpris2_watcher_check_for_active_clients_finish (Mpris2Watcher* self, GAsyncResult* _res_); static gboolean mpris2_watcher_check_for_active_clients_co (Mpris2WatcherCheckForActiveClientsData* data); void free_desktop_object_list_names (FreeDesktopObject* self, GAsyncReadyCallback _callback_, gpointer _user_data_); gchar** free_desktop_object_list_names_finish (FreeDesktopObject* self, GAsyncResult* _res_, int* result_length1, GError** error); @@ -216,7 +216,7 @@ static gpointer _g_object_ref0 (gpointer self) { } -static void mpris2_watcher_check_for_active_clients (Mpris2Watcher* self, GAsyncReadyCallback _callback_, gpointer _user_data_) { +void mpris2_watcher_check_for_active_clients (Mpris2Watcher* self, GAsyncReadyCallback _callback_, gpointer _user_data_) { Mpris2WatcherCheckForActiveClientsData* _data_; _data_ = g_slice_new0 (Mpris2WatcherCheckForActiveClientsData); _data_->_async_result = g_simple_async_result_new (G_OBJECT (self), _callback_, _user_data_, mpris2_watcher_check_for_active_clients); @@ -226,7 +226,7 @@ static void mpris2_watcher_check_for_active_clients (Mpris2Watcher* self, GAsync } -static void mpris2_watcher_check_for_active_clients_finish (Mpris2Watcher* self, GAsyncResult* _res_) { +void mpris2_watcher_check_for_active_clients_finish (Mpris2Watcher* self, GAsyncResult* _res_) { Mpris2WatcherCheckForActiveClientsData* _data_; _data_ = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (_res_)); } diff --git a/src/mpris2-watcher.vala b/src/mpris2-watcher.vala index c20b04b..0b37506 100644 --- a/src/mpris2-watcher.vala +++ b/src/mpris2-watcher.vala @@ -50,7 +50,7 @@ public class Mpris2Watcher : GLib.Object // At startup check to see if there are clients up that we are interested in // More relevant for development and daemon's like mpd. - private async void check_for_active_clients() + public async void check_for_active_clients() { string[] interfaces; try{ diff --git a/src/music-player-bridge.c b/src/music-player-bridge.c index 6076732..fe42ce4 100644 --- a/src/music-player-bridge.c +++ b/src/music-player-bridge.c @@ -153,10 +153,13 @@ enum { MusicPlayerBridge* music_player_bridge_new (void); MusicPlayerBridge* music_player_bridge_construct (GType object_type); static void music_player_bridge_on_blacklist_update (MusicPlayerBridge* self, gchar** blacklist, int blacklist_length1); +static gchar* music_player_bridge_determine_key (gchar* desktop_or_interface); +void player_controller_remove_from_menu (PlayerController* self); +void mpris2_watcher_check_for_active_clients (Mpris2Watcher* self, GAsyncReadyCallback _callback_, gpointer _user_data_); +void mpris2_watcher_check_for_active_clients_finish (Mpris2Watcher* self, GAsyncResult* _res_); static void music_player_bridge_try_to_add_inactive_familiar_clients (MusicPlayerBridge* self); GeeArrayList* settings_manager_fetch_interested (SettingsManager* self); static GAppInfo* music_player_bridge_create_app_info (const gchar* desktop); -static gchar* music_player_bridge_determine_key (gchar* desktop_or_interface); static gchar* music_player_bridge_fetch_icon_name (const gchar* desktop); static gint music_player_bridge_calculate_menu_position (MusicPlayerBridge* self); GType player_controller_state_get_type (void) G_GNUC_CONST; @@ -204,6 +207,43 @@ MusicPlayerBridge* music_player_bridge_new (void) { static void music_player_bridge_on_blacklist_update (MusicPlayerBridge* self, gchar** blacklist, int blacklist_length1) { g_return_if_fail (self != NULL); g_debug ("music-player-bridge.vala:43: some blacklist update"); + { + gchar** s_collection; + int s_collection_length1; + int s_it; + s_collection = blacklist; + s_collection_length1 = blacklist_length1; + for (s_it = 0; s_it < blacklist_length1; s_it = s_it + 1) { + gchar* _tmp0_; + gchar* s; + _tmp0_ = g_strdup (s_collection[s_it]); + s = _tmp0_; + { + gchar* _tmp1_; + gchar* _tmp2_ = NULL; + gchar* key; + gboolean _tmp3_; + _tmp1_ = g_strdup (s); + _tmp2_ = music_player_bridge_determine_key (_tmp1_); + key = _tmp2_; + _tmp3_ = gee_abstract_map_has_key ((GeeAbstractMap*) self->priv->registered_clients, key); + if (_tmp3_) { + gpointer _tmp4_ = NULL; + PlayerController* _tmp5_; + g_debug ("music-player-bridge.vala:48: Apparently %s is now blacklisted - remove" \ +" thy self", key); + _tmp4_ = gee_abstract_map_get ((GeeAbstractMap*) self->priv->registered_clients, key); + _tmp5_ = (PlayerController*) _tmp4_; + player_controller_remove_from_menu (_tmp5_); + _g_object_unref0 (_tmp5_); + gee_abstract_map_unset ((GeeAbstractMap*) self->priv->registered_clients, key, NULL); + } + _g_free0 (key); + _g_free0 (s); + } + } + } + mpris2_watcher_check_for_active_clients (self->priv->watcher, NULL, NULL); } @@ -243,13 +283,13 @@ static void music_player_bridge_try_to_add_inactive_familiar_clients (MusicPlaye } _tmp2_ = gee_abstract_list_get ((GeeAbstractList*) _desktop_list, _desktop_index); desktop = (gchar*) _tmp2_; - g_debug ("music-player-bridge.vala:49: interested client found : %s", desktop); + g_debug ("music-player-bridge.vala:60: interested client found : %s", desktop); _tmp3_ = g_strconcat (desktop, ".desktop", NULL); _tmp4_ = _tmp3_; _tmp5_ = music_player_bridge_create_app_info (_tmp4_); app_info = (_tmp6_ = _tmp5_, _g_free0 (_tmp4_), _tmp6_); if (app_info == NULL) { - g_warning ("music-player-bridge.vala:52: Could not create app_info for path %s \n" \ + g_warning ("music-player-bridge.vala:63: Could not create app_info for path %s \n" \ " Getting out of here ", desktop); _g_object_unref0 (app_info); _g_free0 (desktop); @@ -340,7 +380,7 @@ void music_player_bridge_client_has_become_available (MusicPlayerBridge* self, c _tmp0_ = g_strcmp0 (desktop, "") == 0; } if (_tmp0_) { - g_warning ("music-player-bridge.vala:83: Client %s attempting to register without " \ + g_warning ("music-player-bridge.vala:94: Client %s attempting to register without " \ "desktop entry being set on the mpris root", dbus_name); return; } @@ -348,17 +388,17 @@ void music_player_bridge_client_has_become_available (MusicPlayerBridge* self, c _tmp3_ = _tmp2_; _tmp3__length1 = _tmp1_; if ((_tmp4_ = _vala_string_array_contains (_tmp3_, _tmp1_, desktop), _tmp3_ = (_vala_array_free (_tmp3_, _tmp3__length1, (GDestroyNotify) g_free), NULL), _tmp4_)) { - g_debug ("music-player-bridge.vala:88: Client %s attempting to register but I'm " \ + g_debug ("music-player-bridge.vala:99: Client %s attempting to register but I'm " \ "afraid it is blacklisted", desktop); return; } - g_debug ("music-player-bridge.vala:93: client_has_become_available %s", desktop); + g_debug ("music-player-bridge.vala:104: client_has_become_available %s", desktop); _tmp5_ = g_strconcat (desktop, ".desktop", NULL); _tmp6_ = _tmp5_; _tmp7_ = music_player_bridge_create_app_info (_tmp6_); app_info = (_tmp8_ = _tmp7_, _g_free0 (_tmp6_), _tmp8_); if (app_info == NULL) { - g_warning ("music-player-bridge.vala:96: Could not create app_info for path %s \n" \ + g_warning ("music-player-bridge.vala:107: Could not create app_info for path %s \n" \ " Getting out of here ", desktop); _g_object_unref0 (app_info); return; @@ -374,7 +414,7 @@ void music_player_bridge_client_has_become_available (MusicPlayerBridge* self, c PlayerController* _tmp15_ = NULL; PlayerController* _tmp16_; PlayerController* ctrl; - g_debug ("music-player-bridge.vala:104: New client has registered that we have n" \ + g_debug ("music-player-bridge.vala:115: New client has registered that we have n" \ "ot seen before: %s", dbus_name); _tmp12_ = music_player_bridge_fetch_icon_name (desktop); _tmp13_ = _tmp12_; @@ -382,10 +422,10 @@ void music_player_bridge_client_has_become_available (MusicPlayerBridge* self, c _tmp15_ = player_controller_new (self->priv->root_menu, app_info, dbus_name, _tmp13_, _tmp14_, &use_playlists, PLAYER_CONTROLLER_STATE_READY); ctrl = (_tmp16_ = _tmp15_, _g_free0 (_tmp13_), _tmp16_); gee_abstract_map_set ((GeeAbstractMap*) self->priv->registered_clients, mpris_key, ctrl); - g_debug ("music-player-bridge.vala:113: Have not seen this %s before, new contro" \ + g_debug ("music-player-bridge.vala:124: Have not seen this %s before, new contro" \ "ller created.", desktop); settings_manager_add_interested (self->priv->settings_manager, desktop); - g_debug ("music-player-bridge.vala:115: application added to the interested list"); + g_debug ("music-player-bridge.vala:126: application added to the interested list"); _g_object_unref0 (ctrl); } else { gpointer _tmp17_ = NULL; @@ -411,7 +451,7 @@ void music_player_bridge_client_has_become_available (MusicPlayerBridge* self, c _tmp24_ = (PlayerController*) _tmp23_; player_controller_activate (_tmp24_, dbus_name); _g_object_unref0 (_tmp24_); - g_debug ("music-player-bridge.vala:121: Application has already registered - awa" \ + g_debug ("music-player-bridge.vala:132: Application has already registered - awa" \ "ken the hibernation: %s \n", dbus_name); } _g_free0 (mpris_key); @@ -422,14 +462,14 @@ void music_player_bridge_client_has_become_available (MusicPlayerBridge* self, c void music_player_bridge_client_has_vanished (MusicPlayerBridge* self, const gchar* mpris_root_interface) { g_return_if_fail (self != NULL); g_return_if_fail (mpris_root_interface != NULL); - g_debug ("music-player-bridge.vala:127: MusicPlayerBridge -> client with dbus in" \ + g_debug ("music-player-bridge.vala:138: MusicPlayerBridge -> client with dbus in" \ "terface %s has vanished", mpris_root_interface); if (self->priv->root_menu != NULL) { gchar* _tmp0_; gchar* _tmp1_ = NULL; gchar* mpris_key; gboolean _tmp2_ = FALSE; - g_debug ("music-player-bridge.vala:130: attempt to remove %s", mpris_root_interface); + g_debug ("music-player-bridge.vala:141: attempt to remove %s", mpris_root_interface); _tmp0_ = g_strdup (mpris_root_interface); _tmp1_ = music_player_bridge_determine_key (_tmp0_); mpris_key = _tmp1_; @@ -447,7 +487,7 @@ void music_player_bridge_client_has_vanished (MusicPlayerBridge* self, const gch _tmp5_ = (PlayerController*) _tmp4_; player_controller_hibernate (_tmp5_); _g_object_unref0 (_tmp5_); - g_debug ("music-player-bridge.vala:134: Successively offlined client %s", mpris_key); + g_debug ("music-player-bridge.vala:145: Successively offlined client %s", mpris_key); } _g_free0 (mpris_key); } @@ -507,7 +547,7 @@ static GAppInfo* music_player_bridge_create_app_info (const gchar* desktop) { _tmp1_ = info == NULL; } if (_tmp1_) { - g_warning ("music-player-bridge.vala:153: Could not create a desktopappinfo instan" \ + g_warning ("music-player-bridge.vala:164: Could not create a desktopappinfo instan" \ "ce from app: %s", desktop); result = NULL; _g_object_unref0 (info); @@ -562,7 +602,7 @@ static gchar* music_player_bridge_fetch_icon_name (const gchar* desktop) { GError * _error_; _error_ = _inner_error_; _inner_error_ = NULL; - g_warning ("music-player-bridge.vala:169: Error loading keyfile - FileError"); + g_warning ("music-player-bridge.vala:180: Error loading keyfile - FileError"); result = NULL; _g_error_free0 (_error_); _g_key_file_free0 (desktop_keyfile); @@ -575,7 +615,7 @@ static gchar* music_player_bridge_fetch_icon_name (const gchar* desktop) { GError * _error_; _error_ = _inner_error_; _inner_error_ = NULL; - g_warning ("music-player-bridge.vala:173: Error loading keyfile - KeyFileError"); + g_warning ("music-player-bridge.vala:184: Error loading keyfile - KeyFileError"); result = NULL; _g_error_free0 (_error_); _g_key_file_free0 (desktop_keyfile); @@ -612,7 +652,7 @@ static gchar* music_player_bridge_fetch_icon_name (const gchar* desktop) { GError * _error_; _error_ = _inner_error_; _inner_error_ = NULL; - g_warning ("music-player-bridge.vala:182: Error trying to fetch the icon name from" \ + g_warning ("music-player-bridge.vala:193: Error trying to fetch the icon name from" \ " the keyfile"); result = NULL; _g_error_free0 (_error_); @@ -670,7 +710,7 @@ static gchar* music_player_bridge_determine_key (gchar* desktop_or_interface) { _g_free0 (_result_); _result_ = _tmp8_; } - g_debug ("music-player-bridge.vala:205: determine key result = %s", _result_); + g_debug ("music-player-bridge.vala:216: determine key result = %s", _result_); result = _result_; temp = (_vala_array_free (temp, temp_length1, (GDestroyNotify) g_free), NULL); tokens = (_vala_array_free (tokens, tokens_length1, (GDestroyNotify) g_free), NULL); diff --git a/src/music-player-bridge.h b/src/music-player-bridge.h index 14575fe..4c98ac7 100644 --- a/src/music-player-bridge.h +++ b/src/music-player-bridge.h @@ -450,6 +450,7 @@ GeeHashSet* metadata_menuitem_attributes_format (void); GType title_menuitem_get_type (void) G_GNUC_CONST; TitleMenuitem* title_menuitem_new (PlayerController* parent); TitleMenuitem* title_menuitem_construct (GType object_type, PlayerController* parent); +void title_menuitem_alter_label (TitleMenuitem* self, const gchar* new_title); void title_menuitem_toggle_active_triangle (TitleMenuitem* self, gboolean update); GeeHashSet* title_menuitem_attributes_format (void); GType mpris2_controller_get_type (void) G_GNUC_CONST; @@ -461,7 +462,7 @@ PlayerController* player_controller_construct (GType object_type, DbusmenuMenuit void player_controller_update_state (PlayerController* self, PlayerControllerstate new_state); void player_controller_activate (PlayerController* self, const gchar* dbus_name); void player_controller_instantiate (PlayerController* self); -void player_controller_vanish (PlayerController* self); +void player_controller_remove_from_menu (PlayerController* self); void player_controller_hibernate (PlayerController* self); void player_controller_update_layout (PlayerController* self); const gchar* player_controller_get_dbus_name (PlayerController* self); @@ -530,6 +531,8 @@ void mpris_playlists_set_ActivePlaylist (MprisPlaylists* self, ActivePlaylistCon GType mpris2_watcher_get_type (void) G_GNUC_CONST; Mpris2Watcher* mpris2_watcher_new (void); Mpris2Watcher* mpris2_watcher_construct (GType object_type); +void mpris2_watcher_check_for_active_clients (Mpris2Watcher* self, GAsyncReadyCallback _callback_, gpointer _user_data_); +void mpris2_watcher_check_for_active_clients_finish (Mpris2Watcher* self, GAsyncResult* _res_); Mpris2Controller* mpris2_controller_new (PlayerController* ctrl); Mpris2Controller* mpris2_controller_construct (GType object_type, PlayerController* ctrl); void mpris2_controller_property_changed_cb (Mpris2Controller* self, const gchar* interface_source, GHashTable* changed_properties, gchar** invalid, int invalid_length1); @@ -566,6 +569,7 @@ GType playlists_menuitem_get_type (void) G_GNUC_CONST; PlaylistsMenuitem* playlists_menuitem_new (PlayerController* parent); PlaylistsMenuitem* playlists_menuitem_construct (GType object_type, PlayerController* parent); void playlists_menuitem_update (PlaylistsMenuitem* self, PlaylistDetails* playlists, int playlists_length1); +void playlists_menuitem_update_individual_playlist (PlaylistsMenuitem* self, PlaylistDetails* new_detail); void playlists_menuitem_update_active_playlist (PlaylistsMenuitem* self, PlaylistDetails* detail); GeeHashSet* playlists_menuitem_attributes_format (void); GType free_desktop_object_proxy_get_type (void) G_GNUC_CONST; diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala index c167e08..c6c9913 100644 --- a/src/music-player-bridge.vala +++ b/src/music-player-bridge.vala @@ -41,6 +41,17 @@ public class MusicPlayerBridge : GLib.Object private void on_blacklist_update ( string[] blacklist ) { debug("some blacklist update"); + + foreach(var s in blacklist){ + string key = this.determine_key (s); + if (this.registered_clients.has_key (key)){ + debug ("Apparently %s is now blacklisted - remove thy self", key); + this.registered_clients[key].remove_from_menu(); + this.registered_clients.unset (key); + } + } + // double check present players to ensure dynamic removal/addition + this.watcher.check_for_active_clients.begin(); } private void try_to_add_inactive_familiar_clients() diff --git a/src/mute-menu-item.c b/src/mute-menu-item.c index f7f3824..8409b9f 100644 --- a/src/mute-menu-item.c +++ b/src/mute-menu-item.c @@ -24,7 +24,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include "common-defs.h" #include "mute-menu-item.h" -#include "pulse-manager.h" +#include "pulseaudio-mgr.h" typedef struct _MuteMenuItemPrivate MuteMenuItemPrivate; @@ -62,6 +62,9 @@ mute_menu_item_init (MuteMenuItem *self) g_debug("Building new Mute Menu Item"); MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE(self); priv->button = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set_bool (priv->button, + DBUSMENU_MENUITEM_PROP_VISIBLE, + TRUE); g_signal_connect (G_OBJECT (priv->button), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, @@ -90,10 +93,8 @@ mute_menu_item_set_global_mute_from_ui (gpointer user_data) DbusmenuMenuitem* button = DBUSMENU_MENUITEM (user_data); gboolean current_value = dbusmenu_menuitem_property_get_bool (button, DBUSMENU_MUTE_MENUITEM_VALUE); - gboolean new_value = !current_value; - // pa manager api - to be refactored - toggle_global_mute (new_value); + pm_update_mute (new_value); } void @@ -113,6 +114,9 @@ void mute_menu_item_enable (MuteMenuItem* item, gboolean active) { MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item); + dbusmenu_menuitem_property_set_bool (priv->button, + DBUSMENU_MENUITEM_PROP_VISIBLE, + TRUE); dbusmenu_menuitem_property_set_bool (priv->button, DBUSMENU_MENUITEM_PROP_ENABLED, diff --git a/src/player-controller.c b/src/player-controller.c index c8f241d..84bb0c1 100644 --- a/src/player-controller.c +++ b/src/player-controller.c @@ -72,16 +72,6 @@ typedef struct _Mpris2ControllerClass Mpris2ControllerClass; #define _g_free0(var) (var = (g_free (var), NULL)) #define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) -#define TYPE_TITLE_MENUITEM (title_menuitem_get_type ()) -#define TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TITLE_MENUITEM, TitleMenuitem)) -#define TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) -#define IS_TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TITLE_MENUITEM)) -#define IS_TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TITLE_MENUITEM)) -#define TITLE_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) - -typedef struct _TitleMenuitem TitleMenuitem; -typedef struct _TitleMenuitemClass TitleMenuitemClass; - #define TYPE_PLAYLISTS_MENUITEM (playlists_menuitem_get_type ()) #define PLAYLISTS_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYLISTS_MENUITEM, PlaylistsMenuitem)) #define PLAYLISTS_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYLISTS_MENUITEM, PlaylistsMenuitemClass)) @@ -94,6 +84,16 @@ typedef struct _PlaylistsMenuitemClass PlaylistsMenuitemClass; typedef struct _PlayerItemPrivate PlayerItemPrivate; typedef struct _PlaylistsMenuitemPrivate PlaylistsMenuitemPrivate; +#define TYPE_TITLE_MENUITEM (title_menuitem_get_type ()) +#define TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TITLE_MENUITEM, TitleMenuitem)) +#define TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) +#define IS_TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TITLE_MENUITEM)) +#define IS_TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TITLE_MENUITEM)) +#define TITLE_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) + +typedef struct _TitleMenuitem TitleMenuitem; +typedef struct _TitleMenuitemClass TitleMenuitemClass; + #define TYPE_METADATA_MENUITEM (metadata_menuitem_get_type ()) #define METADATA_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_METADATA_MENUITEM, MetadataMenuitem)) #define METADATA_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_METADATA_MENUITEM, MetadataMenuitemClass)) @@ -205,14 +205,15 @@ const gchar* player_controller_get_dbus_name (PlayerController* self); Mpris2Controller* mpris2_controller_new (PlayerController* ctrl); Mpris2Controller* mpris2_controller_construct (GType object_type, PlayerController* ctrl); static void player_controller_determine_state (PlayerController* self); -void player_controller_vanish (PlayerController* self); +void player_controller_remove_from_menu (PlayerController* self); +static gboolean _bool_equal (const gboolean* s1, const gboolean* s2); +GType playlists_menuitem_get_type (void) G_GNUC_CONST; void player_controller_hibernate (PlayerController* self); void player_item_reset (PlayerItem* self, GeeHashSet* attrs); GeeHashSet* transport_menuitem_attributes_format (void); GeeHashSet* metadata_menuitem_attributes_format (void); GType title_menuitem_get_type (void) G_GNUC_CONST; void title_menuitem_toggle_active_triangle (TitleMenuitem* self, gboolean update); -GType playlists_menuitem_get_type (void) G_GNUC_CONST; gboolean player_item_populated (PlayerItem* self, GeeHashSet* attrs); PlayerItem* player_item_new (const gchar* type); PlayerItem* player_item_construct (GType object_type, const gchar* type); @@ -415,7 +416,22 @@ static void player_controller_establish_mpris_connection (PlayerController* self } -void player_controller_vanish (PlayerController* self) { +static gboolean _bool_equal (const gboolean* s1, const gboolean* s2) { + if (s1 == s2) { + return TRUE; + } + if (s1 == NULL) { + return FALSE; + } + if (s2 == NULL) { + return FALSE; + } + return (*s1) == (*s2); +} + + +void player_controller_remove_from_menu (PlayerController* self) { + gboolean _tmp3_; g_return_if_fail (self != NULL); { GeeArrayList* _tmp0_; @@ -430,18 +446,27 @@ void player_controller_vanish (PlayerController* self) { _item_index = -1; while (TRUE) { gpointer _tmp2_ = NULL; - DbusmenuMenuitem* item; + PlayerItem* item; _item_index = _item_index + 1; if (!(_item_index < _item_size)) { break; } _tmp2_ = gee_abstract_list_get ((GeeAbstractList*) _item_list, _item_index); - item = (DbusmenuMenuitem*) ((PlayerItem*) _tmp2_); - dbusmenu_menuitem_child_delete (self->priv->root_menu, item); + item = (PlayerItem*) _tmp2_; + dbusmenu_menuitem_child_delete (self->priv->root_menu, (DbusmenuMenuitem*) item); _g_object_unref0 (item); } _g_object_unref0 (_item_list); } + if (_bool_equal (self->use_playlists, (_tmp3_ = TRUE, &_tmp3_)) == TRUE) { + gpointer _tmp4_ = NULL; + PlayerItem* _tmp5_; + PlaylistsMenuitem* playlists_menuitem; + _tmp4_ = gee_abstract_list_get ((GeeAbstractList*) self->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_PLAYLISTS); + playlists_menuitem = (_tmp5_ = (PlayerItem*) _tmp4_, IS_PLAYLISTS_MENUITEM (_tmp5_) ? ((PlaylistsMenuitem*) _tmp5_) : NULL); + dbusmenu_menuitem_child_delete (self->priv->root_menu, playlists_menuitem->root_item); + _g_object_unref0 (playlists_menuitem); + } } diff --git a/src/player-controller.vala b/src/player-controller.vala index 024b88b..3ce121e 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -119,10 +119,14 @@ public class PlayerController : GLib.Object this.determine_state(); } - public void vanish() + public void remove_from_menu() { - foreach(Dbusmenu.Menuitem item in this.custom_items){ - root_menu.child_delete(item); + foreach(PlayerItem item in this.custom_items){ + this.root_menu.child_delete(item); + } + if (this.use_playlists == true){ + PlaylistsMenuitem playlists_menuitem = this.custom_items[widget_order.PLAYLISTS] as PlaylistsMenuitem; + this.root_menu.child_delete (playlists_menuitem.root_item); } } @@ -180,7 +184,7 @@ public class PlayerController : GLib.Object foreach(PlayerItem item in this.custom_items){ if (this.custom_items.index_of(item) != 4) { - root_menu.child_add_position(item, this.menu_offset + this.custom_items.index_of(item)); + root_menu.child_add_position(item, this.menu_offset + this.custom_items.index_of(item)); } else{ PlaylistsMenuitem playlists_menuitem = item as PlaylistsMenuitem; @@ -188,7 +192,7 @@ public class PlayerController : GLib.Object } } } - + private void determine_state() { if(this.mpris_bridge.connected() == true){ diff --git a/src/player-item.c b/src/player-item.c index 2408ec7..b974b67 100644 --- a/src/player-item.c +++ b/src/player-item.c @@ -192,30 +192,14 @@ static gpointer _g_object_ref0 (gpointer self) { } -static gchar* bool_to_string (gboolean self) { - gchar* result = NULL; - if (self) { - gchar* _tmp0_; - _tmp0_ = g_strdup ("true"); - result = _tmp0_; - return result; - } else { - gchar* _tmp1_; - _tmp1_ = g_strdup ("false"); - result = _tmp1_; - return result; - } -} - - void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes) { - gboolean _tmp25_; + gboolean _tmp20_; g_return_if_fail (self != NULL); g_return_if_fail (data != NULL); g_return_if_fail (attributes != NULL); g_debug ("player-item.vala:53: PlayerItem::update()"); if (data == NULL) { - g_debug ("player-item.vala:55: PlayerItem::Update -> The hashtable was null - ju" \ + g_warning ("player-item.vala:55: PlayerItem::Update -> The hashtable was null - ju" \ "st leave it!"); return; } @@ -251,7 +235,6 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu _input_keys_size_ = _vala_array_length (_tmp3_); _tmp5_ = g_strdup ((input_keys + (input_keys_length1 - 1))[0]); search_key = _tmp5_; - g_debug ("player-item.vala:62: search key = %s", search_key); _tmp6_ = g_hash_table_lookup (data, search_key); _tmp7_ = _g_variant_ref0 ((GVariant*) _tmp6_); v = _tmp7_; @@ -264,7 +247,6 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu _tmp9_ = g_variant_get_string (v, NULL); _tmp10_ = string_strip (_tmp9_); update = _tmp10_; - g_debug ("player-item.vala:67: with value : %s", update); _tmp11_ = string_contains (property, "mpris:artUrl"); if (_tmp11_) { PlayerItem* _tmp12_; @@ -288,36 +270,22 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu _tmp14_ = g_variant_is_of_type (v, G_VARIANT_TYPE_INT32); if (_tmp14_) { gint32 _tmp15_; - gint32 _tmp16_; _tmp15_ = g_variant_get_int32 (v); - g_debug ("player-item.vala:78: with value : %i", (gint) _tmp15_); - _tmp16_ = g_variant_get_int32 (v); - dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, property, (gint) _tmp16_); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, property, (gint) _tmp15_); } else { - gboolean _tmp17_; - _tmp17_ = g_variant_is_of_type (v, G_VARIANT_TYPE_INT64); - if (_tmp17_) { - gint64 _tmp18_; - gint64 _tmp19_; - _tmp18_ = g_variant_get_int64 (v); - g_debug ("player-item.vala:82: with value : %i", (gint) _tmp18_); - _tmp19_ = g_variant_get_int64 (v); - dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, property, (gint) _tmp19_); + gboolean _tmp16_; + _tmp16_ = g_variant_is_of_type (v, G_VARIANT_TYPE_INT64); + if (_tmp16_) { + gint64 _tmp17_; + _tmp17_ = g_variant_get_int64 (v); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, property, (gint) _tmp17_); } else { - gboolean _tmp20_; - _tmp20_ = g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN); - if (_tmp20_) { - gboolean _tmp21_; - gchar* _tmp22_ = NULL; - gchar* _tmp23_; - gboolean _tmp24_; - _tmp21_ = g_variant_get_boolean (v); - _tmp22_ = bool_to_string (_tmp21_); - _tmp23_ = _tmp22_; - g_debug ("player-item.vala:86: with value : %s", _tmp23_); - _g_free0 (_tmp23_); - _tmp24_ = g_variant_get_boolean (v); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, property, _tmp24_); + gboolean _tmp18_; + _tmp18_ = g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN); + if (_tmp18_) { + gboolean _tmp19_; + _tmp19_ = g_variant_get_boolean (v); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, property, _tmp19_); } } } @@ -329,8 +297,8 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu } _g_object_unref0 (_property_it); } - _tmp25_ = player_item_populated (self, attributes); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, DBUSMENU_MENUITEM_PROP_VISIBLE, _tmp25_); + _tmp20_ = player_item_populated (self, attributes); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, DBUSMENU_MENUITEM_PROP_VISIBLE, _tmp20_); } @@ -356,12 +324,10 @@ gboolean player_item_populated (PlayerItem* self, GeeHashSet* attrs) { } _tmp2_ = gee_iterator_get (_prop_it); prop = (gchar*) _tmp2_; - g_debug ("player-item.vala:96: populated ? - prop: %s", prop); _tmp3_ = dbusmenu_menuitem_property_get_int ((DbusmenuMenuitem*) self, prop); value_int = _tmp3_; _tmp4_ = dbusmenu_menuitem_property_get_int ((DbusmenuMenuitem*) self, prop); if (_tmp4_ != PLAYER_ITEM_EMPTY) { - g_debug ("player-item.vala:99: populated - prop %s and value %i", prop, value_int); result = TRUE; _g_free0 (prop); _g_object_unref0 (_prop_it); diff --git a/src/player-item.vala b/src/player-item.vala index f883a1e..e146d4a 100644 --- a/src/player-item.vala +++ b/src/player-item.vala @@ -52,19 +52,19 @@ public class PlayerItem : Dbusmenu.Menuitem { debug("PlayerItem::update()"); if(data == null){ - debug("PlayerItem::Update -> The hashtable was null - just leave it!"); + warning("PlayerItem::Update -> The hashtable was null - just leave it!"); return; } foreach(string property in attributes){ string[] input_keys = property.split("-"); string search_key = input_keys[input_keys.length-1 : input_keys.length][0]; - debug("search key = %s", search_key); + //debug("search key = %s", search_key); Variant? v = data.lookup(search_key); if (v.is_of_type ( VariantType.STRING )){ string update = v.get_string().strip(); - debug("with value : %s", update); + //debug("with value : %s", update); if(property.contains("mpris:artUrl")){ // We know its a metadata instance because thats the only // object with the arturl prop @@ -75,15 +75,15 @@ public class PlayerItem : Dbusmenu.Menuitem this.property_set(property, update); } else if (v.is_of_type (VariantType.INT32 )){ - debug("with value : %i", v.get_int32()); + //debug("with value : %i", v.get_int32()); this.property_set_int(property, v.get_int32()); } else if (v.is_of_type (VariantType.INT64 )){ - debug("with value : %i", (int)v.get_int64()); + //debug("with value : %i", (int)v.get_int64()); this.property_set_int(property, (int)v.get_int64()); } else if(v.is_of_type ( VariantType.BOOLEAN )){ - debug("with value : %s", v.get_boolean().to_string()); + //debug("with value : %s", v.get_boolean().to_string()); this.property_set_bool(property, v.get_boolean()); } } @@ -93,10 +93,10 @@ public class PlayerItem : Dbusmenu.Menuitem public bool populated(HashSet<string> attrs) { foreach(string prop in attrs){ - debug("populated ? - prop: %s", prop); + //debug("populated ? - prop: %s", prop); int value_int = property_get_int(prop); if(property_get_int(prop) != EMPTY){ - debug("populated - prop %s and value %i", prop, value_int); + //debug("populated - prop %s and value %i", prop, value_int); return true; } } diff --git a/src/playlists-menu-item.c b/src/playlists-menu-item.c index 13004ed..d38004c 100644 --- a/src/playlists-menu-item.c +++ b/src/playlists-menu-item.c @@ -28,9 +28,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/menuitem.h> #include <libdbusmenu-glib/server.h> #include <gee.h> +#include <common-defs.h> #include <stdlib.h> #include <string.h> -#include <common-defs.h> #define TYPE_PLAYER_ITEM (player_item_get_type ()) @@ -54,9 +54,6 @@ typedef struct _PlayerItemPrivate PlayerItemPrivate; typedef struct _PlaylistsMenuitem PlaylistsMenuitem; typedef struct _PlaylistsMenuitemClass PlaylistsMenuitemClass; typedef struct _PlaylistsMenuitemPrivate PlaylistsMenuitemPrivate; - -#define TYPE_PLAYLIST_DETAILS (playlist_details_get_type ()) -typedef struct _PlaylistDetails PlaylistDetails; #define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) #define TYPE_PLAYER_CONTROLLER (player_controller_get_type ()) @@ -68,8 +65,10 @@ typedef struct _PlaylistDetails PlaylistDetails; typedef struct _PlayerController PlayerController; typedef struct _PlayerControllerClass PlayerControllerClass; + +#define TYPE_PLAYLIST_DETAILS (playlist_details_get_type ()) +typedef struct _PlaylistDetails PlaylistDetails; typedef struct _Block1Data Block1Data; -#define _playlist_details_free0(var) ((var == NULL) ? NULL : (var = (playlist_details_free (var), NULL))) #define _g_free0(var) (var = (g_free (var), NULL)) typedef struct _PlayerControllerPrivate PlayerControllerPrivate; @@ -102,16 +101,16 @@ struct _PlaylistsMenuitemClass { PlayerItemClass parent_class; }; +struct _PlaylistsMenuitemPrivate { + GeeHashMap* current_playlists; +}; + struct _PlaylistDetails { char* path; gchar* name; gchar* icon_path; }; -struct _PlaylistsMenuitemPrivate { - GeeHashMap* current_playlists; -}; - struct _Block1Data { int _ref_count_; PlaylistsMenuitem * self; @@ -136,11 +135,6 @@ static gpointer playlists_menuitem_parent_class = NULL; GType player_item_get_type (void) G_GNUC_CONST; GType playlists_menuitem_get_type (void) G_GNUC_CONST; -GType playlist_details_get_type (void) G_GNUC_CONST; -PlaylistDetails* playlist_details_dup (const PlaylistDetails* self); -void playlist_details_free (PlaylistDetails* self); -void playlist_details_copy (const PlaylistDetails* self, PlaylistDetails* dest); -void playlist_details_destroy (PlaylistDetails* self); #define PLAYLISTS_MENUITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PLAYLISTS_MENUITEM, PlaylistsMenuitemPrivate)) enum { PLAYLISTS_MENUITEM_DUMMY_PROPERTY @@ -148,6 +142,11 @@ enum { GType player_controller_get_type (void) G_GNUC_CONST; PlaylistsMenuitem* playlists_menuitem_new (PlayerController* parent); PlaylistsMenuitem* playlists_menuitem_construct (GType object_type, PlayerController* parent); +GType playlist_details_get_type (void) G_GNUC_CONST; +PlaylistDetails* playlist_details_dup (const PlaylistDetails* self); +void playlist_details_free (PlaylistDetails* self); +void playlist_details_copy (const PlaylistDetails* self, PlaylistDetails* dest); +void playlist_details_destroy (PlaylistDetails* self); void playlists_menuitem_update (PlaylistsMenuitem* self, PlaylistDetails* playlists, int playlists_length1); static Block1Data* block1_data_ref (Block1Data* _data1_); static void block1_data_unref (Block1Data* _data1_); @@ -155,6 +154,7 @@ static gboolean playlists_menuitem_already_observed (PlaylistsMenuitem* self, Pl static void _lambda1_ (Block1Data* _data1_); static void playlists_menuitem_submenu_item_activated (PlaylistsMenuitem* self, gint menu_item_id); static void __lambda1__dbusmenu_menuitem_item_activated (DbusmenuMenuitem* _sender, guint timestamp, gpointer self); +void playlists_menuitem_update_individual_playlist (PlaylistsMenuitem* self, PlaylistDetails* new_detail); void playlists_menuitem_update_active_playlist (PlaylistsMenuitem* self, PlaylistDetails* detail); PlayerController* player_item_get_owner (PlayerItem* self); GType mpris2_controller_get_type (void) G_GNUC_CONST; @@ -238,12 +238,13 @@ void playlists_menuitem_update (PlaylistsMenuitem* self, PlaylistDetails* playli _tmp3_ = dbusmenu_menuitem_new (); _data1_->menuitem = _tmp3_; dbusmenu_menuitem_property_set (_data1_->menuitem, DBUSMENU_MENUITEM_PROP_LABEL, detail.name); - dbusmenu_menuitem_property_set (_data1_->menuitem, DBUSMENU_MENUITEM_PROP_ICON_NAME, "source-smart-playlist"); + dbusmenu_menuitem_property_set (_data1_->menuitem, DBUSMENU_MENUITEM_PROP_ICON_NAME, detail.icon_path); + dbusmenu_menuitem_property_set (_data1_->menuitem, DBUSMENU_PLAYLIST_MENUITEM_PATH, (const gchar*) detail.path); dbusmenu_menuitem_property_set_bool (_data1_->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); dbusmenu_menuitem_property_set_bool (_data1_->menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE); - _tmp4_ = dbusmenu_menuitem_get_id (_data1_->menuitem); - gee_abstract_map_set ((GeeAbstractMap*) self->priv->current_playlists, GINT_TO_POINTER (_tmp4_), &detail); g_signal_connect_data (_data1_->menuitem, "item-activated", (GCallback) __lambda1__dbusmenu_menuitem_item_activated, block1_data_ref (_data1_), (GClosureNotify) block1_data_unref, 0); + _tmp4_ = dbusmenu_menuitem_get_id (_data1_->menuitem); + gee_abstract_map_set ((GeeAbstractMap*) self->priv->current_playlists, GINT_TO_POINTER (_tmp4_), _data1_->menuitem); dbusmenu_menuitem_child_append (self->root_item, _data1_->menuitem); playlist_details_destroy (&detail); block1_data_unref (_data1_); @@ -254,6 +255,41 @@ void playlists_menuitem_update (PlaylistsMenuitem* self, PlaylistDetails* playli } +void playlists_menuitem_update_individual_playlist (PlaylistsMenuitem* self, PlaylistDetails* new_detail) { + g_return_if_fail (self != NULL); + { + GeeCollection* _tmp0_ = NULL; + GeeCollection* _tmp1_; + GeeIterator* _tmp2_ = NULL; + GeeIterator* _tmp3_; + GeeIterator* _item_it; + _tmp0_ = gee_map_get_values ((GeeMap*) self->priv->current_playlists); + _tmp1_ = _tmp0_; + _tmp2_ = gee_iterable_iterator ((GeeIterable*) _tmp1_); + _item_it = (_tmp3_ = _tmp2_, _g_object_unref0 (_tmp1_), _tmp3_); + while (TRUE) { + gboolean _tmp4_; + gpointer _tmp5_ = NULL; + DbusmenuMenuitem* item; + const gchar* _tmp6_ = NULL; + _tmp4_ = gee_iterator_next (_item_it); + if (!_tmp4_) { + break; + } + _tmp5_ = gee_iterator_get (_item_it); + item = (DbusmenuMenuitem*) _tmp5_; + _tmp6_ = dbusmenu_menuitem_property_get (item, DBUSMENU_PLAYLIST_MENUITEM_PATH); + if (g_strcmp0 ((*new_detail).path, _tmp6_) == 0) { + dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_LABEL, (*new_detail).name); + dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_ICON_NAME, (*new_detail).icon_path); + } + _g_object_unref0 (item); + } + _g_object_unref0 (_item_it); + } +} + + static gboolean playlists_menuitem_already_observed (PlaylistsMenuitem* self, PlaylistDetails* new_detail) { gboolean result = FALSE; g_return_val_if_fail (self != NULL, FALSE); @@ -262,36 +298,38 @@ static gboolean playlists_menuitem_already_observed (PlaylistsMenuitem* self, Pl GeeCollection* _tmp1_; GeeIterator* _tmp2_ = NULL; GeeIterator* _tmp3_; - GeeIterator* _detail_it; + GeeIterator* _item_it; _tmp0_ = gee_map_get_values ((GeeMap*) self->priv->current_playlists); _tmp1_ = _tmp0_; _tmp2_ = gee_iterable_iterator ((GeeIterable*) _tmp1_); - _detail_it = (_tmp3_ = _tmp2_, _g_object_unref0 (_tmp1_), _tmp3_); + _item_it = (_tmp3_ = _tmp2_, _g_object_unref0 (_tmp1_), _tmp3_); while (TRUE) { gboolean _tmp4_; gpointer _tmp5_ = NULL; - PlaylistDetails* _tmp6_; - PlaylistDetails _tmp7_; - PlaylistDetails _tmp8_ = {0}; - PlaylistDetails _tmp9_; - PlaylistDetails detail; - _tmp4_ = gee_iterator_next (_detail_it); + DbusmenuMenuitem* item; + const gchar* _tmp6_ = NULL; + gchar* _tmp7_; + gchar* path; + _tmp4_ = gee_iterator_next (_item_it); if (!_tmp4_) { break; } - _tmp5_ = gee_iterator_get (_detail_it); - _tmp6_ = (PlaylistDetails*) _tmp5_; - _tmp7_ = (playlist_details_copy (_tmp6_, &_tmp8_), _tmp8_); - detail = (_tmp9_ = _tmp7_, _playlist_details_free0 (_tmp6_), _tmp9_); - if (g_strcmp0 ((*new_detail).path, detail.path) == 0) { + _tmp5_ = gee_iterator_get (_item_it); + item = (DbusmenuMenuitem*) _tmp5_; + _tmp6_ = dbusmenu_menuitem_property_get (item, DBUSMENU_PLAYLIST_MENUITEM_PATH); + _tmp7_ = g_strdup (_tmp6_); + path = _tmp7_; + if (g_strcmp0 ((*new_detail).path, path) == 0) { result = TRUE; - playlist_details_destroy (&detail); - _g_object_unref0 (_detail_it); + _g_free0 (path); + _g_object_unref0 (item); + _g_object_unref0 (_item_it); return result; } - playlist_details_destroy (&detail); + _g_free0 (path); + _g_object_unref0 (item); } - _g_object_unref0 (_detail_it); + _g_object_unref0 (_item_it); } result = FALSE; return result; @@ -321,19 +359,21 @@ static void playlists_menuitem_submenu_item_activated (PlaylistsMenuitem* self, gboolean _tmp0_; PlayerController* _tmp1_ = NULL; gpointer _tmp2_ = NULL; - PlaylistDetails* _tmp3_; + DbusmenuMenuitem* _tmp3_; + const gchar* _tmp4_ = NULL; g_return_if_fail (self != NULL); _tmp0_ = gee_abstract_map_has_key ((GeeAbstractMap*) self->priv->current_playlists, GINT_TO_POINTER (menu_item_id)); if (!_tmp0_) { - g_warning ("playlists-menu-item.vala:72: item %i was activated but we don't have a" \ + g_warning ("playlists-menu-item.vala:89: item %i was activated but we don't have a" \ " corresponding playlist", menu_item_id); return; } _tmp1_ = player_item_get_owner ((PlayerItem*) self); _tmp2_ = gee_abstract_map_get ((GeeAbstractMap*) self->priv->current_playlists, GINT_TO_POINTER (menu_item_id)); - _tmp3_ = (PlaylistDetails*) _tmp2_; - mpris2_controller_activate_playlist (_tmp1_->mpris_bridge, (*_tmp3_).path); - _playlist_details_free0 (_tmp3_); + _tmp3_ = (DbusmenuMenuitem*) _tmp2_; + _tmp4_ = dbusmenu_menuitem_property_get (_tmp3_, DBUSMENU_PLAYLIST_MENUITEM_PATH); + mpris2_controller_activate_playlist (_tmp1_->mpris_bridge, (const char*) _tmp4_); + _g_object_unref0 (_tmp3_); } @@ -361,7 +401,7 @@ static GObject * playlists_menuitem_constructor (GType type, guint n_construct_p parent_class = G_OBJECT_CLASS (playlists_menuitem_parent_class); obj = parent_class->constructor (type, n_construct_properties, construct_properties); self = PLAYLISTS_MENUITEM (obj); - _tmp0_ = gee_hash_map_new (G_TYPE_INT, NULL, NULL, TYPE_PLAYLIST_DETAILS, (GBoxedCopyFunc) playlist_details_dup, playlist_details_free, NULL, NULL, NULL); + _tmp0_ = gee_hash_map_new (G_TYPE_INT, NULL, NULL, DBUSMENU_TYPE_MENUITEM, (GBoxedCopyFunc) g_object_ref, g_object_unref, NULL, NULL, NULL); _tmp1_ = _tmp0_; _g_object_unref0 (self->priv->current_playlists); self->priv->current_playlists = _tmp1_; diff --git a/src/playlists-menu-item.vala b/src/playlists-menu-item.vala index 024839c..8a2ccac 100644 --- a/src/playlists-menu-item.vala +++ b/src/playlists-menu-item.vala @@ -19,18 +19,20 @@ with this program. If not, see <http://www.gnu.org/licenses/>. using Dbusmenu; using DbusmenuPlaylists; +using DbusmenuPlaylist; using Gee; public class PlaylistsMenuitem : PlayerItem { - private HashMap<int, PlaylistDetails?> current_playlists; + private HashMap<int, Dbusmenu.Menuitem> current_playlists; public Menuitem root_item; + public PlaylistsMenuitem ( PlayerController parent ) { Object ( item_type: MENUITEM_TYPE, owner: parent ); } construct{ - this.current_playlists = new HashMap<int, PlaylistDetails?>(); + this.current_playlists = new HashMap<int, Dbusmenu.Menuitem>(); this.root_item = new Menuitem(); this.root_item.property_set ( MENUITEM_PROP_LABEL, "Choose Playlist" ); } @@ -38,23 +40,38 @@ public class PlaylistsMenuitem : PlayerItem public new void update (PlaylistDetails[] playlists) { foreach ( PlaylistDetails detail in playlists ){ + if (this.already_observed(detail)) continue; + Dbusmenu.Menuitem menuitem = new Menuitem(); menuitem.property_set (MENUITEM_PROP_LABEL, detail.name); - menuitem.property_set (MENUITEM_PROP_ICON_NAME, "source-smart-playlist"); + menuitem.property_set (MENUITEM_PROP_ICON_NAME, detail.icon_path); + menuitem.property_set (MENUITEM_PATH, (string)detail.path); menuitem.property_set_bool (MENUITEM_PROP_VISIBLE, true); menuitem.property_set_bool (MENUITEM_PROP_ENABLED, true); - this.current_playlists.set( menuitem.id, detail ); + menuitem.item_activated.connect(() => { submenu_item_activated (menuitem.id );}); + this.current_playlists.set( menuitem.id, menuitem ); this.root_item.child_append( menuitem ); } } + public void update_individual_playlist (PlaylistDetails new_detail) + { + foreach ( Dbusmenu.Menuitem item in this.current_playlists.values ){ + if (new_detail.path == item.property_get (MENUITEM_PATH)){ + item.property_set (MENUITEM_PROP_LABEL, new_detail.name); + item.property_set (MENUITEM_PROP_ICON_NAME, new_detail.icon_path); + } + } + } + private bool already_observed (PlaylistDetails new_detail) { - foreach ( PlaylistDetails detail in this.current_playlists.values ){ - if (new_detail.path == detail.path) return true; + foreach ( Dbusmenu.Menuitem item in this.current_playlists.values ){ + var path = item.property_get (MENUITEM_PATH); + if (new_detail.path == path) return true; } return false; } @@ -68,12 +85,12 @@ public class PlaylistsMenuitem : PlayerItem private void submenu_item_activated (int menu_item_id) { - if(!this.current_playlists.has_key(menu_item_id)){ + if (!this.current_playlists.has_key(menu_item_id)) { warning( "item %i was activated but we don't have a corresponding playlist", menu_item_id ); return; } - this.owner.mpris_bridge.activate_playlist ( this.current_playlists[menu_item_id].path ); + this.owner.mpris_bridge.activate_playlist ( (GLib.ObjectPath)this.current_playlists[menu_item_id].property_get (MENUITEM_PATH) ); } public static HashSet<string> attributes_format() diff --git a/src/pulse-manager.c b/src/pulse-manager.c deleted file mode 100644 index 457992b..0000000 --- a/src/pulse-manager.c +++ /dev/null @@ -1,589 +0,0 @@ -/* -A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. - -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <pulse/glib-mainloop.h> -#include <pulse/error.h> -#include <pulse/gccmacro.h> - -#include "pulse-manager.h" - -#define RECONNECT_DELAY 5 - -static GHashTable *sink_hash = NULL; -static SoundServiceDbus *dbus_service = NULL; -static gint DEFAULT_SINK_INDEX = -1; -static gboolean pa_server_available = FALSE; -static gint reconnect_idle_id = 0; -static pa_context *pulse_context = NULL; -static pa_glib_mainloop *pa_main_loop = NULL; - -static void context_state_callback(pa_context *c, void *userdata); -static gboolean reconnect_to_pulse(); -static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink_info, int eol, void *userdata); -static void context_success_callback(pa_context *c, int success, void *userdata); -static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_info *info, int eol, void *userdata); -static void pulse_server_info_callback(pa_context *c, const pa_server_info *info, void *userdata); -static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, void *userdata); -static void destroy_sink_info(void *value); -static gboolean determine_sink_availability(); - -static gboolean has_volume_changed(const pa_sink_info* new_sink, sink_info* cached_sink); -static pa_cvolume construct_mono_volume(const pa_cvolume* vol); - -/** -Future Refactoring notes - - rewrite in vala. - - make sure all state is kept in the service for volume icon switching. -**/ - -/** -Entry point -**/ -void establish_pulse_activities(SoundServiceDbus *service) -{ - dbus_service = service; - pa_main_loop = pa_glib_mainloop_new(g_main_context_default()); - g_assert(pa_main_loop); - pulse_context = pa_context_new(pa_glib_mainloop_get_api(pa_main_loop), - "com.canonical.indicators.sound"); - g_assert(pulse_context); - - sink_hash = g_hash_table_new_full(g_direct_hash, - g_direct_equal, - NULL, - destroy_sink_info); - - // Establish event callback registration - pa_context_set_state_callback (pulse_context, context_state_callback, NULL); - sound_service_dbus_update_pa_state (dbus_service, FALSE, FALSE, 0); - pa_context_connect (pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); -} - -/** -get_context() -Needed for testing - bah! -**/ -pa_context* get_context() -{ - return pulse_context; -} - -static gboolean -reconnect_to_pulse() -{ - g_debug("Attempt to reconnect to pulse"); - // reset - if (pulse_context != NULL) { - pa_context_unref(pulse_context); - pulse_context = NULL; - } - - if (sink_hash != NULL) { - g_hash_table_destroy(sink_hash); - sink_hash = NULL; - } - pulse_context = pa_context_new( pa_glib_mainloop_get_api( pa_main_loop ), - "com.canonical.indicators.sound" ); - g_assert(pulse_context); - sink_hash = g_hash_table_new_full( g_direct_hash, g_direct_equal, - NULL, - destroy_sink_info ); - // Establish event callback registration - pa_context_set_state_callback (pulse_context, context_state_callback, NULL); - int result = pa_context_connect (pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); - - if (result < 0) { - g_warning ("Failed to connect context: %s", - pa_strerror (pa_context_errno (pulse_context))); - } - // we always want to cancel any continious callbacks with the existing timeout - // if the connection failed the new context created above will catch any updates - // to do with the state of pulse and thus take care of business. - reconnect_idle_id = 0; - return FALSE; -} - -/** -close_pulse_activites() -Gracefully close our connection with the Pulse async library. -**/ -void close_pulse_activites() -{ - if (pulse_context != NULL) { - /* g_debug("freeing the pulse context");*/ - pa_context_unref(pulse_context); - pulse_context = NULL; - } - g_hash_table_destroy(sink_hash); - pa_glib_mainloop_free(pa_main_loop); - pa_main_loop = NULL; - /* g_debug("I just closed communication with Pulse");*/ -} - -/** -destroy_sink_info() -item destructor method for the sink_info hash -**/ -static void destroy_sink_info(void *value) -{ - sink_info *sink = (sink_info*)value; - g_free(sink->name); - g_free(sink); -} - -/* -Controllers & Utilities -*/ -static gboolean determine_sink_availability() -{ - // Firstly check to see if we have any sinks - // if not get the hell out of here ! - if (g_hash_table_size(sink_hash) < 1) { - g_debug("Sink_available returning false because sinks_hash is empty !!!"); - DEFAULT_SINK_INDEX = -1; - return FALSE; - } - // Secondly, make sure the default sink index is set - // If the default sink index has not been set - // (via the server or has been reset because default sink has been removed), - // it will attempt to set it to the value of the first - // index in the array of keys from the sink_hash. - GList* keys = g_hash_table_get_keys(sink_hash); - GList* key = g_list_first(keys); - - DEFAULT_SINK_INDEX = (DEFAULT_SINK_INDEX < 0) ? GPOINTER_TO_INT(key->data) : DEFAULT_SINK_INDEX; - - // Thirdly ensure the default sink index does not have the name "auto_null" - sink_info* s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX)); - // Up until now the most robust method to test this is to manually remove the available sink device - // kernel module and then reload (rmmod & modprobe). - // TODO: Edge case of dynamic loading and unloading of sinks should be handled also. - /* g_debug("About to test for to see if the available sink is null - s->name = %s", s->name);*/ - gboolean available = g_ascii_strncasecmp("auto_null", s->name, 9) != 0; - /* g_debug("PA_Manager -> determine_sink_availability: %i", available);*/ - return available; -} - -gboolean default_sink_is_muted() -{ - if (DEFAULT_SINK_INDEX < 0) - return FALSE; - if (g_hash_table_size(sink_hash) < 1) - return FALSE; - sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX)); - return s->mute; -} - -static void check_sink_input_while_muted_event(gint sink_index) -{ - /* g_debug("SINKINPUTWHILEMUTED SIGNAL EVENT TO BE SENT FROM PA MANAGER - check trace for value");*/ - - if (default_sink_is_muted(sink_index) == TRUE) { - sound_service_dbus_update_sound_state(dbus_service, BLOCKED); - } -// Why do you need to send a false for a blocked event, it times out after 5 secs anyway -//} else { - // sound_service_dbus_sink_input_while_muted(dbus_service, FALSE); - //} -} - -static gdouble get_default_sink_volume() -{ - if (DEFAULT_SINK_INDEX < 0) - return 0; - sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX)); - pa_volume_t vol = pa_cvolume_avg(&s->volume); - gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; - /* g_debug("software volume = %f", volume_percent);*/ - return volume_percent; -} - -static void mute_each_sink(gpointer key, gpointer value, gpointer user_data) -{ - sink_info *info = (sink_info*)value; - pa_operation_unref(pa_context_set_sink_mute_by_index(pulse_context, info->index, GPOINTER_TO_INT(user_data), context_success_callback, NULL)); - if (GPOINTER_TO_INT(user_data) == 1) { - sound_service_dbus_update_sink_mute(dbus_service, TRUE); - } else { - sound_service_dbus_update_volume(dbus_service, get_default_sink_volume()); - } -} - -void toggle_global_mute(gboolean mute_value) -{ - g_hash_table_foreach(sink_hash, mute_each_sink, GINT_TO_POINTER(mute_value)); - /* g_debug("in the pulse manager: toggle global mute value %i", mute_value);*/ -} - - -/* -Refine the resolution of the slider or binary scale it to achieve a more subtle volume control. -Use the base volume stored in the sink struct to calculate actual linear volumes. -*/ -void set_sink_volume(gdouble percent) -{ - if (pa_server_available == FALSE) - return; - /* g_debug("in the pulse manager:set_sink_volume with percent %f", percent);*/ - - if (DEFAULT_SINK_INDEX < 0) { - g_warning("We have no default sink !!! - returning after not attempting to set any volume of any sink"); - return; - } - - sink_info *cached_sink = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX)); - - pa_cvolume new_volume; - pa_cvolume_init(&new_volume); - new_volume.channels = 1; - pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100); - pa_cvolume_set(&new_volume, 1, new_volume_value); - pa_cvolume_set(&cached_sink->volume, cached_sink->channel_map.channels, new_volume_value); - pa_operation_unref(pa_context_set_sink_volume_by_index(pulse_context, DEFAULT_SINK_INDEX, &new_volume, NULL, NULL)); -} - - -static pa_cvolume construct_mono_volume(const pa_cvolume* vol) -{ - pa_cvolume new_volume; - pa_cvolume_init(&new_volume); - new_volume.channels = 1; - pa_volume_t max_vol = pa_cvolume_max(vol); - pa_cvolume_set(&new_volume, 1, max_vol); - return new_volume; -} - -/**********************************************************************************************************************/ -// Pulse-Audio asychronous call-backs -/**********************************************************************************************************************/ - -static void gather_pulse_information(pa_context *c, void *userdata) -{ - pa_operation *operation; - if (!(operation = pa_context_get_server_info(c, pulse_server_info_callback, userdata))) { - g_warning("pa_context_get_server_info failed"); - if (!(operation = pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL))) { - g_warning("pa_context_get_sink_info_list() failed - cannot fetch server or sink info - leaving . . ."); - return; - } - } - pa_operation_unref(operation); - return; -} - - -static void context_success_callback(pa_context *c, int success, void *userdata) -{ - /* g_debug("Context Success Callback - result = %i", success);*/ -} - -/** -On Service startup this callback will be called multiple times resulting our sinks_hash container to be filled with the -available sinks. -For now this callback assumes it only used at startup. It may be necessary to use if sinks become available after startup. -Major candidate for refactoring. -**/ -static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, int eol, void *userdata) -{ - if (eol > 0) { - - gboolean device_available = determine_sink_availability(); - if (device_available == TRUE) { - sound_service_dbus_update_pa_state( dbus_service, - device_available, - default_sink_is_muted(), - get_default_sink_volume() ); - } else { - //Update the indicator to show PA either is not ready or has no available sink - g_warning("Cannot find a suitable default sink ..."); - sound_service_dbus_update_pa_state( dbus_service, - device_available, - default_sink_is_muted(), - get_default_sink_volume() ); - } - } else { - /* g_debug("About to add an item to our hash");*/ - sink_info *value; - value = g_new0(sink_info, 1); - value->index = sink->index; - value->name = g_strdup(sink->name); - value->mute = !!sink->mute; - value->volume = construct_mono_volume(&sink->volume); - value->base_volume = sink->base_volume; - value->channel_map = sink->channel_map; - g_hash_table_insert(sink_hash, GINT_TO_POINTER(sink->index), value); - /* g_debug("After adding an item to our hash");*/ - } -} - -static void pulse_default_sink_info_callback(pa_context *c, const pa_sink_info *info, int eol, void *userdata) -{ - if (eol > 0) { - return; - } else { - DEFAULT_SINK_INDEX = info->index; - /* g_debug("Just set the default sink index to %i", DEFAULT_SINK_INDEX); */ - GList *keys = g_hash_table_get_keys(sink_hash); - gint position = g_list_index(keys, GINT_TO_POINTER(info->index)); - // Only update sink-list if the index is not in our already fetched list. - if (position < 0) { - pa_operation_unref(pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL)); - } else { - sound_service_dbus_update_pa_state(dbus_service, - determine_sink_availability(), - default_sink_is_muted(), - get_default_sink_volume()); - } - } -} - -static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_info *info, int eol, void *userdata) -{ - if (eol > 0) { - if (pa_context_errno(c) == PA_ERR_NOENTITY) - return; - /* g_warning("Sink INPUT info callback failure");*/ - return; - } else { - if (info == NULL) { - // TODO: watch this carefully - PA async api should not be doing this . . . - /* g_warning("\n Sink input info callback : SINK INPUT INFO IS NULL BUT EOL was not POSITIVE!!!");*/ - return; - } - /* g_debug("\n SINK INPUT INFO sink index : %d \n", info->sink);*/ - check_sink_input_while_muted_event(info->sink); - } -} - -static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, void *userdata) -{ - if (eol > 0) { - if (pa_context_errno(c) == PA_ERR_NOENTITY) - return; - /* g_warning("Sink INPUT info callback failure");*/ - return; - } - gint position = -1; - GList *keys = g_hash_table_get_keys(sink_hash); - - if (info == NULL) - return; - - position = g_list_index(keys, GINT_TO_POINTER(info->index)); - - if (position >= 0) { // => index is within the keys of the hash. - sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(info->index)); - s->name = g_strdup(info->name); - gboolean mute_changed = s->mute != !!info->mute; - s->mute = !!info->mute; - gboolean volume_changed = has_volume_changed(info, s); - - /* g_debug("new balance : %i", (int)(pa_cvolume_get_balance(&info->volume, &info->channel_map) * 100));*/ - /* g_debug("cached balance : %i", (int)(pa_cvolume_get_balance(&s->volume, &s->channel_map) * 100));*/ - /* g_debug("update_sink_info: new_volume input : %f", (gdouble)(pa_cvolume_max(&info->volume)));*/ - /* g_debug("update sink info: cached volume is at: %f", (gdouble)(pa_cvolume_max(&s->volume)));*/ - /* g_debug("update sink info : volume changed = %i", volume_changed);*/ - /* g_debug("update sink info : compatibility = %i", pa_cvolume_compatible_with_channel_map(&info->volume, &s->channel_map));*/ - - s->volume = construct_mono_volume(&info->volume); - s->channel_map = info->channel_map; - - if (DEFAULT_SINK_INDEX == s->index) { - //update the UI - if (volume_changed == TRUE && s->mute == FALSE) { - pa_volume_t vol = pa_cvolume_max(&s->volume); - gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; - /* g_debug("Updating volume from PA manager with volume = %f", volume_percent);*/ - sound_service_dbus_update_volume(dbus_service, volume_percent); - } - - if (mute_changed == TRUE) { - /* g_debug("Updating Mute from PA manager with mute = %i", s->mute);*/ - sound_service_dbus_update_sink_mute(dbus_service, s->mute); - if (s->mute == FALSE) { - pa_volume_t vol = pa_cvolume_max(&s->volume); - gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM; - /* g_debug("Updating volume from PA manager with volume = %f", volume_percent);*/ - sound_service_dbus_update_volume(dbus_service, volume_percent); - } - } - } - } else { - sink_info *value; - value = g_new0(sink_info, 1); - value->index = info->index; - value->name = g_strdup(info->name); - value->mute = !!info->mute; - value->volume = construct_mono_volume(&info->volume); - value->channel_map = info->channel_map; - value->base_volume = info->base_volume; - g_hash_table_insert(sink_hash, GINT_TO_POINTER(value->index), value); - /* g_debug("pulse-manager:update_sink_info -> After adding a new sink to our hash");*/ - sound_service_dbus_update_sound_state(dbus_service, AVAILABLE); - } -} - - -static gboolean has_volume_changed(const pa_sink_info* new_sink, sink_info* cached_sink) -{ - if (pa_cvolume_compatible_with_channel_map(&new_sink->volume, &cached_sink->channel_map) == FALSE) - return FALSE; - - pa_cvolume new_vol = construct_mono_volume(&new_sink->volume); - - if (pa_cvolume_equal(&new_vol, &(cached_sink->volume)) == TRUE) { - /* g_debug("has_volume_changed: volumes appear to be equal? no change triggered!"); */ - return FALSE; - } - - return TRUE; -} - - -static void pulse_server_info_callback(pa_context *c, - const pa_server_info *info, - void *userdata) -{ - /* g_debug("server info callback");*/ - pa_operation *operation; - if (info == NULL) { - g_warning("No server - get the hell out of here"); - sound_service_dbus_update_pa_state(dbus_service, FALSE, TRUE, 0); - pa_server_available = FALSE; - return; - } - pa_server_available = TRUE; - if (info->default_sink_name != NULL) { - if (!(operation = pa_context_get_sink_info_by_name(c, - info->default_sink_name, - pulse_default_sink_info_callback, - userdata))) { - g_warning("pa_context_get_sink_info_by_name() failed"); - } else { - pa_operation_unref(operation); - return; - } - } - if (!(operation = pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL))) { - g_warning("pa_context_get_sink_info_list() failed"); - return; - } - pa_operation_unref(operation); -} - - -static void subscribed_events_callback(pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) -{ - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SINK: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (index == DEFAULT_SINK_INDEX) - sound_service_dbus_update_sound_state(dbus_service, UNAVAILABLE); - - /* g_debug("Subscribed_events_callback - removing sink of index %i from our sink hash - keep the cache tidy !", index);*/ - g_hash_table_remove(sink_hash, GINT_TO_POINTER(index)); - - if (index == DEFAULT_SINK_INDEX) { - /* g_debug("subscribed_events_callback - PA_SUBSCRIPTION_EVENT_SINK REMOVAL: default sink %i has been removed.", DEFAULT_SINK_INDEX); */ - DEFAULT_SINK_INDEX = -1; - determine_sink_availability(); - } - /* g_debug("subscribed_events_callback - Now what is our default sink : %i", DEFAULT_SINK_INDEX); */ - } else { - /* g_debug("subscribed_events_callback - PA_SUBSCRIPTION_EVENT_SINK: a generic sink event - will trigger an update"); */ - pa_operation_unref(pa_context_get_sink_info_by_index(c, index, update_sink_info, userdata)); - } - break; - case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - /* g_debug("subscribed_events_callback - PA_SUBSCRIPTION_EVENT_SINK_INPUT event triggered!!");*/ - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - //handle the sink input remove event - not relevant for current design - } else { - pa_operation_unref(pa_context_get_sink_input_info(c, index, pulse_sink_input_info_callback, userdata)); - } - break; - case PA_SUBSCRIPTION_EVENT_SERVER: - g_debug("subscribed_events_callback - PA_SUBSCRIPTION_EVENT_SERVER change of some description ???"); - pa_operation *o; - if (!(o = pa_context_get_server_info(c, pulse_server_info_callback, userdata))) { - g_warning("subscribed_events_callback - pa_context_get_server_info() failed"); - return; - } - pa_operation_unref(o); - break; - } -} - - -static void context_state_callback(pa_context *c, void *userdata) -{ - switch (pa_context_get_state(c)) { - case PA_CONTEXT_UNCONNECTED: - g_debug("unconnected"); - break; - case PA_CONTEXT_CONNECTING: - g_debug("connecting - waiting for the server to become available"); - break; - case PA_CONTEXT_AUTHORIZING: - /* g_debug("authorizing");*/ - break; - case PA_CONTEXT_SETTING_NAME: - /* g_debug("context setting name");*/ - break; - case PA_CONTEXT_FAILED: - g_warning("PA_CONTEXT_FAILED - Is PulseAudio Daemon running ?"); - pa_server_available = FALSE; - sound_service_dbus_update_pa_state( dbus_service, - pa_server_available, - default_sink_is_muted(), - get_default_sink_volume() ); - - if (reconnect_idle_id == 0){ - reconnect_idle_id = g_timeout_add_seconds (RECONNECT_DELAY, - reconnect_to_pulse, - NULL); - } - break; - case PA_CONTEXT_TERMINATED: - /* g_debug("context terminated");*/ - break; - case PA_CONTEXT_READY: - g_debug("PA_CONTEXT_READY"); - pa_operation *o; - - pa_context_set_subscribe_callback(c, subscribed_events_callback, userdata); - - if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) - (PA_SUBSCRIPTION_MASK_SINK| - PA_SUBSCRIPTION_MASK_SINK_INPUT| - PA_SUBSCRIPTION_MASK_SERVER), NULL, NULL))) { - g_warning("pa_context_subscribe() failed"); - return; - } - pa_operation_unref(o); - - gather_pulse_information(c, userdata); - - break; - } -} - diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c new file mode 100644 index 0000000..3aed1f1 --- /dev/null +++ b/src/pulseaudio-mgr.c @@ -0,0 +1,406 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/**Notes + * + * Approach now is to set up the communication channels then query the server + * fetch its default sink. If this fails then fetch the list of sinks and take + * the first one which is not the auto-null sink. + * TODO: need to handle the situation where one chink in this linear chain breaks + * i.e. start off the process again and count the attempts (note different to + reconnect attempts) + */ +#include <pulse/gccmacro.h> +#include <pulse/glib-mainloop.h> +#include <pulse/error.h> + +#include "pulseaudio-mgr.h" + +#define RECONNECT_DELAY 5 + + +static void pm_context_state_callback(pa_context *c, void *userdata); +static void pm_subscribed_events_callback (pa_context *c, + enum pa_subscription_event_type t, + uint32_t index, + void* userdata); +static void pm_server_info_callback (pa_context *c, + const pa_server_info *info, + void *userdata); +static void pm_default_sink_info_callback (pa_context *c, + const pa_sink_info *info, + int eol, + void *userdata); +static void pm_sink_info_callback (pa_context *c, + const pa_sink_info *sink, + int eol, + void *userdata); +static void pm_sink_input_info_callback (pa_context *c, + const pa_sink_input_info *info, + int eol, + void *userdata); +static void pm_update_active_sink (pa_context *c, + const pa_sink_info *info, + int eol, + void *userdata); +static void pm_toggle_mute_for_every_sink_callback (pa_context *c, + const pa_sink_info *sink, + int eol, + void* userdata); + +static gboolean reconnect_to_pulse (gpointer user_data); + +static gint connection_attempts = 0; +static gint reconnect_idle_id = 0; +static pa_context *pulse_context = NULL; +static pa_glib_mainloop *pa_main_loop = NULL; + +/** + Entry Point + **/ +void +pm_establish_pulse_connection (ActiveSink* active_sink) +{ + pa_main_loop = pa_glib_mainloop_new (g_main_context_default ()); + g_assert (pa_main_loop); + reconnect_to_pulse ((gpointer)active_sink); +} + +/** +close_pulse_activites() +Gracefully close our connection with the Pulse async library. +**/ +void close_pulse_activites() +{ + if (pulse_context != NULL) { + pa_context_unref(pulse_context); + pulse_context = NULL; + } + pa_glib_mainloop_free(pa_main_loop); + pa_main_loop = NULL; +} + +/** +reconnect_to_pulse (gpointer user_data) +Method which connects to the pulse server and is used to track reconnects. + */ +static gboolean +reconnect_to_pulse (gpointer user_data) +{ + g_debug("Attempt to reconnect to pulse"); + // reset + connection_attempts += 1; + if (pulse_context != NULL) { + pa_context_unref(pulse_context); + pulse_context = NULL; + } + + pulse_context = pa_context_new( pa_glib_mainloop_get_api( pa_main_loop ), + "com.canonical.indicators.sound" ); + g_assert(pulse_context); + pa_context_set_state_callback (pulse_context, + pm_context_state_callback, + user_data); + int result = pa_context_connect (pulse_context, + NULL, + PA_CONTEXT_NOFAIL, + user_data); + + if (result < 0) { + g_warning ("Failed to connect context: %s", + pa_strerror (pa_context_errno (pulse_context))); + } + if (connection_attempts > 5){ + return FALSE; + } + else{ + return TRUE; + } +} + +void +pm_update_volume (gint sink_index, pa_cvolume new_volume) +{ + pa_operation_unref (pa_context_set_sink_volume_by_index (pulse_context, + sink_index, + &new_volume, + NULL, + NULL) ); +} + +void +pm_update_mute (gboolean update) +{ + pa_operation_unref (pa_context_get_sink_info_list (pulse_context, + pm_toggle_mute_for_every_sink_callback, + GINT_TO_POINTER (update))); +} + +/**********************************************************************************************************************/ +// Pulse-Audio asychronous call-backs +/**********************************************************************************************************************/ + + +static void +pm_subscribed_events_callback (pa_context *c, + enum pa_subscription_event_type t, + uint32_t index, + void* userdata) +{ + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + case PA_SUBSCRIPTION_EVENT_SINK: + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("subscribed events callback - our userdata is not what we think it should be"); + return; + } + ActiveSink* sink = ACTIVE_SINK (userdata); + // We don't care about any other sink other than the active one. + if (index != active_sink_get_index (sink)) + return; + + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + active_sink_deactivate (ACTIVE_SINK (userdata)); + + } + else{ + pa_operation_unref (pa_context_get_sink_info_by_index (c, + index, + pm_update_active_sink, + userdata) ); + } + break; + case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + // We don't care about sink input removals. + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_REMOVE) { + pa_operation_unref (pa_context_get_sink_input_info (c, + index, + pm_sink_input_info_callback, userdata)); + } + break; + case PA_SUBSCRIPTION_EVENT_SERVER: + g_debug("PA_SUBSCRIPTION_EVENT_SERVER event triggered."); + pa_operation *o; + if (!(o = pa_context_get_server_info (c, pm_server_info_callback, userdata))) { + g_warning("subscribed_events_callback - pa_context_get_server_info() failed"); + return; + } + pa_operation_unref(o); + break; + } +} + + +static void +pm_context_state_callback (pa_context *c, void *userdata) +{ + switch (pa_context_get_state(c)) { + case PA_CONTEXT_UNCONNECTED: + g_debug("unconnected"); + break; + case PA_CONTEXT_CONNECTING: + g_debug("connecting - waiting for the server to become available"); + break; + case PA_CONTEXT_AUTHORIZING: + break; + case PA_CONTEXT_SETTING_NAME: + break; + case PA_CONTEXT_FAILED: + g_warning("PA_CONTEXT_FAILED - Is PulseAudio Daemon running ?"); + active_sink_deactivate (ACTIVE_SINK (userdata)); + if (reconnect_idle_id == 0){ + reconnect_idle_id = g_timeout_add_seconds (RECONNECT_DELAY, + reconnect_to_pulse, + userdata); + } + break; + case PA_CONTEXT_TERMINATED: + break; + case PA_CONTEXT_READY: + connection_attempts = 0; + g_debug("PA_CONTEXT_READY"); + if (reconnect_idle_id != 0){ + g_source_remove (reconnect_idle_id); + reconnect_idle_id = 0; + } + pa_operation *o; + + pa_context_set_subscribe_callback(c, pm_subscribed_events_callback, userdata); + + if (!(o = pa_context_subscribe (c, (pa_subscription_mask_t) + (PA_SUBSCRIPTION_MASK_SINK| + PA_SUBSCRIPTION_MASK_SINK_INPUT| + PA_SUBSCRIPTION_MASK_SERVER), NULL, NULL))) { + g_warning("pa_context_subscribe() failed"); + + } + + if (!(o = pa_context_get_server_info (c, pm_server_info_callback, userdata))) { + g_warning("Initial - pa_context_get_server_info() failed"); + } + pa_operation_unref(o); + + break; + } +} + +/** + After startup we go straight for the server info to see if it has details of + the default sink. If so it makes things much easier. + **/ +static void +pm_server_info_callback (pa_context *c, + const pa_server_info *info, + void *userdata) +{ + pa_operation *operation; + g_debug ("server info callback"); + + if (info == NULL) { + g_warning("No PA server - get the hell out of here"); + active_sink_deactivate (ACTIVE_SINK (userdata)); + return; + } + if (info->default_sink_name != NULL) { + g_debug ("default sink name from the server ain't null'"); + if (!(operation = pa_context_get_sink_info_by_name (c, + info->default_sink_name, + pm_default_sink_info_callback, + userdata) )) { + } + else{ + pa_operation_unref(operation); + return; + } + } + else if (!(operation = pa_context_get_sink_info_list(c, + pm_sink_info_callback, + NULL))) { + g_warning("pa_context_get_sink_info_list() failed"); + return; + } + pa_operation_unref(operation); +} + +// If the server doesn't have a default sink to give us +// we should attempt to pick up the first of the list of sinks which doesn't have +// the name 'auto_null' (that was all really I was doing before) +static void +pm_sink_info_callback (pa_context *c, + const pa_sink_info *sink, + int eol, + void* userdata) +{ + if (eol > 0) { + return; + } + else { + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("sink info callback - our user data is not what we think it should be"); + return; + } + ActiveSink* a_sink = ACTIVE_SINK (userdata); + if (active_sink_is_populated (a_sink) == FALSE && + g_ascii_strncasecmp("auto_null", sink->name, 9) != 0){ + active_sink_populate (a_sink, sink); + } + } +} + +static void +pm_default_sink_info_callback (pa_context *c, + const pa_sink_info *info, + int eol, + void *userdata) +{ + if (eol > 0) { + return; + } + else { + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("Default sink info callback - our user data is not what we think it should be"); + return; + } + g_debug ("server has handed us a default sink"); + active_sink_populate (ACTIVE_SINK (userdata), info); + } +} + +static void +pm_sink_input_info_callback (pa_context *c, + const pa_sink_input_info *info, + int eol, + void *userdata) +{ + if (eol > 0) { + return; + } + else { + if (info == NULL) { + // TODO: watch this carefully - PA async api should not be doing this . . . + g_warning("\n Sink input info callback : SINK INPUT INFO IS NULL BUT EOL was not POSITIVE!!!"); + return; + } + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("sink input info callback - our user data is not what we think it should be"); + return; + } + + ActiveSink* a_sink = ACTIVE_SINK (userdata); + if (active_sink_get_index (a_sink) == info->sink){ + active_sink_determine_blocking_state (a_sink); + } + } +} + +static void +pm_update_active_sink (pa_context *c, + const pa_sink_info *info, + int eol, + void *userdata) +{ + if (eol > 0) { + return; + } + else{ + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("update_active_sink - our user data is not what we think it should be"); + return; + } + active_sink_update (ACTIVE_SINK(userdata), info); + } +} + +static void +pm_toggle_mute_for_every_sink_callback (pa_context *c, + const pa_sink_info *sink, + int eol, + void* userdata) +{ + if (eol > 0) { + return; + } + else { + pa_operation_unref (pa_context_set_sink_mute_by_index (c, + sink->index, + GPOINTER_TO_INT(userdata), + NULL, + NULL)); + } +} + diff --git a/src/pulse-manager.h b/src/pulseaudio-mgr.h index 5895aeb..c0ab9c0 100644 --- a/src/pulse-manager.h +++ b/src/pulseaudio-mgr.h @@ -1,7 +1,5 @@ -#ifndef __INCLUDE_PULSE_MANAGER_H__ -#define __INCLUDE_PULSE_MANAGER_H__ /* -Copyright 2010 Canonical Ltd. +Copyright 2011 Canonical Ltd. Authors: Conor Curran <conor.curran@canonical.com> @@ -19,27 +17,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "active-sink.h" + +void pm_establish_pulse_connection (ActiveSink* active_sink); +void close_pulse_activites(); +void pm_update_volume (gint sink_index, pa_cvolume new_volume); +void pm_update_mute (gboolean update); -#include <pulse/pulseaudio.h> -#include <glib.h> -#include "sound-service-dbus.h" -typedef struct { - gchar* name; - gint index; - pa_cvolume volume; - pa_channel_map channel_map; - gboolean mute; - pa_volume_t base_volume; -} sink_info; -pa_context* get_context(void); -void establish_pulse_activities(SoundServiceDbus *service); -void set_sink_volume(gdouble percent); -void toggle_global_mute(gboolean mute_value); -void close_pulse_activites(); -gboolean default_sink_is_muted(); -#endif diff --git a/src/settings-manager.c b/src/settings-manager.c index 94dc8f9..d383b4f 100644 --- a/src/settings-manager.c +++ b/src/settings-manager.c @@ -71,6 +71,7 @@ void settings_manager_clear_list (SettingsManager* self); void settings_manager_add_interested (SettingsManager* self, const gchar* app_desktop_name); static void _vala_array_add1 (gchar*** array, int* length, int* size, gchar* value); static void settings_manager_on_blacklist_event (SettingsManager* self); +static void settings_manager_reveal_contents (SettingsManager* self); static void g_cclosure_user_marshal_VOID__BOXED_INT (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data); static GObject * settings_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties); static void _settings_manager_on_blacklist_event_g_settings_changed (GSettings* _sender, const gchar* key, gpointer self); @@ -242,6 +243,67 @@ static void settings_manager_on_blacklist_event (SettingsManager* self) { } +static void settings_manager_reveal_contents (SettingsManager* self) { + gchar** _tmp0_; + gchar** _tmp1_ = NULL; + gchar** already_interested; + gint already_interested_length1; + gint _already_interested_size_; + gchar** _tmp3_; + gchar** _tmp4_ = NULL; + gchar** blacklisted; + gint blacklisted_length1; + gint _blacklisted_size_; + g_return_if_fail (self != NULL); + _tmp1_ = _tmp0_ = g_settings_get_strv (self->priv->settings, "interested-media-players"); + already_interested = _tmp1_; + already_interested_length1 = _vala_array_length (_tmp0_); + _already_interested_size_ = _vala_array_length (_tmp0_); + { + gchar** s_collection; + int s_collection_length1; + int s_it; + s_collection = already_interested; + s_collection_length1 = already_interested_length1; + for (s_it = 0; s_it < already_interested_length1; s_it = s_it + 1) { + gchar* _tmp2_; + gchar* s; + _tmp2_ = g_strdup (s_collection[s_it]); + s = _tmp2_; + { + g_debug ("settings-manager.vala:79: client %s is in interested array", s); + _g_free0 (s); + } + } + } + _tmp4_ = _tmp3_ = g_settings_get_strv (self->priv->settings, "blacklisted-media-players"); + blacklisted = _tmp4_; + blacklisted_length1 = _vala_array_length (_tmp3_); + _blacklisted_size_ = _vala_array_length (_tmp3_); + { + gchar** s_collection; + int s_collection_length1; + int s_it; + s_collection = blacklisted; + s_collection_length1 = blacklisted_length1; + for (s_it = 0; s_it < blacklisted_length1; s_it = s_it + 1) { + gchar* _tmp5_; + gchar* s; + _tmp5_ = g_strdup (s_collection[s_it]); + s = _tmp5_; + { + g_debug ("settings-manager.vala:84: client %s is in blacklisted array", s); + _g_free0 (s); + } + } + } + g_debug ("settings-manager.vala:87: interested array size = %i", already_interested_length1); + g_debug ("settings-manager.vala:88: blacklisted array size = %i", blacklisted_length1); + blacklisted = (_vala_array_free (blacklisted, blacklisted_length1, (GDestroyNotify) g_free), NULL); + already_interested = (_vala_array_free (already_interested, already_interested_length1, (GDestroyNotify) g_free), NULL); +} + + static void g_cclosure_user_marshal_VOID__BOXED_INT (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) { typedef void (*GMarshalFunc_VOID__BOXED_INT) (gpointer data1, gpointer arg_1, gint arg_2, gpointer data2); register GMarshalFunc_VOID__BOXED_INT callback; diff --git a/src/settings-manager.vala b/src/settings-manager.vala index 380e442..057a47b 100644 --- a/src/settings-manager.vala +++ b/src/settings-manager.vala @@ -52,7 +52,7 @@ public class SettingsManager : GLib.Object this.settings.reset("interested-media-players"); } - public void add_interested(string app_desktop_name) + public void add_interested (string app_desktop_name) { var already_interested = this.settings.get_strv ("interested-media-players"); foreach (var s in already_interested){ @@ -67,5 +67,24 @@ public class SettingsManager : GLib.Object private void on_blacklist_event() { this.blacklist_updates(this.settings.get_strv ("blacklisted-media-players")); - } + } + + // Convenient debug method inorder to provide visability over + // the contents of both interested and blacklisted containers in its gsettings + private void reveal_contents() + { + var already_interested = this.settings.get_strv ("interested-media-players"); + foreach (var s in already_interested) + { + debug ("client %s is in interested array", s); + } + var blacklisted = this.settings.get_strv ("blacklisted-media-players"); + foreach (var s in blacklisted) + { + debug ("client %s is in blacklisted array", s); + } + + debug ("interested array size = %i", already_interested.length); + debug ("blacklisted array size = %i", blacklisted.length); + } } diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c index a20bb00..b89f5ca 100644 --- a/src/slider-menu-item.c +++ b/src/slider-menu-item.c @@ -22,13 +22,12 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <glib/gi18n.h> #include "slider-menu-item.h" -#include "pulse-manager.h" #include "common-defs.h" - typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate; struct _SliderMenuItemPrivate { + ActiveSink* a_sink; }; #define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate)) @@ -43,7 +42,8 @@ static void handle_event (DbusmenuMenuitem * mi, const gchar * name, G_DEFINE_TYPE (SliderMenuItem, slider_menu_item, DBUSMENU_TYPE_MENUITEM); -static void slider_menu_item_class_init (SliderMenuItemClass *klass) +static void +slider_menu_item_class_init (SliderMenuItemClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -57,13 +57,18 @@ static void slider_menu_item_class_init (SliderMenuItemClass *klass) return; } -static void slider_menu_item_init (SliderMenuItem *self) +static void +slider_menu_item_init (SliderMenuItem *self) { g_debug("Building new Slider Menu Item"); + dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self), + DBUSMENU_MENUITEM_PROP_TYPE, + DBUSMENU_VOLUME_MENUITEM_TYPE ); return; } -static void slider_menu_item_dispose (GObject *object) +static void +slider_menu_item_dispose (GObject *object) { G_OBJECT_CLASS (slider_menu_item_parent_class)->dispose (object); return; @@ -89,27 +94,26 @@ handle_event (DbusmenuMenuitem * mi, gboolean volume_input = g_variant_get_double(input); if (value != NULL){ - set_sink_volume(volume_input); - // TODO -when the ACTIVESINK instance exists this will be handled nicely - // PA MANAGER will be refactored first. - if (default_sink_is_muted () == TRUE){ - toggle_global_mute (FALSE); - } + if (IS_SLIDER_MENU_ITEM (mi)) { + SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (SLIDER_MENU_ITEM (mi)); + active_sink_update_volume (priv->a_sink, volume_input); + active_sink_ensure_sink_is_unmuted (priv->a_sink); + } } } -void slider_menu_item_update (SliderMenuItem* item, +void +slider_menu_item_update (SliderMenuItem* item, gdouble update) { - // TODO - // Check if that variant below will leak !!! GVariant* new_volume = g_variant_new_double(update); dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item), DBUSMENU_VOLUME_MENUITEM_LEVEL, new_volume); } -void slider_menu_item_enable (SliderMenuItem* item, +void +slider_menu_item_enable (SliderMenuItem* item, gboolean active) { dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item), @@ -117,15 +121,11 @@ void slider_menu_item_enable (SliderMenuItem* item, active ); } -SliderMenuItem* slider_menu_item_new (gboolean sinks_available, - gdouble start_volume) +SliderMenuItem* +slider_menu_item_new (ActiveSink* sink) { SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL); - dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self), - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_VOLUME_MENUITEM_TYPE ); - slider_menu_item_update (self, start_volume); - slider_menu_item_enable (self, sinks_available); - + SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self); + priv->a_sink = sink; return self; }
\ No newline at end of file diff --git a/src/slider-menu-item.h b/src/slider-menu-item.h index 51336ae..f094c71 100644 --- a/src/slider-menu-item.h +++ b/src/slider-menu-item.h @@ -23,6 +23,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <glib-object.h> #include <libdbusmenu-glib/menuitem.h> +#include "active-sink.h" G_BEGIN_DECLS @@ -49,8 +50,7 @@ GType slider_menu_item_get_type (void); void slider_menu_item_update(SliderMenuItem* item, gdouble update); void slider_menu_item_enable(SliderMenuItem* item, gboolean active); -SliderMenuItem* slider_menu_item_new (gboolean sinks_available, - gdouble current_vol); +SliderMenuItem* slider_menu_item_new (ActiveSink* sink); G_END_DECLS diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c index a532c0e..58367f4 100644 --- a/src/sound-service-dbus.c +++ b/src/sound-service-dbus.c @@ -29,13 +29,9 @@ #include <libdbusmenu-glib/client.h> #include "sound-service-dbus.h" - +#include "active-sink.h" #include "gen-sound-service.xml.h" #include "dbus-shared-names.h" -#include "pulse-manager.h" -#include "slider-menu-item.h" -#include "mute-menu-item.h" -#include "pulse-manager.h" // DBUS methods static void bus_method_call (GDBusConnection * connection, @@ -57,16 +53,14 @@ static GDBusInterfaceVTable interface_table = { typedef struct _SoundServiceDbusPrivate SoundServiceDbusPrivate; struct _SoundServiceDbusPrivate { - GDBusConnection* connection; - DbusmenuMenuitem* root_menuitem; - SliderMenuItem* volume_slider_menuitem; - MuteMenuItem* mute_menuitem; - SoundState current_sound_state; + GDBusConnection* connection; + DbusmenuMenuitem* root_menuitem; + ActiveSink* active_sink; }; static GDBusNodeInfo * node_info = NULL; static GDBusInterfaceInfo * interface_info = NULL; -static gboolean b_startup = TRUE; + #define SOUND_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUND_SERVICE_DBUS_TYPE, SoundServiceDbusPrivate)) static void sound_service_dbus_class_init (SoundServiceDbusClass *klass); @@ -74,17 +68,12 @@ static void sound_service_dbus_init (SoundServiceDbus *self); static void sound_service_dbus_dispose (GObject *object); static void sound_service_dbus_finalize (GObject *object); -static void sound_service_dbus_build_sound_menu ( SoundServiceDbus* root, - gboolean mute_update, - gboolean availability, - gdouble volume ); static void show_sound_settings_dialog (DbusmenuMenuitem *mi, gpointer user_data); -static SoundState sound_service_dbus_get_state_from_volume (SoundServiceDbus* self); -static void sound_service_dbus_determine_state (SoundServiceDbus* self, - gboolean availability, - gboolean mute, - gdouble volume); +static gboolean sound_service_dbus_blacklist_player (SoundServiceDbus* self, + gchar* player_name, + gboolean blacklist); + G_DEFINE_TYPE (SoundServiceDbus, sound_service_dbus, G_TYPE_OBJECT); @@ -129,8 +118,6 @@ sound_service_dbus_init (SoundServiceDbus *self) priv->connection = NULL; - priv->current_sound_state = UNAVAILABLE; - /* Fetch the session bus */ priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); @@ -163,32 +150,26 @@ sound_service_dbus_create_root_item (SoundServiceDbus* self) DbusmenuServer *server = dbusmenu_server_new(INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH); dbusmenu_server_set_root (server, priv->root_menuitem); g_object_unref (priv->root_menuitem); - establish_pulse_activities (self); + priv->active_sink = active_sink_new (self); return priv->root_menuitem; } -static void +void sound_service_dbus_build_sound_menu ( SoundServiceDbus* self, - gboolean mute_update, - gboolean availability, - gdouble volume ) + DbusmenuMenuitem* mute_item, + DbusmenuMenuitem* slider_item) { SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self); // Mute button - priv->mute_menuitem = mute_menu_item_new ( mute_update, availability); - dbusmenu_menuitem_child_append (priv->root_menuitem, - mute_menu_item_get_button (priv->mute_menuitem)); - - // Slider - priv->volume_slider_menuitem = slider_menu_item_new ( availability, volume ); - dbusmenu_menuitem_child_append (priv->root_menuitem, DBUSMENU_MENUITEM ( priv->volume_slider_menuitem )); + dbusmenu_menuitem_child_append (priv->root_menuitem, mute_item); + g_debug ("just about to add the slider %i", DBUSMENU_IS_MENUITEM(slider_item)); + dbusmenu_menuitem_child_append (priv->root_menuitem, slider_item); // Separator - DbusmenuMenuitem* separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set( separator, + dbusmenu_menuitem_property_set (separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); dbusmenu_menuitem_child_append(priv->root_menuitem, separator); @@ -203,9 +184,7 @@ sound_service_dbus_build_sound_menu ( SoundServiceDbus* self, dbusmenu_menuitem_child_append(priv->root_menuitem, settings_mi); g_object_unref (settings_mi); g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_sound_settings_dialog), NULL); - - sound_service_dbus_determine_state (self, availability, mute_update, volume); + G_CALLBACK(show_sound_settings_dialog), NULL); } /** @@ -225,41 +204,11 @@ show_sound_settings_dialog (DbusmenuMenuitem *mi, } } -void -sound_service_dbus_update_pa_state ( SoundServiceDbus* self, - gboolean availability, - gboolean mute_update, - gdouble volume ) -{ - g_debug("update pa state with availability of %i, mute value of %i and a volume percent is %f", availability, mute_update, volume); - SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self); - - if (b_startup == TRUE) { - sound_service_dbus_build_sound_menu ( self, - mute_update, - availability, - volume ); - b_startup = FALSE; - return; - } - - mute_menu_item_update ( priv->mute_menuitem, - mute_update ); - slider_menu_item_update ( priv->volume_slider_menuitem, - volume ); - - mute_menu_item_enable ( priv->mute_menuitem, availability); - slider_menu_item_enable ( priv->volume_slider_menuitem, - availability ); - sound_service_dbus_determine_state (self, availability, mute_update, volume); - -} - - static void sound_service_dbus_dispose (GObject *object) { G_OBJECT_CLASS (sound_service_dbus_parent_class)->dispose (object); + //TODO dispose of the active sink instance ! return; } @@ -270,101 +219,19 @@ sound_service_dbus_finalize (GObject *object) return; } -// UNTIL PA-MANAGER IS REFACTORED AND THE ACTIVESINK CLASS IS CREATED LEAVE -// THE UI ELEMENTS SEPARATELY HANDLED LIKE THIS. -void -sound_service_dbus_update_volume (SoundServiceDbus* self, - gdouble volume) -{ - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); - slider_menu_item_update (priv->volume_slider_menuitem, volume); - sound_service_dbus_update_sound_state (self, - sound_service_dbus_get_state_from_volume (self)); -} - -void -sound_service_dbus_update_sink_mute (SoundServiceDbus* self, - gboolean mute_update) -{ - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); - mute_menu_item_update (priv->mute_menuitem, mute_update); - SoundState state = sound_service_dbus_get_state_from_volume (self); - if (mute_update == TRUE){ - state = MUTED; - } - sound_service_dbus_update_sound_state (self, state); -} - -/*------- State calculators ------------------*/ -static SoundState -sound_service_dbus_get_state_from_volume (SoundServiceDbus* self) -{ - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); - GVariant* v = dbusmenu_menuitem_property_get_variant (DBUSMENU_MENUITEM(priv->volume_slider_menuitem), - DBUSMENU_VOLUME_MENUITEM_LEVEL); - gdouble volume_percent = g_variant_get_double (v); - - SoundState state = LOW_LEVEL; - - if (volume_percent < 30.0 && volume_percent > 0) { - state = LOW_LEVEL; - } - else if (volume_percent < 70.0 && volume_percent >= 30.0) { - state = MEDIUM_LEVEL; - } - else if (volume_percent >= 70.0) { - state = HIGH_LEVEL; - } - else if (volume_percent == 0.0) { - state = ZERO_LEVEL; - } - return state; -} - -static void -sound_service_dbus_determine_state (SoundServiceDbus* self, - gboolean availability, - gboolean mute, - gdouble volume) -{ - SoundState update; - if (availability == FALSE) { - update = UNAVAILABLE; - } - else if (mute == TRUE) { - update = MUTED; - } - else{ - update = sound_service_dbus_get_state_from_volume (self); - } - sound_service_dbus_update_sound_state (self, update); -} - // EMIT STATE SIGNAL - -// TODO: this will be a bit messy until the pa_manager is sorted. -// And we figure out all of the edge cases. void sound_service_dbus_update_sound_state (SoundServiceDbus* self, SoundState new_state) { SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); - SoundState update = new_state; - // Ensure that after it has become available update the state with the current volume level - if (new_state == AVAILABLE && - mute_menu_item_is_muted (priv->mute_menuitem) == FALSE){ - update = sound_service_dbus_get_state_from_volume (self); - } - if (update != BLOCKED){ - priv->current_sound_state = update; - } - GVariant* v_output = g_variant_new("(i)", (int)update); + GVariant* v_output = g_variant_new("(i)", (int)new_state); GError * error = NULL; - g_debug ("emitting signal with value %i", (int)update); + g_debug ("emitting state signal with value %i", (int)new_state); g_dbus_connection_emit_signal( priv->connection, NULL, INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH, @@ -380,7 +247,6 @@ sound_service_dbus_update_sound_state (SoundServiceDbus* self, } //HANDLE DBUS METHOD CALLS -// TODO we will need to implement the black_list method. static void bus_method_call (GDBusConnection * connection, const gchar * sender, @@ -397,15 +263,108 @@ bus_method_call (GDBusConnection * connection, SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (service); if (g_strcmp0(method, "GetSoundState") == 0) { - g_debug("Get state - %i", priv->current_sound_state ); - retval = g_variant_new ( "(i)", priv->current_sound_state); + g_debug("Get state - %i", active_sink_get_state (priv->active_sink)); + retval = g_variant_new ( "(i)", active_sink_get_state (priv->active_sink)); } + else if (g_strcmp0(method, "BlacklistMediaPlayer") == 0) { + gboolean blacklist; + gchar* player_name; + g_variant_get (params, "(sb)", &player_name, &blacklist); + + g_debug ("BlacklistMediaPlayer - bool %i", blacklist); + g_debug ("BlacklistMediaPlayer - name %s", player_name); + gboolean result = sound_service_dbus_blacklist_player (service, + player_name, + blacklist); + retval = g_variant_new ("(b)", result); + } else { g_warning("Calling method '%s' on the sound service but it's unknown", method); } g_dbus_method_invocation_return_value (invocation, retval); } +/** + TODO - Works nicely but refactor into at least two different methods +**/ +static gboolean sound_service_dbus_blacklist_player (SoundServiceDbus* self, + gchar* player_name, + gboolean blacklist) +{ + gboolean result = FALSE; + GSettings* our_settings = NULL; + our_settings = g_settings_new ("com.canonical.indicators.sound"); + GVariant* the_black_list = g_settings_get_value (our_settings, + "blacklisted-media-players"); + GVariantIter iter; + gchar *str; + // Firstly prep new array which will be set on the key. + GVariantBuilder builder; + + g_variant_iter_init (&iter, the_black_list); + g_variant_builder_init(&builder, G_VARIANT_TYPE_STRING_ARRAY); + while (g_variant_iter_loop (&iter, "s", &str)){ + g_variant_builder_add (&builder, "s", str); + } + g_variant_iter_init (&iter, the_black_list); + + if (blacklist == TRUE){ + while (g_variant_iter_loop (&iter, "s", &str)){ + g_print ("first pass to check if %s is present\n", str); + if (g_strcmp0 (player_name, str) == 0){ + // Return if its already there + g_debug ("we have this already blacklisted, no need to do anything"); + g_variant_builder_clear (&builder); + g_object_unref (our_settings); + g_variant_unref (the_black_list); + return result; + } + } + // Otherwise blacklist it ! + g_debug ("about to blacklist %s", player_name); + g_variant_builder_add (&builder, "s", player_name); + } + else{ + gboolean present = FALSE; + g_variant_iter_init (&iter, the_black_list); + g_debug ("attempting to UN-blacklist %s", player_name); + + while (g_variant_iter_loop (&iter, "s", &str)){ + if (g_strcmp0 (player_name, str) == 0){ + present = TRUE; + } + } + // It was not there anyway, return false + if (present == FALSE){ + g_debug ("it was not blacklisted ?, no need to do anything"); + g_variant_builder_clear (&builder); + g_object_unref (our_settings); + g_variant_unref (the_black_list); + return result; + } + + // Otherwise free the builder and reconstruct ensuring no duplicates. + g_variant_builder_clear (&builder); + g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY); + + g_variant_iter_init (&iter, the_black_list); + + while (g_variant_iter_loop (&iter, "s", &str)){ + if (g_strcmp0 (player_name, str) != 0){ + g_variant_builder_add (&builder, "s", str); + } + } + } + GVariant* value = g_variant_builder_end (&builder); + result = g_settings_set_value (our_settings, + "blacklisted-media-players", + value); + + g_object_unref (our_settings); + g_variant_unref (the_black_list); + + return result; +} diff --git a/src/sound-service-dbus.h b/src/sound-service-dbus.h index fab3549..cdc4608 100644 --- a/src/sound-service-dbus.h +++ b/src/sound-service-dbus.h @@ -55,12 +55,10 @@ GType sound_service_dbus_get_type (void) G_GNUC_CONST; DbusmenuMenuitem* sound_service_dbus_create_root_item (SoundServiceDbus* self); void sound_service_dbus_update_sound_state (SoundServiceDbus* self, SoundState new_state); -void sound_service_dbus_update_sink_mute(SoundServiceDbus* self, gboolean sink_mute); -void sound_service_dbus_update_volume(SoundServiceDbus* self, gdouble volume); -void sound_service_dbus_update_pa_state ( SoundServiceDbus* root, - gboolean availability, - gboolean mute_update, - gdouble volume ); +void sound_service_dbus_build_sound_menu ( SoundServiceDbus* self, + DbusmenuMenuitem* mute_item, + DbusmenuMenuitem* slider_item); + G_END_DECLS diff --git a/src/sound-service.c b/src/sound-service.c index 2cb33d3..cfc0b7e 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -18,8 +18,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sound-service.h" - -#include "pulse-manager.h" +#include "pulseaudio-mgr.h" #include "sound-service-dbus.h" #include "music-player-bridge.h" diff --git a/src/sound-service.xml b/src/sound-service.xml index 18e47fc..81ebc2d 100644 --- a/src/sound-service.xml +++ b/src/sound-service.xml @@ -2,12 +2,13 @@ <node name="/com/canonical/indicators/sound"> <interface name="com.canonical.indicators.sound"> <method name = "BlacklistMediaPlayer"> - <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_blacklist_media_player"/> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> <arg type='s' name='player_desktop_name' direction="in"/> <arg type='b' name='blacklist' direction="in"/> + <arg type='b' name='result' direction="out"/> </method> <method name = "GetSoundState"> - <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_get_sink_state"/> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> <arg type='i' name='current_state' direction="out"/> </method> <signal name="SoundStateUpdate"> diff --git a/src/sound-state-manager.c b/src/sound-state-manager.c index e8865d8..a592711 100644 --- a/src/sound-state-manager.c +++ b/src/sound-state-manager.c @@ -18,6 +18,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <libindicator/indicator-image-helper.h> +#include <libnotify/notify.h> + +#include "config.h" + #include "sound-state-manager.h" #include "dbus-shared-names.h" @@ -30,6 +34,8 @@ struct _SoundStateManagerPrivate GList* blocked_animation_list; SoundState current_state; GtkImage* speaker_image; + NotifyNotification* notification; + GSettings *settings_manager; }; #define SOUND_STATE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUND_TYPE_STATE_MANAGER, SoundStateManagerPrivate)) @@ -41,7 +47,11 @@ static gint animation_id; static GList* blocked_iter = NULL; static gboolean can_animate = FALSE; -static void sound_state_manager_prepare_blocked_animation(SoundStateManager* self); +//Notifications +static void sound_state_manager_notification_init (SoundStateManager* self); + +//Animation/State related +static void sound_state_manager_prepare_blocked_animation (SoundStateManager* self); static gboolean sound_state_manager_start_animation (gpointer user_data); static gboolean sound_state_manager_fade_back_to_mute_image (gpointer user_data); static void sound_state_manager_reset_mute_blocking_animation (SoundStateManager* self); @@ -54,6 +64,7 @@ static void sound_state_signal_cb ( GDBusProxy* proxy, gpointer user_data ); static gboolean sound_state_manager_can_proceed_with_blocking_animation (SoundStateManager* self); + static void sound_state_manager_init (SoundStateManager* self) { @@ -63,6 +74,12 @@ sound_state_manager_init (SoundStateManager* self) priv->volume_states = NULL; priv->speaker_image = NULL; priv->blocked_animation_list = NULL; + priv->notification = NULL; + priv->settings_manager = NULL; + + priv->settings_manager = g_settings_new("com.canonical.indicators.sound"); + + sound_state_manager_notification_init (self); sound_state_manager_prepare_state_image_names (self); sound_state_manager_prepare_blocked_animation (self); @@ -89,9 +106,16 @@ sound_state_manager_dispose (GObject *object) g_hash_table_destroy (priv->volume_states); sound_state_manager_free_the_animation_list (self); + + if (priv->notification) { + notify_uninit(); + } + + g_object_unref(priv->settings_manager); + G_OBJECT_CLASS (sound_state_manager_parent_class)->dispose (object); } - + static void sound_state_manager_class_init (SoundStateManagerClass *klass) @@ -106,6 +130,77 @@ sound_state_manager_class_init (SoundStateManagerClass *klass) design_team_size = gtk_icon_size_register("design-team-size", 22, 22); } +static void +sound_state_manager_notification_init (SoundStateManager* self) +{ + SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self); + + if (!notify_init(PACKAGE_NAME)) + return; + + GList* caps = notify_get_server_caps(); + gboolean has_notify_osd = FALSE; + + if (caps) { + if (g_list_find_custom(caps, "x-canonical-private-synchronous", + (GCompareFunc) g_strcmp0)) { + has_notify_osd = TRUE; + } + g_list_foreach(caps, (GFunc) g_free, NULL); + g_list_free(caps); + } + + if (has_notify_osd) { + priv->notification = notify_notification_new(PACKAGE_NAME, NULL, NULL, NULL); + notify_notification_set_hint_string(priv->notification, + "x-canonical-private-synchronous", ""); + } +} + +void +sound_state_manager_attach_notification_to_volume_widget (SoundStateManager *self, + GtkWidget* volume_widget) +{ + SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self); + if (priv->notification) + notify_notification_attach_to_widget(priv->notification, volume_widget); +} + + +void +sound_state_manager_show_notification (SoundStateManager *self, + double value) +{ + SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self); + + if (priv->notification == NULL || + g_settings_get_boolean (priv->settings_manager, "show-notify-osd-on-scroll") == FALSE){ + return; + } + + char *icon; + const int notify_value = CLAMP((int)value, -1, 101); + SoundState state = sound_state_manager_get_current_state (self); + + if (state == ZERO_LEVEL) { + // Not available for all the themes + icon = "audio-volume-off"; + } else if (state == LOW_LEVEL) { + icon = "audio-volume-low"; + } else if (state == MEDIUM_LEVEL) { + icon = "audio-volume-medium"; + } else if (state == HIGH_LEVEL) { + icon = "audio-volume-high"; + } else { + icon = "audio-volume-muted"; + } + + notify_notification_update(priv->notification, PACKAGE_NAME, NULL, icon); + notify_notification_set_hint_int32(priv->notification, "value", notify_value); + notify_notification_show(priv->notification, NULL); +} + + /* Prepare states versus images names hash. */ @@ -113,7 +208,8 @@ static void sound_state_manager_prepare_state_image_names (SoundStateManager* self) { SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self); - priv->volume_states = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + priv->volume_states = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(MUTED), g_strdup("audio-volume-muted-panel")); g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(ZERO_LEVEL), g_strdup("audio-volume-low-zero-panel")); g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(LOW_LEVEL), g_strdup("audio-volume-low-panel")); @@ -281,8 +377,7 @@ sound_state_signal_cb ( GDBusProxy* proxy, blocked_id = g_timeout_add_seconds (4, sound_state_manager_start_animation, self); - indicator_image_helper_update (priv->speaker_image, image_name); - + indicator_image_helper_update (priv->speaker_image, image_name); } else{ indicator_image_helper_update (priv->speaker_image, image_name); @@ -291,7 +386,6 @@ sound_state_signal_cb ( GDBusProxy* proxy, else { g_warning ("sorry don't know what signal this is - %s", signal_name); } - } void diff --git a/src/sound-state-manager.h b/src/sound-state-manager.h index d73d5d9..0b919cb 100644 --- a/src/sound-state-manager.h +++ b/src/sound-state-manager.h @@ -58,8 +58,11 @@ void sound_state_manager_deal_with_disconnect (SoundStateManager* self); void sound_state_manager_get_state_cb (GObject *object, GAsyncResult *res, gpointer user_data); +void sound_state_manager_show_notification (SoundStateManager *self, + double value); - +void sound_state_manager_attach_notification_to_volume_widget (SoundStateManager *self, + GtkWidget* volume_widget); G_END_DECLS diff --git a/src/title-menu-item.c b/src/title-menu-item.c index a92af90..66c38e5 100644 --- a/src/title-menu-item.c +++ b/src/title-menu-item.c @@ -28,10 +28,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/menuitem.h> #include <libdbusmenu-glib/server.h> #include <common-defs.h> -#include <gio/gio.h> #include <stdlib.h> #include <string.h> #include <gee.h> +#include <gio/gio.h> #define TYPE_PLAYER_ITEM (player_item_get_type ()) @@ -130,31 +130,24 @@ enum { GType player_controller_get_type (void) G_GNUC_CONST; TitleMenuitem* title_menuitem_new (PlayerController* parent); TitleMenuitem* title_menuitem_construct (GType object_type, PlayerController* parent); -GAppInfo* player_controller_get_app_info (PlayerController* self); -const gchar* player_controller_get_icon_name (PlayerController* self); static void title_menuitem_real_handle_event (DbusmenuMenuitem* base, const gchar* name, GVariant* input_value, guint timestamp); PlayerController* player_item_get_owner (PlayerItem* self); GType mpris2_controller_get_type (void) G_GNUC_CONST; GType player_controller_state_get_type (void) G_GNUC_CONST; void player_controller_instantiate (PlayerController* self); void mpris2_controller_expose (Mpris2Controller* self); +void title_menuitem_alter_label (TitleMenuitem* self, const gchar* new_title); void title_menuitem_toggle_active_triangle (TitleMenuitem* self, gboolean update); GeeHashSet* title_menuitem_attributes_format (void); +static GObject * title_menuitem_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties); +GAppInfo* player_controller_get_app_info (PlayerController* self); +const gchar* player_controller_get_icon_name (PlayerController* self); TitleMenuitem* title_menuitem_construct (GType object_type, PlayerController* parent) { TitleMenuitem * self = NULL; - GAppInfo* _tmp0_ = NULL; - const gchar* _tmp1_ = NULL; - const gchar* _tmp2_ = NULL; g_return_val_if_fail (parent != NULL, NULL); self = (TitleMenuitem*) g_object_new (object_type, "item-type", DBUSMENU_TITLE_MENUITEM_TYPE, "owner", parent, NULL); - _tmp0_ = player_controller_get_app_info (parent); - _tmp1_ = g_app_info_get_name (_tmp0_); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_NAME, _tmp1_); - _tmp2_ = player_controller_get_icon_name (parent); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_ICON, _tmp2_); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_RUNNING, FALSE); return self; } @@ -187,6 +180,16 @@ static void title_menuitem_real_handle_event (DbusmenuMenuitem* base, const gcha } +void title_menuitem_alter_label (TitleMenuitem* self, const gchar* new_title) { + g_return_if_fail (self != NULL); + g_return_if_fail (new_title != NULL); + if (new_title == NULL) { + return; + } + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_NAME, new_title); +} + + void title_menuitem_toggle_active_triangle (TitleMenuitem* self, gboolean update) { g_return_if_fail (self != NULL); dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_RUNNING, update); @@ -207,9 +210,34 @@ GeeHashSet* title_menuitem_attributes_format (void) { } +static GObject * title_menuitem_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) { + GObject * obj; + GObjectClass * parent_class; + TitleMenuitem * self; + PlayerController* _tmp0_ = NULL; + GAppInfo* _tmp1_ = NULL; + const gchar* _tmp2_ = NULL; + PlayerController* _tmp3_ = NULL; + const gchar* _tmp4_ = NULL; + parent_class = G_OBJECT_CLASS (title_menuitem_parent_class); + obj = parent_class->constructor (type, n_construct_properties, construct_properties); + self = TITLE_MENUITEM (obj); + _tmp0_ = player_item_get_owner ((PlayerItem*) self); + _tmp1_ = player_controller_get_app_info (_tmp0_); + _tmp2_ = g_app_info_get_name (_tmp1_); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_NAME, _tmp2_); + _tmp3_ = player_item_get_owner ((PlayerItem*) self); + _tmp4_ = player_controller_get_icon_name (_tmp3_); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_ICON, _tmp4_); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_RUNNING, FALSE); + return obj; +} + + static void title_menuitem_class_init (TitleMenuitemClass * klass) { title_menuitem_parent_class = g_type_class_peek_parent (klass); DBUSMENU_MENUITEM_CLASS (klass)->handle_event = title_menuitem_real_handle_event; + G_OBJECT_CLASS (klass)->constructor = title_menuitem_constructor; } diff --git a/src/title-menu-item.vala b/src/title-menu-item.vala index 6ed24d8..ac93b89 100644 --- a/src/title-menu-item.vala +++ b/src/title-menu-item.vala @@ -26,8 +26,12 @@ public class TitleMenuitem : PlayerItem public TitleMenuitem(PlayerController parent) { Object(item_type: MENUITEM_TYPE, owner: parent); - this.property_set(MENUITEM_NAME, parent.app_info.get_name()); - this.property_set(MENUITEM_ICON, parent.icon_name); + } + + construct + { + this.property_set(MENUITEM_NAME, this.owner.app_info.get_name()); + this.property_set(MENUITEM_ICON, this.owner.icon_name); this.property_set_bool(MENUITEM_RUNNING, false); } @@ -42,6 +46,12 @@ public class TitleMenuitem : PlayerItem } } + public void alter_label (string new_title) + { + if (new_title == null) return; + this.property_set(MENUITEM_NAME, new_title); + } + public void toggle_active_triangle(bool update) { this.property_set_bool(MENUITEM_RUNNING, update); diff --git a/src/transport-menu-item.c b/src/transport-menu-item.c index 92d435b..05b5bb9 100644 --- a/src/transport-menu-item.c +++ b/src/transport-menu-item.c @@ -69,7 +69,6 @@ typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate; typedef struct _PlayerController PlayerController; typedef struct _PlayerControllerClass PlayerControllerClass; #define _g_variant_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_unref (var), NULL))) -#define _g_free0(var) (var = (g_free (var), NULL)) typedef struct _PlayerControllerPrivate PlayerControllerPrivate; #define TYPE_MPRIS2_CONTROLLER (mpris2_controller_get_type ()) @@ -187,8 +186,6 @@ TransportMenuitem* transport_menuitem_new (PlayerController* parent) { void transport_menuitem_change_play_state (TransportMenuitem* self, TransportMenuitemstate update) { gint temp; g_return_if_fail (self != NULL); - g_debug ("transport-menu-item.vala:45: UPDATING THE TRANSPORT DBUSMENUITEM PLAY " \ -"STATE WITH VALUE %i", (gint) update); temp = (gint) update; dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE, temp); } @@ -206,9 +203,7 @@ static void transport_menuitem_real_handle_event (DbusmenuMenuitem* base, const gboolean _tmp1_; gint32 _tmp4_; gint32 input; - gchar* _tmp5_ = NULL; - gchar* _tmp6_; - PlayerController* _tmp7_ = NULL; + PlayerController* _tmp5_ = NULL; self = (TransportMenuitem*) base; g_return_if_fail (name != NULL); g_return_if_fail (input_value != NULL); @@ -225,13 +220,8 @@ static void transport_menuitem_real_handle_event (DbusmenuMenuitem* base, const } _tmp4_ = g_variant_get_int32 (v); input = _tmp4_; - _tmp5_ = g_strdup_printf ("%i", input); - _tmp6_ = _tmp5_; - g_debug ("transport-menu-item.vala:63: transport menu item -> handle_event with " \ -"value %s", _tmp6_); - _g_free0 (_tmp6_); - _tmp7_ = player_item_get_owner ((PlayerItem*) self); - mpris2_controller_transport_update (_tmp7_->mpris_bridge, (TransportMenuitemaction) input); + _tmp5_ = player_item_get_owner ((PlayerItem*) self); + mpris2_controller_transport_update (_tmp5_->mpris_bridge, (TransportMenuitemaction) input); _g_variant_unref0 (v); } diff --git a/src/transport-menu-item.vala b/src/transport-menu-item.vala index b8f55b5..b0009d9 100644 --- a/src/transport-menu-item.vala +++ b/src/transport-menu-item.vala @@ -42,8 +42,8 @@ public class TransportMenuitem : PlayerItem public void change_play_state(state update) { - debug("UPDATING THE TRANSPORT DBUSMENUITEM PLAY STATE WITH VALUE %i", - (int)update); + //debug("UPDATING THE TRANSPORT DBUSMENUITEM PLAY STATE WITH VALUE %i", + // (int)update); int temp = (int)update; this.property_set_int(MENUITEM_PLAY_STATE, temp); } @@ -60,7 +60,7 @@ public class TransportMenuitem : PlayerItem } int32 input = v.get_int32(); - debug("transport menu item -> handle_event with value %s", input.to_string()); + //debug("transport menu item -> handle_event with value %s", input.to_string()); //debug("transport owner name = %s", this.owner.app_info.get_name()); this.owner.mpris_bridge.transport_update((action)input); } |