diff options
author | Ken VanDine <ken.vandine@canonical.com> | 2010-06-24 14:50:20 -0400 |
---|---|---|
committer | Ken VanDine <ken.vandine@canonical.com> | 2010-06-24 14:50:20 -0400 |
commit | 63cc1d29b748a41f5e779aab6a38b7697421b80a (patch) | |
tree | da17ffa7b04f31af69f5b02c7c8373a38c58abfb /src | |
parent | 1e65c770811a96d79b302dfd0ddee67a4c7c07f5 (diff) | |
parent | 288985d7c0a4dcdde22335a31d9eae7f7d5ec215 (diff) | |
download | ayatana-indicator-sound-63cc1d29b748a41f5e779aab6a38b7697421b80a.tar.gz ayatana-indicator-sound-63cc1d29b748a41f5e779aab6a38b7697421b80a.tar.bz2 ayatana-indicator-sound-63cc1d29b748a41f5e779aab6a38b7697421b80a.zip |
* New upstream release.
- MPRIS transport status updates reflecting in UI
If externally a registered player transport is changed (play/stop)
the menu should reflect that
- The first time a player registers its desktop file path should be
stored ~.cache/indicators/sound/familiar-players-db.keyfile (provided
the application indicator has a desktop file set.
- Album art dynamically updated
- Album title dynamically updated
- Track title dynamically updated
- Artist name dynamically updated
- Play/pause transport control should be working from the menu
Diffstat (limited to 'src')
32 files changed, 2935 insertions, 1494 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5a42dc6..b33107d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,20 +56,23 @@ music_bridge_VALASOURCES = \ metadata-menu-item.vala \ player-controller.vala \ mpris-controller-v2.vala \ - mpris-controller.vala + mpris-controller.vala \ + player-item.vala \ + familiar-players-db.vala music_bridge_VALAFLAGS = \ --ccode \ -H music-player-bridge.h -d . \ - --library music-bridge \ + --vapidir=$(top_srcdir)/vapi/ \ --vapidir=./ \ --thread \ --pkg gee-1.0 \ --pkg Indicate-0.2 \ --pkg Dbusmenu-Glib-0.2 \ - --pkg dbus-glib-1 - - $(MAINTAINER_VALAFLAGS) + --pkg common-defs \ + --pkg dbus-glib-1 \ + --pkg gio-unix-2.0 + $(MAINTAINER_VALAFLAGS) music_bridge_APIFILES = \ music-player-bridge.h @@ -115,7 +118,6 @@ BUILT_SOURCES = \ music_bridge_vala.stamp \ sound-service-client.h \ sound-service-server.h \ - music-bridge.vapi \ $(music_bridge_APIFILES) \ $(music_bridge_VALASOURCES:.vala=.c) diff --git a/src/Makefile.in b/src/Makefile.in index c78ee32..3af9677 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -39,7 +39,10 @@ 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)/configure.ac +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__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -89,7 +92,9 @@ am__objects_1 = indicator_sound_service-music-player-bridge.$(OBJEXT) \ indicator_sound_service-metadata-menu-item.$(OBJEXT) \ indicator_sound_service-player-controller.$(OBJEXT) \ indicator_sound_service-mpris-controller-v2.$(OBJEXT) \ - indicator_sound_service-mpris-controller.$(OBJEXT) + indicator_sound_service-mpris-controller.$(OBJEXT) \ + indicator_sound_service-player-item.$(OBJEXT) \ + indicator_sound_service-familiar-players-db.$(OBJEXT) am_indicator_sound_service_OBJECTS = \ indicator_sound_service-sound-service.$(OBJEXT) \ indicator_sound_service-dbus-menu-manager.$(OBJEXT) \ @@ -322,18 +327,22 @@ music_bridge_VALASOURCES = \ metadata-menu-item.vala \ player-controller.vala \ mpris-controller-v2.vala \ - mpris-controller.vala + mpris-controller.vala \ + player-item.vala \ + familiar-players-db.vala music_bridge_VALAFLAGS = \ --ccode \ -H music-player-bridge.h -d . \ - --library music-bridge \ + --vapidir=$(top_srcdir)/vapi/ \ --vapidir=./ \ --thread \ --pkg gee-1.0 \ --pkg Indicate-0.2 \ --pkg Dbusmenu-Glib-0.2 \ - --pkg dbus-glib-1 + --pkg common-defs \ + --pkg dbus-glib-1 \ + --pkg gio-unix-2.0 music_bridge_APIFILES = \ music-player-bridge.h @@ -377,7 +386,6 @@ BUILT_SOURCES = \ music_bridge_vala.stamp \ sound-service-client.h \ sound-service-server.h \ - music-bridge.vapi \ $(music_bridge_APIFILES) \ $(music_bridge_VALASOURCES:.vala=.c) @@ -506,11 +514,13 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-dbus-menu-manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-familiar-players-db.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-metadata-menu-item.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-mpris-controller-v2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-mpris-controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-music-player-bridge.Po@am__quote@ @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-pulse-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@ @@ -744,6 +754,38 @@ indicator_sound_service-mpris-controller.obj: mpris-controller.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-mpris-controller.obj `if test -f 'mpris-controller.c'; then $(CYGPATH_W) 'mpris-controller.c'; else $(CYGPATH_W) '$(srcdir)/mpris-controller.c'; fi` +indicator_sound_service-player-item.o: player-item.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-player-item.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-player-item.Tpo -c -o indicator_sound_service-player-item.o `test -f 'player-item.c' || echo '$(srcdir)/'`player-item.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-player-item.Tpo $(DEPDIR)/indicator_sound_service-player-item.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='player-item.c' object='indicator_sound_service-player-item.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-player-item.o `test -f 'player-item.c' || echo '$(srcdir)/'`player-item.c + +indicator_sound_service-player-item.obj: player-item.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-player-item.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-player-item.Tpo -c -o indicator_sound_service-player-item.obj `if test -f 'player-item.c'; then $(CYGPATH_W) 'player-item.c'; else $(CYGPATH_W) '$(srcdir)/player-item.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-player-item.Tpo $(DEPDIR)/indicator_sound_service-player-item.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='player-item.c' object='indicator_sound_service-player-item.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-player-item.obj `if test -f 'player-item.c'; then $(CYGPATH_W) 'player-item.c'; else $(CYGPATH_W) '$(srcdir)/player-item.c'; fi` + +indicator_sound_service-familiar-players-db.o: familiar-players-db.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-familiar-players-db.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-familiar-players-db.Tpo -c -o indicator_sound_service-familiar-players-db.o `test -f 'familiar-players-db.c' || echo '$(srcdir)/'`familiar-players-db.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-familiar-players-db.Tpo $(DEPDIR)/indicator_sound_service-familiar-players-db.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='familiar-players-db.c' object='indicator_sound_service-familiar-players-db.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-familiar-players-db.o `test -f 'familiar-players-db.c' || echo '$(srcdir)/'`familiar-players-db.c + +indicator_sound_service-familiar-players-db.obj: familiar-players-db.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-familiar-players-db.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-familiar-players-db.Tpo -c -o indicator_sound_service-familiar-players-db.obj `if test -f 'familiar-players-db.c'; then $(CYGPATH_W) 'familiar-players-db.c'; else $(CYGPATH_W) '$(srcdir)/familiar-players-db.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-familiar-players-db.Tpo $(DEPDIR)/indicator_sound_service-familiar-players-db.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='familiar-players-db.c' object='indicator_sound_service-familiar-players-db.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-familiar-players-db.obj `if test -f 'familiar-players-db.c'; then $(CYGPATH_W) 'familiar-players-db.c'; else $(CYGPATH_W) '$(srcdir)/familiar-players-db.c'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -983,8 +1025,7 @@ sound-service-server.h: $(srcdir)/sound-service.xml --mode=glib-server \ --output=sound-service-server.h \ $(srcdir)/sound-service.xml - - $(MAINTAINER_VALAFLAGS) + $(MAINTAINER_VALAFLAGS) music_bridge_vala.stamp $(music_bridge_APIFILES): $(music_bridge_VALASOURCES) $(AM_V_GEN) $(VALAC) $(music_bridge_VALAFLAGS) $^ diff --git a/src/common-defs.h b/src/common-defs.h index 014d864..dca21cc 100644 --- a/src/common-defs.h +++ b/src/common-defs.h @@ -27,10 +27,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>. /* DBUS Custom Items */ #define DBUSMENU_SLIDER_MENUITEM_TYPE "x-canonical-ido-slider-item" #define DBUSMENU_TRANSPORT_MENUITEM_TYPE "x-canonical-transport-bar" -#define DBUSMENU_TRANSPORT_MENUITEM_STATE "x-canonical-transport-state" +#define DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE "x-canonical-transport-play-state" #define DBUSMENU_METADATA_MENUITEM_TYPE "x-canonical-metadata-menu-item" #define DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST "x-canonical-metadata-text-artist" -#define DBUSMENU_METADATA_MENUITEM_TEXT_PIECE "x-canonical-metadata-text-piece" -#define DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER "x-canonical-metadata-text-container" -#define DBUSMENU_METADATA_MENUITEM_IMAGE_PATH "x-canonical-metadata-image" +#define DBUSMENU_METADATA_MENUITEM_TEXT_TITLE "x-canonical-metadata-text-title" +#define DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM "x-canonical-metadata-text-album" +#define DBUSMENU_METADATA_MENUITEM_ARTURL "x-canonical-metadata-arturl" diff --git a/src/dbus-menu-manager.c b/src/dbus-menu-manager.c index 9d62adb..d19bfbb 100644 --- a/src/dbus-menu-manager.c +++ b/src/dbus-menu-manager.c @@ -5,16 +5,16 @@ 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 +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 +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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -27,8 +27,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/server.h> #include <libdbusmenu-glib/client.h> -#include "dbus-menu-manager.h" -#include "sound-service-dbus.h" +#include "dbus-menu-manager.h" +#include "sound-service-dbus.h" #include "pulse-manager.h" #include "slider-menu-item.h" @@ -53,7 +53,7 @@ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service static void refresh_menu(); /*-------------------------------------------------------------------------*/ -// Public Methods +// Public Methods /*-------------------------------------------------------------------------*/ /** @@ -61,17 +61,17 @@ setup: **/ DbusmenuMenuitem* dbus_menu_manager_setup() { - root_menuitem = dbusmenu_menuitem_new(); - g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem)); - - g_idle_add(idle_routine, root_menuitem); + root_menuitem = dbusmenu_menuitem_new(); + g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem)); - dbus_interface = g_object_new(SOUND_SERVICE_DBUS_TYPE, NULL); + g_idle_add(idle_routine, root_menuitem); - DbusmenuServer *server = dbusmenu_server_new(INDICATOR_SOUND_DBUS_OBJECT); - dbusmenu_server_set_root(server, root_menuitem); - establish_pulse_activities(dbus_interface); - return root_menuitem; + dbus_interface = g_object_new(SOUND_SERVICE_DBUS_TYPE, NULL); + + DbusmenuServer *server = dbusmenu_server_new(INDICATOR_SOUND_DBUS_OBJECT); + dbusmenu_server_set_root(server, root_menuitem); + establish_pulse_activities(dbus_interface); + return root_menuitem; } /** @@ -79,7 +79,7 @@ teardown: **/ void dbus_menu_manager_teardown() { - //TODO tidy up dbus_interface and items! + //TODO tidy up dbus_interface and items! } /** @@ -87,25 +87,24 @@ update_pa_state: **/ void dbus_menu_manager_update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_muted, gdouble percent) { - b_sink_available = sink_available; - b_all_muted = sink_muted; - b_pulse_ready = pa_state; - volume_percent = percent; - g_debug("update pa state with state %i, availability of %i, mute value of %i and a volume percent is %f", pa_state, sink_available, sink_muted, volume_percent); - // Only rebuild the menu on start up... - if(b_startup == TRUE){ - rebuild_sound_menu(root_menuitem, dbus_interface); - b_startup = FALSE; - } - else{ - refresh_menu(); - } - // Emit the signals after the menus are setup/torn down - // preserve ordering ! - sound_service_dbus_update_sink_availability(dbus_interface, sink_available); - sound_service_dbus_update_sink_volume(dbus_interface, percent); - sound_service_dbus_update_sink_mute(dbus_interface, sink_muted); - dbus_menu_manager_update_mute_ui(b_all_muted); + b_sink_available = sink_available; + b_all_muted = sink_muted; + b_pulse_ready = pa_state; + volume_percent = percent; + g_debug("update pa state with state %i, availability of %i, mute value of %i and a volume percent is %f", pa_state, sink_available, sink_muted, volume_percent); + // Only rebuild the menu on start up... + if (b_startup == TRUE) { + rebuild_sound_menu(root_menuitem, dbus_interface); + b_startup = FALSE; + } else { + refresh_menu(); + } + // Emit the signals after the menus are setup/torn down + // preserve ordering ! + sound_service_dbus_update_sink_availability(dbus_interface, sink_available); + sound_service_dbus_update_sink_volume(dbus_interface, percent); + sound_service_dbus_update_sink_mute(dbus_interface, sink_muted); + dbus_menu_manager_update_mute_ui(b_all_muted); } /** @@ -114,46 +113,44 @@ update_mute_ui: **/ void dbus_menu_manager_update_mute_ui(gboolean incoming_mute_value) { - b_all_muted = incoming_mute_value; - dbusmenu_menuitem_property_set(mute_all_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - b_all_muted == FALSE ? _("Mute All") : _("Unmute")); + b_all_muted = incoming_mute_value; + dbusmenu_menuitem_property_set(mute_all_menuitem, + DBUSMENU_MENUITEM_PROP_LABEL, + b_all_muted == FALSE ? _("Mute All") : _("Unmute")); } /*-------------------------------------------------------------------------*/ -// Private Methods +// Private Methods /*-------------------------------------------------------------------------*/ static void refresh_menu() { - g_debug("in the refresh menu method"); - if(b_sink_available == FALSE || b_pulse_ready == FALSE) - { - - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), - DBUSMENU_MENUITEM_PROP_ENABLED, - FALSE); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), - DBUSMENU_MENUITEM_PROP_VISIBLE, - FALSE); - dbusmenu_menuitem_property_set_bool(mute_all_menuitem, - DBUSMENU_MENUITEM_PROP_ENABLED, - FALSE); - - } - else if(b_sink_available == TRUE && b_pulse_ready == TRUE){ - - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), - DBUSMENU_MENUITEM_PROP_ENABLED, - TRUE); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), - DBUSMENU_MENUITEM_PROP_VISIBLE, - TRUE); - dbusmenu_menuitem_property_set_bool(mute_all_menuitem, - DBUSMENU_MENUITEM_PROP_ENABLED, - TRUE); - } + g_debug("in the refresh menu method"); + if (b_sink_available == FALSE || b_pulse_ready == FALSE) { + + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_ENABLED, + FALSE); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_VISIBLE, + FALSE); + dbusmenu_menuitem_property_set_bool(mute_all_menuitem, + DBUSMENU_MENUITEM_PROP_ENABLED, + FALSE); + + } else if (b_sink_available == TRUE && b_pulse_ready == TRUE) { + + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_ENABLED, + TRUE); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_VISIBLE, + TRUE); + dbusmenu_menuitem_property_set_bool(mute_all_menuitem, + DBUSMENU_MENUITEM_PROP_ENABLED, + TRUE); + } } @@ -163,23 +160,22 @@ Something for glip mainloop to do when idle **/ static gboolean idle_routine (gpointer data) { - return FALSE; + return FALSE; } - + /** show_sound_settings_dialog: Bring up the gnome volume preferences dialog **/ -static void show_sound_settings_dialog (DbusmenuMenuitem *mi, gpointer user_data) +static void show_sound_settings_dialog (DbusmenuMenuitem *mi, gpointer user_data) { - GError * error = NULL; - if (!g_spawn_command_line_async("gnome-volume-control", &error)) - { - g_warning("Unable to show dialog: %s", error->message); - g_error_free(error); - } + GError * error = NULL; + if (!g_spawn_command_line_async("gnome-volume-control", &error)) { + g_warning("Unable to show dialog: %s", error->message); + g_error_free(error); + } } /** @@ -188,35 +184,35 @@ Build the DBus menu items, mute/unmute, slider, separator and sound preferences **/ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service) { - // Mute button - mute_all_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, b_all_muted == FALSE ? _("Mute All") : _("Unmute")); - g_signal_connect(G_OBJECT(mute_all_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(set_global_mute_from_ui), NULL); - dbusmenu_menuitem_property_set_bool(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, b_sink_available); - - // Slider - volume_slider_menuitem = slider_menu_item_new(b_sink_available, volume_percent); - dbusmenu_menuitem_child_append(root, mute_all_menuitem); - dbusmenu_menuitem_child_append(root, DBUSMENU_MENUITEM(volume_slider_menuitem)); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), - DBUSMENU_MENUITEM_PROP_ENABLED, - b_sink_available && !b_all_muted); - g_debug("!!!!!!**in the rebuild sound menu - slider active = %i", b_sink_available && !b_all_muted); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), - DBUSMENU_MENUITEM_PROP_VISIBLE, - b_sink_available); - // Separator - DbusmenuMenuitem *separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append(root, separator); - - // Sound preferences dialog - DbusmenuMenuitem *settings_mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(settings_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sound Preferences...")); + // Mute button + mute_all_menuitem = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, b_all_muted == FALSE ? _("Mute All") : _("Unmute")); + g_signal_connect(G_OBJECT(mute_all_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(set_global_mute_from_ui), NULL); + dbusmenu_menuitem_property_set_bool(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, b_sink_available); + + // Slider + volume_slider_menuitem = slider_menu_item_new(b_sink_available, volume_percent); + dbusmenu_menuitem_child_append(root, mute_all_menuitem); + dbusmenu_menuitem_child_append(root, DBUSMENU_MENUITEM(volume_slider_menuitem)); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_ENABLED, + b_sink_available && !b_all_muted); + g_debug("!!!!!!**in the rebuild sound menu - slider active = %i", b_sink_available && !b_all_muted); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(volume_slider_menuitem), + DBUSMENU_MENUITEM_PROP_VISIBLE, + b_sink_available); + // Separator + DbusmenuMenuitem *separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + dbusmenu_menuitem_child_append(root, separator); + + // Sound preferences dialog + DbusmenuMenuitem *settings_mi = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(settings_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sound Preferences...")); //_("Sound Preferences...")); - dbusmenu_menuitem_child_append(root, settings_mi); - g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_sound_settings_dialog), NULL); + dbusmenu_menuitem_child_append(root, settings_mi); + g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(show_sound_settings_dialog), NULL); } /** @@ -225,11 +221,11 @@ Callback for the dbusmenuitem button **/ static void set_global_mute_from_ui() { - b_all_muted = !b_all_muted; - toggle_global_mute(b_all_muted); - dbusmenu_menuitem_property_set(mute_all_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - b_all_muted == FALSE ? _("Mute All") : _("Unmute")); + b_all_muted = !b_all_muted; + toggle_global_mute(b_all_muted); + dbusmenu_menuitem_property_set(mute_all_menuitem, + DBUSMENU_MENUITEM_PROP_LABEL, + b_all_muted == FALSE ? _("Mute All") : _("Unmute")); } diff --git a/src/dbus-menu-manager.h b/src/dbus-menu-manager.h index a5286ca..926e292 100644 --- a/src/dbus-menu-manager.h +++ b/src/dbus-menu-manager.h @@ -10,16 +10,16 @@ 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 +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 +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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ diff --git a/src/familiar-players-db.c b/src/familiar-players-db.c new file mode 100644 index 0000000..152571d --- /dev/null +++ b/src/familiar-players-db.c @@ -0,0 +1,500 @@ +/* familiar-players-db.c generated by valac, the Vala compiler + * generated from familiar-players-db.vala, do not modify */ + +/* +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 <glib.h> +#include <glib-object.h> +#include <gee.h> +#include <stdlib.h> +#include <string.h> +#include <glib/gstdio.h> + + +#define TYPE_FAMILIAR_PLAYERS_DB (familiar_players_db_get_type ()) +#define FAMILIAR_PLAYERS_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDB)) +#define FAMILIAR_PLAYERS_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDBClass)) +#define IS_FAMILIAR_PLAYERS_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_FAMILIAR_PLAYERS_DB)) +#define IS_FAMILIAR_PLAYERS_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_FAMILIAR_PLAYERS_DB)) +#define FAMILIAR_PLAYERS_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDBClass)) + +typedef struct _FamiliarPlayersDB FamiliarPlayersDB; +typedef struct _FamiliarPlayersDBClass FamiliarPlayersDBClass; +typedef struct _FamiliarPlayersDBPrivate FamiliarPlayersDBPrivate; +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_key_file_free0(var) ((var == NULL) ? NULL : (var = (g_key_file_free (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) + +struct _FamiliarPlayersDB { + GObject parent_instance; + FamiliarPlayersDBPrivate * priv; +}; + +struct _FamiliarPlayersDBClass { + GObjectClass parent_class; +}; + +struct _FamiliarPlayersDBPrivate { + GeeHashMap* players_DB; + char* file_name; + char* dir_name; + GKeyFile* key_file; + guint write_id; +}; + + +static gpointer familiar_players_db_parent_class = NULL; + +GType familiar_players_db_get_type (void); +#define FAMILIAR_PLAYERS_DB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDBPrivate)) +enum { + FAMILIAR_PLAYERS_DB_DUMMY_PROPERTY +}; +#define FAMILIAR_PLAYERS_DB_GROUP_NAME "Seen Database" +#define FAMILIAR_PLAYERS_DB_KEY_NAME "DesktopFiles" +static gboolean familiar_players_db_create_key_file (FamiliarPlayersDB* self); +static gboolean familiar_players_db_check_for_keys (FamiliarPlayersDB* self); +static gboolean familiar_players_db_load_data_from_key_file (FamiliarPlayersDB* self); +FamiliarPlayersDB* familiar_players_db_new (void); +FamiliarPlayersDB* familiar_players_db_construct (GType object_type); +static void _vala_array_add1 (char*** array, int* length, int* size, char* value); +static gboolean familiar_players_db_write_db (FamiliarPlayersDB* self); +gboolean familiar_players_db_already_familiar (FamiliarPlayersDB* self, const char* desktop); +static gboolean _familiar_players_db_write_db_gsource_func (gpointer self); +void familiar_players_db_insert (FamiliarPlayersDB* self, const char* desktop); +GeeSet* familiar_players_db_records (FamiliarPlayersDB* self); +static void familiar_players_db_finalize (GObject* obj); +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); + + + +FamiliarPlayersDB* familiar_players_db_construct (GType object_type) { + FamiliarPlayersDB * self; + GeeHashMap* _tmp0_; + char* _tmp1_; + char* _tmp2_; + gboolean _tmp3_ = FALSE; + gboolean _tmp4_ = FALSE; + self = (FamiliarPlayersDB*) g_object_new (object_type, NULL); + self->priv->write_id = (guint) 0; + self->priv->players_DB = (_tmp0_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, G_TYPE_BOOLEAN, NULL, NULL, NULL, NULL, NULL), _g_object_unref0 (self->priv->players_DB), _tmp0_); + self->priv->dir_name = (_tmp1_ = g_build_filename (g_get_user_cache_dir (), "indicators", "sound", NULL), _g_free0 (self->priv->dir_name), _tmp1_); + self->priv->file_name = (_tmp2_ = g_build_filename (self->priv->dir_name, "familiar-players-db.keyfile", NULL), _g_free0 (self->priv->file_name), _tmp2_); + if (familiar_players_db_create_key_file (self)) { + _tmp4_ = familiar_players_db_check_for_keys (self); + } else { + _tmp4_ = FALSE; + } + if (_tmp4_) { + _tmp3_ = familiar_players_db_load_data_from_key_file (self); + } else { + _tmp3_ = FALSE; + } + if (_tmp3_) { + g_debug ("familiar-players-db.vala:45: keyfiles in place and ready for action"); + } else { + GKeyFile* _tmp5_; + self->priv->key_file = (_tmp5_ = NULL, _g_key_file_free0 (self->priv->key_file), _tmp5_); + g_warning ("familiar-players-db.vala:49: FamiliarPlayersDB:: problems loading key " \ +"file - can't go any further"); + } + return self; +} + + +FamiliarPlayersDB* familiar_players_db_new (void) { + return familiar_players_db_construct (TYPE_FAMILIAR_PLAYERS_DB); +} + + +static gboolean familiar_players_db_create_key_file (FamiliarPlayersDB* self) { + gboolean result = FALSE; + GError * _inner_error_; + g_return_val_if_fail (self != NULL, FALSE); + _inner_error_ = NULL; + if (g_file_test (self->priv->file_name, G_FILE_TEST_EXISTS)) { + GKeyFile* _tmp0_; + self->priv->key_file = (_tmp0_ = g_key_file_new (), _g_key_file_free0 (self->priv->key_file), _tmp0_); + { + gboolean _tmp1_; + _tmp1_ = g_key_file_load_from_file (self->priv->key_file, self->priv->file_name, G_KEY_FILE_NONE, &_inner_error_); + if (_inner_error_ != NULL) { + if (_inner_error_->domain == G_FILE_ERROR) { + goto __catch2_g_file_error; + } + goto __finally2; + } + if (_tmp1_ == TRUE) { + result = TRUE; + return result; + } + } + goto __finally2; + __catch2_g_file_error: + { + GError * e; + e = _inner_error_; + _inner_error_ = NULL; + { + g_warning ("familiar-players-db.vala:62: FamiliarPlayersDB - error trying to load " \ +"KeyFile"); + _g_error_free0 (e); + } + } + __finally2: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } + } + result = FALSE; + return result; +} + + +static gboolean familiar_players_db_check_for_keys (FamiliarPlayersDB* self) { + gboolean result = FALSE; + GError * _inner_error_; + g_return_val_if_fail (self != NULL, FALSE); + _inner_error_ = NULL; + { + gboolean _tmp0_; + _tmp0_ = g_key_file_has_key (self->priv->key_file, FAMILIAR_PLAYERS_DB_GROUP_NAME, FAMILIAR_PLAYERS_DB_KEY_NAME, &_inner_error_); + if (_inner_error_ != NULL) { + if (_inner_error_->domain == G_KEY_FILE_ERROR) { + goto __catch3_g_key_file_error; + } + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } + if (_tmp0_ == TRUE) { + result = TRUE; + return result; + } + } + goto __finally3; + __catch3_g_key_file_error: + { + GError * e; + e = _inner_error_; + _inner_error_ = NULL; + { + result = FALSE; + _g_error_free0 (e); + return result; + } + } + __finally3: + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } + g_warning ("familiar-players-db.vala:77: Seen DB '%s' does not have key '%s' in gr" \ +"oup '%s'", self->priv->file_name, FAMILIAR_PLAYERS_DB_KEY_NAME, FAMILIAR_PLAYERS_DB_GROUP_NAME); + result = FALSE; + return result; +} + + +static gboolean familiar_players_db_load_data_from_key_file (FamiliarPlayersDB* self) { + gboolean result = FALSE; + GError * _inner_error_; + g_return_val_if_fail (self != NULL, FALSE); + _inner_error_ = NULL; + { + char** _tmp1_; + gint _desktops_size_; + gint desktops_length1; + gsize _tmp0_; + char** desktops; + desktops = (_tmp1_ = g_key_file_get_string_list (self->priv->key_file, FAMILIAR_PLAYERS_DB_GROUP_NAME, FAMILIAR_PLAYERS_DB_KEY_NAME, &_tmp0_, &_inner_error_), desktops_length1 = _tmp0_, _desktops_size_ = desktops_length1, _tmp1_); + if (_inner_error_ != NULL) { + if (_inner_error_->domain == G_FILE_ERROR) { + goto __catch4_g_file_error; + } + goto __finally4; + } + { + char** s_collection; + int s_collection_length1; + int s_it; + s_collection = desktops; + s_collection_length1 = desktops_length1; + for (s_it = 0; s_it < desktops_length1; s_it = s_it + 1) { + char* s; + s = g_strdup (s_collection[s_it]); + { + gee_abstract_map_set ((GeeAbstractMap*) self->priv->players_DB, s, GINT_TO_POINTER (TRUE)); + _g_free0 (s); + } + } + } + result = TRUE; + desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); + return result; + } + goto __finally4; + __catch4_g_file_error: + { + GError * _error_; + _error_ = _inner_error_; + _inner_error_ = NULL; + { + g_warning ("familiar-players-db.vala:91: Error loading the Desktop string list"); + result = FALSE; + _g_error_free0 (_error_); + return result; + } + } + __finally4: + { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } +} + + +static void _vala_array_add1 (char*** array, int* length, int* size, char* value) { + if ((*length) == (*size)) { + *size = (*size) ? (2 * (*size)) : 4; + *array = g_renew (char*, *array, (*size) + 1); + } + (*array)[(*length)++] = value; + (*array)[*length] = NULL; +} + + +static gboolean familiar_players_db_write_db (FamiliarPlayersDB* self) { + gboolean result = FALSE; + GError * _inner_error_; + GKeyFile* keyfile; + char** _tmp1_; + gint _desktops_size_; + gint desktops_length1; + char** _tmp0_ = NULL; + char** desktops; + gsize data_length = 0UL; + char* data; + g_return_val_if_fail (self != NULL, FALSE); + _inner_error_ = NULL; + keyfile = g_key_file_new (); + desktops = (_tmp1_ = (_tmp0_ = g_new0 (char*, 0 + 1), _tmp0_), desktops_length1 = 0, _desktops_size_ = desktops_length1, _tmp1_); + { + GeeSet* _tmp2_; + GeeIterator* _tmp3_; + GeeIterator* _key_it; + _key_it = (_tmp3_ = gee_iterable_iterator ((GeeIterable*) (_tmp2_ = gee_map_get_keys ((GeeMap*) self->priv->players_DB))), _g_object_unref0 (_tmp2_), _tmp3_); + while (TRUE) { + char* key; + if (!gee_iterator_next (_key_it)) { + break; + } + key = (char*) gee_iterator_get (_key_it); + _vala_array_add1 (&desktops, &desktops_length1, &_desktops_size_, g_strdup (key)); + _g_free0 (key); + } + _g_object_unref0 (_key_it); + } + g_key_file_set_string_list (keyfile, FAMILIAR_PLAYERS_DB_GROUP_NAME, FAMILIAR_PLAYERS_DB_KEY_NAME, (const gchar* const*) desktops, desktops_length1); + data = NULL; + { + char* _tmp4_; + data = (_tmp4_ = g_key_file_to_data (keyfile, &data_length, NULL), _g_free0 (data), _tmp4_); + } + goto __finally5; + __catch5_g_error: + { + GError * e; + e = _inner_error_; + _inner_error_ = NULL; + { + g_warning ("familiar-players-db.vala:112: Problems dumping keyfile to a string"); + result = FALSE; + _g_error_free0 (e); + _g_key_file_free0 (keyfile); + desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (data); + return result; + } + } + __finally5: + if (_inner_error_ != NULL) { + _g_key_file_free0 (keyfile); + desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (data); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } + if (g_mkdir_with_parents (self->priv->dir_name, 0700) != 0) { + g_warning ("familiar-players-db.vala:117: Unable to make directory: %s", self->priv->dir_name); + result = FALSE; + _g_key_file_free0 (keyfile); + desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (data); + return result; + } + { + gboolean _tmp5_; + _tmp5_ = g_file_set_contents (self->priv->file_name, data, (gssize) data_length, &_inner_error_); + if (_inner_error_ != NULL) { + if (_inner_error_->domain == G_FILE_ERROR) { + goto __catch6_g_file_error; + } + _g_key_file_free0 (keyfile); + desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (data); + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } + if (_tmp5_ == FALSE) { + g_warning ("familiar-players-db.vala:123: Unable to write out file '%s'", self->priv->file_name); + } + } + goto __finally6; + __catch6_g_file_error: + { + GError * err; + err = _inner_error_; + _inner_error_ = NULL; + { + g_warning ("familiar-players-db.vala:127: Unable to write out file '%s'", self->priv->file_name); + _g_error_free0 (err); + } + } + __finally6: + if (_inner_error_ != NULL) { + _g_key_file_free0 (keyfile); + desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (data); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; + } + result = TRUE; + _g_key_file_free0 (keyfile); + desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (data); + return result; +} + + +static gboolean _familiar_players_db_write_db_gsource_func (gpointer self) { + gboolean result; + result = familiar_players_db_write_db (self); + return result; +} + + +void familiar_players_db_insert (FamiliarPlayersDB* self, const char* desktop) { + g_return_if_fail (self != NULL); + g_return_if_fail (desktop != NULL); + if (familiar_players_db_already_familiar (self, desktop) == FALSE) { + char* _tmp0_; + if (self->priv->write_id != 0) { + g_source_remove (self->priv->write_id); + self->priv->write_id = (guint) 0; + } + self->priv->write_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, (guint) 60, _familiar_players_db_write_db_gsource_func, g_object_ref (self), g_object_unref); + gee_abstract_map_set ((GeeAbstractMap*) self->priv->players_DB, _tmp0_ = g_strdup (desktop), GINT_TO_POINTER (TRUE)); + _g_free0 (_tmp0_); + } +} + + +gboolean familiar_players_db_already_familiar (FamiliarPlayersDB* self, const char* desktop) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (desktop != NULL, FALSE); + result = GPOINTER_TO_INT (gee_abstract_map_get ((GeeAbstractMap*) self->priv->players_DB, desktop)); + return result; +} + + +GeeSet* familiar_players_db_records (FamiliarPlayersDB* self) { + GeeSet* result = NULL; + g_return_val_if_fail (self != NULL, NULL); + result = gee_map_get_keys ((GeeMap*) self->priv->players_DB); + return result; +} + + +static void familiar_players_db_class_init (FamiliarPlayersDBClass * klass) { + familiar_players_db_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (klass, sizeof (FamiliarPlayersDBPrivate)); + G_OBJECT_CLASS (klass)->finalize = familiar_players_db_finalize; +} + + +static void familiar_players_db_instance_init (FamiliarPlayersDB * self) { + self->priv = FAMILIAR_PLAYERS_DB_GET_PRIVATE (self); +} + + +static void familiar_players_db_finalize (GObject* obj) { + FamiliarPlayersDB * self; + self = FAMILIAR_PLAYERS_DB (obj); + _g_object_unref0 (self->priv->players_DB); + _g_free0 (self->priv->file_name); + _g_free0 (self->priv->dir_name); + _g_key_file_free0 (self->priv->key_file); + G_OBJECT_CLASS (familiar_players_db_parent_class)->finalize (obj); +} + + +GType familiar_players_db_get_type (void) { + static volatile gsize familiar_players_db_type_id__volatile = 0; + if (g_once_init_enter (&familiar_players_db_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (FamiliarPlayersDBClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) familiar_players_db_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FamiliarPlayersDB), 0, (GInstanceInitFunc) familiar_players_db_instance_init, NULL }; + GType familiar_players_db_type_id; + familiar_players_db_type_id = g_type_register_static (G_TYPE_OBJECT, "FamiliarPlayersDB", &g_define_type_info, 0); + g_once_init_leave (&familiar_players_db_type_id__volatile, familiar_players_db_type_id); + } + return familiar_players_db_type_id__volatile; +} + + +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} + + +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); +} + + + + diff --git a/src/familiar-players-db.vala b/src/familiar-players-db.vala new file mode 100644 index 0000000..88bc01f --- /dev/null +++ b/src/familiar-players-db.vala @@ -0,0 +1,154 @@ +/* +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/>. +*/ + +using Gee; +using GLib.Path; +using GLib.DirUtils; +using GLib.FileUtils; +using GLib.Timeout; +using GLib.Environment; + +// TODO: more refactoring needed here +public class FamiliarPlayersDB : GLib.Object +{ + private const string GROUP_NAME = "Seen Database"; + private const string KEY_NAME = "DesktopFiles"; + private HashMap<string, bool> players_DB; + private string file_name; + private string dir_name; + private KeyFile key_file; + private uint write_id; + + public FamiliarPlayersDB() + { + this.write_id = 0; + this.players_DB = new HashMap<string, bool>(); + this.dir_name = build_filename(get_user_cache_dir(), "indicators", "sound"); + this.file_name = build_filename(this.dir_name, "familiar-players-db.keyfile"); + if(create_key_file() && check_for_keys() && load_data_from_key_file()){ + debug("keyfiles in place and ready for action"); + } + else{ + this.key_file = null; + warning("FamiliarPlayersDB:: problems loading key file - can't go any further"); + } + } + + private bool create_key_file(){ + if (test(this.file_name, GLib.FileTest.EXISTS)) { + this.key_file = new KeyFile(); + try{ + if (this.key_file.load_from_file(this.file_name, KeyFileFlags.NONE) == true) { + return true; + } + } + catch(FileError e){ + warning("FamiliarPlayersDB - error trying to load KeyFile"); + } + } + return false; + } + + private bool check_for_keys(){ + try{ + if(this.key_file.has_key(GROUP_NAME, KEY_NAME) == true){ + return true; + } + } + catch(KeyFileError e){ + return false; + } + warning("Seen DB '%s' does not have key '%s' in group '%s'", this.file_name, KEY_NAME, GROUP_NAME); + return false; + } + + private bool load_data_from_key_file(){ + try{ + string[] desktops = this.key_file.get_string_list(GROUP_NAME, + KEY_NAME); + foreach(string s in desktops){ + this.players_DB.set(s, true); + } + return true; + } + catch(FileError error){ + warning("Error loading the Desktop string list"); + return false; + } + } + + private bool write_db() + { + KeyFile keyfile = new KeyFile(); + string[] desktops = {}; + foreach(string key in this.players_DB.keys){ + desktops += key; + } + keyfile.set_string_list(GROUP_NAME, + KEY_NAME, + desktops); + size_t data_length; + string data = null; + try{ + data = keyfile.to_data(out data_length); + } + catch(Error e){ + warning("Problems dumping keyfile to a string"); + return false; + } + + if(create_with_parents(this.dir_name, 0700) != 0){ + warning("Unable to make directory: %s", this.dir_name); + return false; + } + + try{ + if(set_contents(this.file_name, data, (ssize_t)data_length) == false){ + warning("Unable to write out file '%s'", this.file_name); + } + } + catch(FileError err){ + warning("Unable to write out file '%s'", this.file_name); + } + return true; + } + + public void insert(string desktop) + { + if(already_familiar(desktop) == false){ + if(this.write_id != 0){ + Source.remove(this.write_id); + this.write_id = 0; + } + this.write_id = Timeout.add_seconds(60, write_db); + this.players_DB.set(desktop.dup(), true); + } + } + + public bool already_familiar(string desktop) + { + return this.players_DB.get(desktop); + } + + public Gee.Set<string> records() + { + return this.players_DB.keys; + } + +}
\ No newline at end of file diff --git a/src/indicator-sound.c b/src/indicator-sound.c index 9f7e136..3f0d2d3 100755..100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -57,14 +57,14 @@ typedef struct _IndicatorSoundClass IndicatorSoundClass; //GObject class struct struct _IndicatorSoundClass { - IndicatorObjectClass parent_class; + IndicatorObjectClass parent_class; }; //GObject instance struct struct _IndicatorSound { - IndicatorObject parent; + IndicatorObject parent; GtkWidget *slider; - IndicatorServiceManager *service; + IndicatorServiceManager *service; }; // GObject Boiler plate GType indicator_sound_get_type (void); @@ -147,27 +147,27 @@ static void free_the_animation_list(); static void indicator_sound_class_init (IndicatorSoundClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->dispose = indicator_sound_dispose; - object_class->finalize = indicator_sound_finalize; + object_class->dispose = indicator_sound_dispose; + object_class->finalize = indicator_sound_finalize; - IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS(klass); - io_class->get_label = get_label; - io_class->get_image = get_icon; - io_class->get_menu = get_menu; + IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS(klass); + io_class->get_label = get_label; + io_class->get_image = get_icon; + io_class->get_menu = get_menu; io_class->scroll = scroll; design_team_size = gtk_icon_size_register("design-team-size", 22, 22); - return; + return; } static void indicator_sound_init (IndicatorSound *self) { - self->service = NULL; - self->service = indicator_service_manager_new_version(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_VERSION); + self->service = NULL; + self->service = indicator_service_manager_new_version(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_VERSION); prepare_state_machine(); prepare_blocked_animation(); animation_id = 0; @@ -177,31 +177,31 @@ indicator_sound_init (IndicatorSound *self) slider_in_direct_use = FALSE; exterior_vol_update = OUT_OF_RANGE; - g_signal_connect(G_OBJECT(self->service), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_changed), self); + g_signal_connect(G_OBJECT(self->service), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_changed), self); return; } static void indicator_sound_dispose (GObject *object) { - IndicatorSound * self = INDICATOR_SOUND(object); + IndicatorSound * self = INDICATOR_SOUND(object); - if (self->service != NULL) { - g_object_unref(G_OBJECT(self->service)); - self->service = NULL; - } + if (self->service != NULL) { + g_object_unref(G_OBJECT(self->service)); + self->service = NULL; + } g_hash_table_destroy(volume_states); free_the_animation_list(); - G_OBJECT_CLASS (indicator_sound_parent_class)->dispose (object); - return; + G_OBJECT_CLASS (indicator_sound_parent_class)->dispose (object); + return; } -static void +static void free_the_animation_list() { - if(blocked_animation_list != NULL){ + if (blocked_animation_list != NULL) { g_list_foreach (blocked_animation_list, (GFunc)g_object_unref, NULL); g_list_free(blocked_animation_list); blocked_animation_list = NULL; @@ -211,24 +211,24 @@ free_the_animation_list() static void indicator_sound_finalize (GObject *object) { - G_OBJECT_CLASS (indicator_sound_parent_class)->finalize (object); - return; + G_OBJECT_CLASS (indicator_sound_parent_class)->finalize (object); + return; } static GtkLabel * get_label (IndicatorObject * io) { - return NULL; + return NULL; } static GtkImage * get_icon (IndicatorObject * io) -{ +{ gchar* current_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state)); g_debug("At start-up attempting to set the image to %s", current_name); - speaker_image = indicator_image_helper(current_name); - gtk_widget_show(GTK_WIDGET(speaker_image)); - return speaker_image; + speaker_image = indicator_image_helper(current_name); + gtk_widget_show(GTK_WIDGET(speaker_image)); + return speaker_image; } /* Indicator based function to get the menu for the whole @@ -241,8 +241,8 @@ get_menu (IndicatorObject * io) DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(menu); g_object_set_data (G_OBJECT (client), "indicator", io); dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_SLIDER_MENUITEM_TYPE, new_slider_item); - dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TRANSPORT_MENUITEM_TYPE, new_transport_widget); - dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_METADATA_MENUITEM_TYPE, new_metadata_widget); + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TRANSPORT_MENUITEM_TYPE, new_transport_widget); + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_METADATA_MENUITEM_TYPE, new_metadata_widget); // register Key-press listening on the menu widget as the slider does not allow this. g_signal_connect(menu, "key-press-event", G_CALLBACK(key_press_cb), NULL); @@ -253,8 +253,8 @@ static void slider_parent_changed (GtkWidget *widget, gpointer user_data) { - gtk_widget_set_size_request (widget, 200, -1); - g_debug("slider parent changed"); + gtk_widget_set_size_request (widget, 200, -1); + g_debug("slider parent changed"); } /** @@ -264,93 +264,93 @@ Create a new dBusMenu Slider item. static gboolean new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) { - IndicatorObject *io = NULL; + IndicatorObject *io = NULL; - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); - g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - io = g_object_get_data (G_OBJECT (client), "indicator"); + io = g_object_get_data (G_OBJECT (client), "indicator"); - volume_slider = ido_scale_menu_item_new_with_range ("Volume", initial_volume_percent, 0, 100, 1); - g_object_set(volume_slider, "reverse-scroll-events", TRUE, NULL); + volume_slider = ido_scale_menu_item_new_with_range ("Volume", initial_volume_percent, 0, 100, 1); + g_object_set(volume_slider, "reverse-scroll-events", TRUE, NULL); - g_signal_connect (volume_slider, - "notify::parent", G_CALLBACK (slider_parent_changed), - NULL); + g_signal_connect (volume_slider, + "notify::parent", G_CALLBACK (slider_parent_changed), + NULL); - GtkMenuItem *menu_volume_slider = GTK_MENU_ITEM(volume_slider); + GtkMenuItem *menu_volume_slider = GTK_MENU_ITEM(volume_slider); - dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_volume_slider, parent); + dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_volume_slider, parent); - // register slider changes listening on the range - GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); + // register slider changes listening on the range + GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); - INDICATOR_SOUND (io)->slider = slider; + INDICATOR_SOUND (io)->slider = slider; - g_signal_connect(slider, "value-changed", G_CALLBACK(value_changed_event_cb), newitem); - g_signal_connect(volume_slider, "slider-grabbed", G_CALLBACK(slider_grabbed), NULL); - g_signal_connect(volume_slider, "slider-released", G_CALLBACK(slider_released), NULL); - g_signal_connect(slider, "style-set", G_CALLBACK(style_changed_cb), NULL); + g_signal_connect(slider, "value-changed", G_CALLBACK(value_changed_event_cb), newitem); + g_signal_connect(volume_slider, "slider-grabbed", G_CALLBACK(slider_grabbed), NULL); + g_signal_connect(volume_slider, "slider-released", G_CALLBACK(slider_released), NULL); + g_signal_connect(slider, "style-set", G_CALLBACK(style_changed_cb), NULL); - // Set images on the ido - GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)volume_slider); - GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks(g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_ZERO))); - gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU); - g_object_unref(primary_gicon); + // Set images on the ido + GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)volume_slider); + GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks(g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_ZERO))); + gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU); + g_object_unref(primary_gicon); - GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)volume_slider); - GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks(g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_HIGH))); - gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU); - g_object_unref(secondary_gicon); + GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)volume_slider); + GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks(g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_HIGH))); + gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU); + g_object_unref(secondary_gicon); - gtk_widget_set_sensitive(volume_slider, !initial_mute); + gtk_widget_set_sensitive(volume_slider, !initial_mute); - GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (slider)); - gtk_adjustment_set_step_increment(adj, 3); + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (slider)); + gtk_adjustment_set_step_increment(adj, 3); - gtk_widget_show_all(volume_slider); + gtk_widget_show_all(volume_slider); - return TRUE; + return TRUE; } static gboolean new_transport_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) { - g_debug("indicator-sound: new_transport_bar() called "); + g_debug("indicator-sound: new_transport_bar() called "); + + GtkWidget* bar = NULL; - GtkWidget* bar = NULL; - - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - bar = transport_widget_new(newitem); + bar = transport_widget_new(newitem); GtkMenuItem *menu_transport_bar = GTK_MENU_ITEM(bar); dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_transport_bar, parent); - - gtk_widget_show_all(bar); - - return TRUE; + + gtk_widget_show_all(bar); + + return TRUE; } static gboolean new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) { - g_debug("indicator-sound: new_metadata_widget"); + g_debug("indicator-sound: new_metadata_widget"); - GtkWidget* metadata = NULL; + GtkWidget* metadata = NULL; - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - metadata = metadata_widget_new (newitem); - GtkMenuItem *menu_metadata_widget = GTK_MENU_ITEM(metadata); - + metadata = metadata_widget_new (newitem); + GtkMenuItem *menu_metadata_widget = GTK_MENU_ITEM(metadata); + dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_metadata_widget, parent); - gtk_widget_show_all(metadata); + gtk_widget_show_all(metadata); - return TRUE; + return TRUE; } //const gchar* path = dbusmenu_menuitem_property_get(new_item, DBUSMENU_METADATA_MENUITEM_IMAGE_PATH); @@ -361,62 +361,62 @@ new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm static void connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer userdata) { - if (connected) { - if (sound_dbus_proxy == NULL) { - GError * error = NULL; - - DBusGConnection * sbus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - - sound_dbus_proxy = dbus_g_proxy_new_for_name_owner(sbus, - INDICATOR_SOUND_DBUS_NAME, - INDICATOR_SOUND_SERVICE_DBUS_OBJECT, - INDICATOR_SOUND_SERVICE_DBUS_INTERFACE, - &error); + if (connected) { + if (sound_dbus_proxy == NULL) { + GError * error = NULL; - if (error != NULL) { - g_warning("Unable to get status proxy: %s", error->message); - g_error_free(error); - } - g_debug("about to connect to the signals"); - dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_INPUT_WHILE_MUTED, G_TYPE_BOOLEAN, G_TYPE_INVALID); + DBusGConnection * sbus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_INPUT_WHILE_MUTED, G_CALLBACK(catch_signal_sink_input_while_muted), NULL, NULL); - dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_VOLUME_UPDATE, G_TYPE_DOUBLE, G_TYPE_INVALID); - dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_VOLUME_UPDATE, G_CALLBACK(catch_signal_sink_volume_update), NULL, NULL); - dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_MUTE_UPDATE, G_TYPE_BOOLEAN, G_TYPE_INVALID); - dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_MUTE_UPDATE, G_CALLBACK(catch_signal_sink_mute_update), NULL, NULL); - dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_AVAILABLE_UPDATE, G_TYPE_BOOLEAN, G_TYPE_INVALID); - dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_AVAILABLE_UPDATE, G_CALLBACK(catch_signal_sink_availability_update), NULL, NULL); + sound_dbus_proxy = dbus_g_proxy_new_for_name_owner(sbus, + INDICATOR_SOUND_DBUS_NAME, + INDICATOR_SOUND_SERVICE_DBUS_OBJECT, + INDICATOR_SOUND_SERVICE_DBUS_INTERFACE, + &error); - // Ensure we are in a coherent state with the service at start up. - // Preserve ordering! - fetch_volume_percent_from_dbus(); - fetch_mute_value_from_dbus(); - fetch_sink_availability_from_dbus(); - } + if (error != NULL) { + g_warning("Unable to get status proxy: %s", error->message); + g_error_free(error); + } + g_debug("about to connect to the signals"); + dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_INPUT_WHILE_MUTED, G_TYPE_BOOLEAN, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_INPUT_WHILE_MUTED, G_CALLBACK(catch_signal_sink_input_while_muted), NULL, NULL); + dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_VOLUME_UPDATE, G_TYPE_DOUBLE, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_VOLUME_UPDATE, G_CALLBACK(catch_signal_sink_volume_update), NULL, NULL); + dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_MUTE_UPDATE, G_TYPE_BOOLEAN, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_MUTE_UPDATE, G_CALLBACK(catch_signal_sink_mute_update), NULL, NULL); + dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_AVAILABLE_UPDATE, G_TYPE_BOOLEAN, G_TYPE_INVALID); + dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_AVAILABLE_UPDATE, G_CALLBACK(catch_signal_sink_availability_update), NULL, NULL); + + // Ensure we are in a coherent state with the service at start up. + // Preserve ordering! + fetch_volume_percent_from_dbus(); + fetch_mute_value_from_dbus(); + fetch_sink_availability_from_dbus(); + } - } else { - //TODO : will need to handle this scenario - // Not much can we do here really, if there is no dbus connection tis goosed. - } + } else { + //TODO : will need to handle this scenario + // Not much can we do here really, if there is no dbus connection tis goosed. + } - return; + return; } /* Prepare states Array. */ -void +void prepare_state_machine() { - volume_states = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); - g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED), g_strdup("audio-volume-muted-panel")); - g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_ZERO), g_strdup("audio-volume-low-zero-panel")); - g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_LOW), g_strdup("audio-volume-low-panel")); - g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MEDIUM), g_strdup("audio-volume-medium-panel")); - g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_HIGH), g_strdup("audio-volume-high-panel")); - g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT), g_strdup("audio-volume-muted-blocking-panel")); - g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_SINKS_NONE), g_strdup("audio-output-none-panel")); + volume_states = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); + g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED), g_strdup("audio-volume-muted-panel")); + g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_ZERO), g_strdup("audio-volume-low-zero-panel")); + g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_LOW), g_strdup("audio-volume-low-panel")); + g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MEDIUM), g_strdup("audio-volume-medium-panel")); + g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_HIGH), g_strdup("audio-volume-high-panel")); + g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT), g_strdup("audio-volume-muted-blocking-panel")); + g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_SINKS_NONE), g_strdup("audio-output-none-panel")); } /* @@ -436,7 +436,7 @@ prepare_blocked_animation() temp_image = indicator_image_helper(blocked_name); GdkPixbuf* blocked_buf = gtk_image_get_pixbuf(temp_image); - if(mute_buf == NULL || blocked_buf == NULL){ + if (mute_buf == NULL || blocked_buf == NULL) { g_debug("Don bother with the animation, the theme aint got the goods !"); return; } @@ -444,8 +444,7 @@ prepare_blocked_animation() int i; // sample 51 snapshots - range : 0-256 - for(i = 0; i < 51; i++) - { + for (i = 0; i < 51; i++) { gdk_pixbuf_composite(mute_buf, blocked_buf, 0, 0, gdk_pixbuf_get_width(mute_buf), gdk_pixbuf_get_height(mute_buf), @@ -453,9 +452,9 @@ prepare_blocked_animation() blocked_animation_list = g_list_append(blocked_animation_list, gdk_pixbuf_copy(blocked_buf)); } g_object_ref_sink(mute_buf); - g_object_unref(mute_buf); + g_object_unref(mute_buf); g_object_ref_sink(blocked_buf); - g_object_unref(blocked_buf); + g_object_unref(blocked_buf); } @@ -487,11 +486,11 @@ tidy_up_hash() static void update_state(const gint state) { -/* g_debug("update state beginning - previous_state = %i", previous_state);*/ + /* g_debug("update state beginning - previous_state = %i", previous_state);*/ previous_state = current_state; -/* g_debug("update state 3rd line - previous_state = %i", previous_state);*/ + /* g_debug("update state 3rd line - previous_state = %i", previous_state);*/ current_state = state; gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state)); @@ -502,51 +501,46 @@ update_state(const gint state) void determine_state_from_volume(gdouble volume_percent) { -/* g_debug("determine_state_from_volume - previous_state = %i", previous_state);*/ - if (device_available == FALSE) - return; - gint state = previous_state; - if (volume_percent < 30.0 && volume_percent > 0){ - state = STATE_LOW; - } - else if(volume_percent < 70.0 && volume_percent >= 30.0){ - state = STATE_MEDIUM; - } - else if(volume_percent >= 70.0){ - state = STATE_HIGH; - } - else if(volume_percent == 0.0){ - state = STATE_ZERO; - } - update_state(state); + /* g_debug("determine_state_from_volume - previous_state = %i", previous_state);*/ + if (device_available == FALSE) + return; + gint state = previous_state; + if (volume_percent < 30.0 && volume_percent > 0) { + state = STATE_LOW; + } else if (volume_percent < 70.0 && volume_percent >= 30.0) { + state = STATE_MEDIUM; + } else if (volume_percent >= 70.0) { + state = STATE_HIGH; + } else if (volume_percent == 0.0) { + state = STATE_ZERO; + } + update_state(state); } static gboolean start_animation() { - blocked_iter = blocked_animation_list; - blocked_id = 0; - g_debug("exit from blocked hold start the animation\n"); - animation_id = g_timeout_add(50, fade_back_to_mute_image, NULL); - return FALSE; + blocked_iter = blocked_animation_list; + blocked_id = 0; + g_debug("exit from blocked hold start the animation\n"); + animation_id = g_timeout_add(50, fade_back_to_mute_image, NULL); + return FALSE; } static gboolean fade_back_to_mute_image() { - if(blocked_iter != NULL) - { - g_debug("in animation 'loop'\n"); - gtk_image_set_from_pixbuf(speaker_image, blocked_iter->data); - blocked_iter = blocked_iter->next; - return TRUE; - } - else{ - animation_id = 0; - g_debug("exit from animation now\n"); - return FALSE; - } + if (blocked_iter != NULL) { + g_debug("in animation 'loop'\n"); + gtk_image_set_from_pixbuf(speaker_image, blocked_iter->data); + blocked_iter = blocked_iter->next; + return TRUE; + } else { + animation_id = 0; + g_debug("exit from animation now\n"); + return FALSE; + } } /*******************************************************************/ @@ -555,67 +549,67 @@ fade_back_to_mute_image() static void fetch_sink_availability_from_dbus() { - GError * error = NULL; - gboolean * available_input; - available_input = g_new0(gboolean, 1); - org_ayatana_indicator_sound_get_sink_availability(sound_dbus_proxy, available_input, &error); - if (error != NULL) { - g_warning("Unable to fetch AVAILABILITY at indicator start up: %s", error->message); - g_error_free(error); - g_free(available_input); - return; - } - device_available = *available_input; - if (device_available == FALSE){ - update_state(STATE_SINKS_NONE); - g_debug("NO DEVICE AVAILABLE"); - } - - if (GTK_IS_WIDGET (volume_slider)) - gtk_widget_set_sensitive(volume_slider, device_available); - + GError * error = NULL; + gboolean * available_input; + available_input = g_new0(gboolean, 1); + org_ayatana_indicator_sound_get_sink_availability(sound_dbus_proxy, available_input, &error); + if (error != NULL) { + g_warning("Unable to fetch AVAILABILITY at indicator start up: %s", error->message); + g_error_free(error); g_free(available_input); - g_debug("IndicatorSound::fetch_sink_availability_from_dbus -> AVAILABILTY returned from dbus method is %i", device_available); + return; + } + device_available = *available_input; + if (device_available == FALSE) { + update_state(STATE_SINKS_NONE); + g_debug("NO DEVICE AVAILABLE"); + } + + if (GTK_IS_WIDGET (volume_slider)) + gtk_widget_set_sensitive(volume_slider, device_available); + + g_free(available_input); + g_debug("IndicatorSound::fetch_sink_availability_from_dbus -> AVAILABILTY returned from dbus method is %i", device_available); } -static void +static void fetch_volume_percent_from_dbus() { - GError * error = NULL; - gdouble *volume_percent_input; - volume_percent_input = g_new0(gdouble, 1); - org_ayatana_indicator_sound_get_sink_volume(sound_dbus_proxy, volume_percent_input, &error); - if (error != NULL) { - g_warning("Unable to fetch VOLUME at indicator start up: %s", error->message); - g_error_free(error); - g_free(volume_percent_input); - return; - } - initial_volume_percent = *volume_percent_input; - determine_state_from_volume(initial_volume_percent); + GError * error = NULL; + gdouble *volume_percent_input; + volume_percent_input = g_new0(gdouble, 1); + org_ayatana_indicator_sound_get_sink_volume(sound_dbus_proxy, volume_percent_input, &error); + if (error != NULL) { + g_warning("Unable to fetch VOLUME at indicator start up: %s", error->message); + g_error_free(error); g_free(volume_percent_input); - g_debug("at the indicator start up and the volume percent returned from dbus method is %f", initial_volume_percent); + return; + } + initial_volume_percent = *volume_percent_input; + determine_state_from_volume(initial_volume_percent); + g_free(volume_percent_input); + g_debug("at the indicator start up and the volume percent returned from dbus method is %f", initial_volume_percent); } -static void +static void fetch_mute_value_from_dbus() { - GError * error = NULL; - gboolean *mute_input; - mute_input = g_new0(gboolean, 1); - org_ayatana_indicator_sound_get_sink_mute(sound_dbus_proxy, mute_input, &error); - if (error != NULL) { - g_warning("Unable to fetch MUTE at indicator start up: %s", error->message); - g_error_free(error); - g_free(mute_input); - return; - } - initial_mute = *mute_input; - if (initial_mute == TRUE) - update_state(STATE_MUTED); + GError * error = NULL; + gboolean *mute_input; + mute_input = g_new0(gboolean, 1); + org_ayatana_indicator_sound_get_sink_mute(sound_dbus_proxy, mute_input, &error); + if (error != NULL) { + g_warning("Unable to fetch MUTE at indicator start up: %s", error->message); + g_error_free(error); g_free(mute_input); - g_debug("at the indicator start up and the MUTE returned from dbus method is %i", initial_mute); + return; + } + initial_mute = *mute_input; + if (initial_mute == TRUE) + update_state(STATE_MUTED); + g_free(mute_input); + g_debug("at the indicator start up and the MUTE returned from dbus method is %i", initial_mute); } /*******************************************************************/ @@ -624,70 +618,68 @@ fetch_mute_value_from_dbus() static void catch_signal_sink_input_while_muted(DBusGProxy * proxy, gboolean block_value, gpointer userdata) { - g_debug("signal caught - sink input while muted with value %i", block_value); - if (block_value == 1 && blocked_id == 0 && animation_id == 0 && blocked_animation_list != NULL) { - gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT)); - indicator_image_helper_update(speaker_image, image_name); - blocked_id = g_timeout_add_seconds(5, start_animation, NULL); - } + g_debug("signal caught - sink input while muted with value %i", block_value); + if (block_value == 1 && blocked_id == 0 && animation_id == 0 && blocked_animation_list != NULL) { + gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT)); + indicator_image_helper_update(speaker_image, image_name); + blocked_id = g_timeout_add_seconds(5, start_animation, NULL); + } } static void catch_signal_sink_volume_update(DBusGProxy *proxy, gdouble volume_percent, gpointer userdata) { - if (slider_in_direct_use == FALSE){ - GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); - GtkRange *range = (GtkRange*)slider; + if (slider_in_direct_use == FALSE) { + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); + GtkRange *range = (GtkRange*)slider; - // DEBUG - gdouble current_value = gtk_range_get_value(range); - g_debug("SIGNAL- update sink volume - current_value : %f and new value : %f", current_value, volume_percent); - exterior_vol_update = volume_percent; - gtk_range_set_value(range, volume_percent); - determine_state_from_volume(volume_percent); - } + // DEBUG + gdouble current_value = gtk_range_get_value(range); + g_debug("SIGNAL- update sink volume - current_value : %f and new value : %f", current_value, volume_percent); + exterior_vol_update = volume_percent; + gtk_range_set_value(range, volume_percent); + determine_state_from_volume(volume_percent); + } } static void catch_signal_sink_mute_update(DBusGProxy *proxy, gboolean mute_value, gpointer userdata) { - //We can be sure the service won't send a mute signal unless it has changed ! - //UNMUTE's force a volume update therefore icon is updated appropriately => no need for unmute handling here. - if(mute_value == TRUE && device_available == TRUE) - { - update_state(STATE_MUTED); - } - else{ - reset_mute_blocking_animation(); - } - g_debug("signal caught - sink mute update with mute value: %i", mute_value); - gtk_widget_set_sensitive(volume_slider, !mute_value); + //We can be sure the service won't send a mute signal unless it has changed ! + //UNMUTE's force a volume update therefore icon is updated appropriately => no need for unmute handling here. + if (mute_value == TRUE && device_available == TRUE) { + update_state(STATE_MUTED); + } else { + reset_mute_blocking_animation(); + } + g_debug("signal caught - sink mute update with mute value: %i", mute_value); + gtk_widget_set_sensitive(volume_slider, !mute_value); } static void reset_mute_blocking_animation() { - if(animation_id != 0){ - g_debug("about to remove the animation_id callback from the mainloop!!**"); - g_source_remove(animation_id); - animation_id = 0; - } - if(blocked_id != 0){ - g_debug("about to remove the blocked_id callback from the mainloop!!**"); - g_source_remove(blocked_id); - blocked_id = 0; - } + if (animation_id != 0) { + g_debug("about to remove the animation_id callback from the mainloop!!**"); + g_source_remove(animation_id); + animation_id = 0; + } + if (blocked_id != 0) { + g_debug("about to remove the blocked_id callback from the mainloop!!**"); + g_source_remove(blocked_id); + blocked_id = 0; + } } static void catch_signal_sink_availability_update(DBusGProxy *proxy, gboolean available_value, gpointer userdata) { - device_available = available_value; - if (device_available == FALSE){ - update_state(STATE_SINKS_NONE); - } - g_debug("signal caught - sink availability update with value: %i", available_value); + device_available = available_value; + if (device_available == FALSE) { + update_state(STATE_SINKS_NONE); + } + g_debug("signal caught - sink availability update with value: %i", available_value); } @@ -703,36 +695,36 @@ This callback will get triggered irregardless of whether its a user change or a static gboolean value_changed_event_cb(GtkRange *range, gpointer user_data) { - gdouble current_value = CLAMP(gtk_range_get_value(range), 0, 100); - if(current_value == exterior_vol_update){ - g_debug("ignore the value changed event - its come from the outside"); - return FALSE; - } - DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data; - GValue value = {0}; - g_value_init(&value, G_TYPE_DOUBLE); - g_value_set_double(&value, current_value); - g_debug("Value changed callback - = %f", current_value); - dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0); - // This is not ideal in that the icon ui will update on ui actions and not on actual service feedback. - // but necessary for now as the server does not send volume update information if the source of change was this ui. - determine_state_from_volume(current_value); + gdouble current_value = CLAMP(gtk_range_get_value(range), 0, 100); + if (current_value == exterior_vol_update) { + g_debug("ignore the value changed event - its come from the outside"); return FALSE; + } + DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data; + GValue value = {0}; + g_value_init(&value, G_TYPE_DOUBLE); + g_value_set_double(&value, current_value); + g_debug("Value changed callback - = %f", current_value); + dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0); + // This is not ideal in that the icon ui will update on ui actions and not on actual service feedback. + // but necessary for now as the server does not send volume update information if the source of change was this ui. + determine_state_from_volume(current_value); + return FALSE; } static void slider_grabbed (GtkWidget *widget, gpointer user_data) { - slider_in_direct_use = TRUE; - g_debug ("!!!!!! grabbed\n"); + slider_in_direct_use = TRUE; + g_debug ("!!!!!! grabbed\n"); } static void slider_released (GtkWidget *widget, gpointer user_data) { - slider_in_direct_use = FALSE; - g_debug ("!!!!!! released\n"); + slider_in_direct_use = FALSE; + g_debug ("!!!!!! released\n"); } @@ -752,30 +744,22 @@ key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data) GtkWidget *menuitem; menuitem = GTK_MENU_SHELL (widget)->active_menu_item; - if(IDO_IS_SCALE_MENU_ITEM(menuitem) == TRUE) - { - switch(event->keyval) - { + if (IDO_IS_SCALE_MENU_ITEM(menuitem) == TRUE) { + switch (event->keyval) { case GDK_Right: - digested = TRUE; - if(event->state & GDK_CONTROL_MASK) - { - new_value = 100; - } - else - { + digested = TRUE; + if (event->state & GDK_CONTROL_MASK) { + new_value = 100; + } else { new_value = current_value + five_percent; - } - break; - case GDK_Left: - digested = TRUE; - if(event->state & GDK_CONTROL_MASK) - { - new_value = 0; } - else - { - new_value = current_value - five_percent; + break; + case GDK_Left: + digested = TRUE; + if (event->state & GDK_CONTROL_MASK) { + new_value = 0; + } else { + new_value = current_value - five_percent; } break; case GDK_plus: @@ -791,11 +775,10 @@ key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data) } new_value = CLAMP(new_value, 0, 100); - if(new_value != current_value && current_state != STATE_MUTED) - { + if (new_value != current_value && current_state != STATE_MUTED) { g_debug("Attempting to set the range from the key listener to %f", new_value); // In order to ensure that the exterior filtering does not catch this, reset the exterior_vol_update - // to ensure these updates. + // to ensure these updates. exterior_vol_update = OUT_OF_RANGE; gtk_range_set_value(range, new_value); } @@ -817,18 +800,17 @@ style_changed_cb(GtkWidget *widget, gpointer user_data) static void scroll (IndicatorObject *io, gint delta, IndicatorScrollDirection direction) { - if (device_available == FALSE || current_state == STATE_MUTED) - return; + if (device_available == FALSE || current_state == STATE_MUTED) + return; IndicatorSound *sound = INDICATOR_SOUND (io); GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (sound->slider)); gdouble value = gtk_range_get_value (GTK_RANGE (sound->slider)); - - if (direction == INDICATOR_OBJECT_SCROLL_UP){ - value += adj->step_increment; - } - else{ - value -= adj->step_increment; + + if (direction == INDICATOR_OBJECT_SCROLL_UP) { + value += adj->step_increment; + } else { + value -= adj->step_increment; } gtk_range_set_value (GTK_RANGE (sound->slider), value); } diff --git a/src/indicator-sound.h b/src/indicator-sound.h index e508390..386ad2a 100644 --- a/src/indicator-sound.h +++ b/src/indicator-sound.h @@ -11,16 +11,16 @@ Authors: Conor Curran <conor.curra@canonical.com> Ted Gould <ted@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 +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 +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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ diff --git a/src/metadata-menu-item.c b/src/metadata-menu-item.c index f111baa..f33e848 100644 --- a/src/metadata-menu-item.c +++ b/src/metadata-menu-item.c @@ -1,6 +1,24 @@ /* metadata-menu-item.c generated by valac, the Vala compiler * generated from metadata-menu-item.vala, do not modify */ +/* +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 <glib.h> #include <glib-object.h> @@ -8,11 +26,33 @@ #include <libdbusmenu-glib/menuitem-proxy.h> #include <libdbusmenu-glib/menuitem.h> #include <libdbusmenu-glib/server.h> +#include <common-defs.h> +#include <gee.h> #include <stdlib.h> #include <string.h> -#include <gee.h> +#define TYPE_PLAYER_ITEM (player_item_get_type ()) +#define PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_ITEM, PlayerItem)) +#define PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_ITEM, PlayerItemClass)) +#define IS_PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_ITEM)) +#define IS_PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_ITEM)) +#define PLAYER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_ITEM, PlayerItemClass)) + +typedef struct _PlayerItem PlayerItem; +typedef struct _PlayerItemClass PlayerItemClass; +typedef struct _PlayerItemPrivate PlayerItemPrivate; + +#define TYPE_MPRIS_CONTROLLER (mpris_controller_get_type ()) +#define MPRIS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER, MprisController)) +#define MPRIS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MPRIS_CONTROLLER, MprisControllerClass)) +#define IS_MPRIS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MPRIS_CONTROLLER)) +#define IS_MPRIS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MPRIS_CONTROLLER)) +#define MPRIS_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MPRIS_CONTROLLER, MprisControllerClass)) + +typedef struct _MprisController MprisController; +typedef struct _MprisControllerClass MprisControllerClass; + #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)) @@ -23,41 +63,53 @@ typedef struct _MetadataMenuitem MetadataMenuitem; typedef struct _MetadataMenuitemClass MetadataMenuitemClass; typedef struct _MetadataMenuitemPrivate MetadataMenuitemPrivate; +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) #define _g_free0(var) (var = (g_free (var), NULL)) -struct _MetadataMenuitem { +struct _PlayerItem { DbusmenuMenuitem parent_instance; + PlayerItemPrivate * priv; + MprisController* mpris_adaptor; +}; + +struct _PlayerItemClass { + DbusmenuMenuitemClass parent_class; + void (*check_layout) (PlayerItem* self); +}; + +struct _MetadataMenuitem { + PlayerItem parent_instance; MetadataMenuitemPrivate * priv; }; struct _MetadataMenuitemClass { - DbusmenuMenuitemClass parent_class; + PlayerItemClass parent_class; }; static gpointer metadata_menuitem_parent_class = NULL; +GType player_item_get_type (void); +GType mpris_controller_get_type (void); GType metadata_menuitem_get_type (void); enum { METADATA_MENUITEM_DUMMY_PROPERTY }; -#define METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TYPE "x-canonical-metadata-menu-item" -#define METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST "x-canonical-metadata-text-artist" -#define METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TEXT_PIECE "x-canonical-metadata-text-piece" -#define METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER "x-canonical-metadata-text-container" -#define METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_IMAGE_PATH "x-canonical-metadata-image" +PlayerItem* player_item_new (void); +PlayerItem* player_item_construct (GType object_type); MetadataMenuitem* metadata_menuitem_new (void); MetadataMenuitem* metadata_menuitem_construct (GType object_type); -char* metadata_menuitem_sanitize_image_path (const char* path); -void metadata_menuitem_update (MetadataMenuitem* self, GeeHashMap* data); -static void metadata_menuitem_real_handle_event (DbusmenuMenuitem* base, const char* name, GValue* input_value, guint timestamp); +GeeHashSet* metadata_menuitem_attributes_format (void); +gboolean metadata_menuitem_populated (MetadataMenuitem* self); +static void metadata_menuitem_real_check_layout (PlayerItem* base); +static int _vala_strcmp0 (const char * str1, const char * str2); MetadataMenuitem* metadata_menuitem_construct (GType object_type) { MetadataMenuitem * self; - self = g_object_newv (object_type, 0, NULL); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_MENUITEM_PROP_TYPE, METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TYPE); + self = (MetadataMenuitem*) player_item_construct (object_type); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_METADATA_MENUITEM_TYPE); return self; } @@ -67,102 +119,58 @@ MetadataMenuitem* metadata_menuitem_new (void) { } -static char* string_strip (const char* self) { - char* result = NULL; - char* _result_; - g_return_val_if_fail (self != NULL, NULL); - _result_ = g_strdup (self); - g_strstrip (_result_); - result = _result_; +GeeHashSet* metadata_menuitem_attributes_format (void) { + GeeHashSet* result = NULL; + GeeHashSet* attrs; + attrs = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, NULL, NULL); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_TEXT_TITLE); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_ARTURL); + result = attrs; return result; } -void metadata_menuitem_update (MetadataMenuitem* self, GeeHashMap* data) { - char* _tmp1_; +static char* bool_to_string (gboolean self) { + char* result = NULL; + if (self) { + result = g_strdup ("true"); + return result; + } else { + result = g_strdup ("false"); + return result; + } +} + + +static void metadata_menuitem_real_check_layout (PlayerItem* base) { + MetadataMenuitem * self; char* _tmp0_; - char* _tmp3_; - char* _tmp2_; - char* _tmp5_; - char* _tmp4_; - char* _tmp7_; - char* _tmp6_; - g_return_if_fail (self != NULL); - g_return_if_fail (data != NULL); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST, _tmp1_ = string_strip (_tmp0_ = (char*) gee_abstract_map_get ((GeeAbstractMap*) data, "artist"))); - _g_free0 (_tmp1_); + self = (MetadataMenuitem*) base; + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, DBUSMENU_MENUITEM_PROP_VISIBLE, metadata_menuitem_populated (self)); + g_debug ("metadata-menu-item.vala:43: check layout for the metadata = %s", _tmp0_ = bool_to_string (metadata_menuitem_populated (self))); _g_free0 (_tmp0_); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TEXT_PIECE, _tmp3_ = string_strip (_tmp2_ = (char*) gee_abstract_map_get ((GeeAbstractMap*) data, "title"))); - _g_free0 (_tmp3_); - _g_free0 (_tmp2_); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER, _tmp5_ = string_strip (_tmp4_ = (char*) gee_abstract_map_get ((GeeAbstractMap*) data, "album"))); - _g_free0 (_tmp5_); - _g_free0 (_tmp4_); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, METADATA_MENUITEM_DBUSMENU_METADATA_MENUITEM_IMAGE_PATH, _tmp7_ = metadata_menuitem_sanitize_image_path (_tmp6_ = (char*) gee_abstract_map_get ((GeeAbstractMap*) data, "arturl"))); - _g_free0 (_tmp7_); - _g_free0 (_tmp6_); } -static char* string_slice (const char* self, glong start, glong end) { - char* result = NULL; - glong string_length; +gboolean metadata_menuitem_populated (MetadataMenuitem* self) { + gboolean result = FALSE; gboolean _tmp0_ = FALSE; - gboolean _tmp1_ = FALSE; - const char* start_string; - g_return_val_if_fail (self != NULL, NULL); - string_length = g_utf8_strlen (self, -1); - if (start < 0) { - start = string_length + start; - } - if (end < 0) { - end = string_length + end; - } - if (start >= 0) { - _tmp0_ = start <= string_length; + g_return_val_if_fail (self != NULL, FALSE); + if (dbusmenu_menuitem_property_get ((DbusmenuMenuitem*) self, DBUSMENU_METADATA_MENUITEM_TEXT_TITLE) != NULL) { + _tmp0_ = _vala_strcmp0 (dbusmenu_menuitem_property_get ((DbusmenuMenuitem*) self, DBUSMENU_METADATA_MENUITEM_TEXT_TITLE), "") != 0; } else { _tmp0_ = FALSE; } - g_return_val_if_fail (_tmp0_, NULL); - if (end >= 0) { - _tmp1_ = end <= string_length; - } else { - _tmp1_ = FALSE; - } - g_return_val_if_fail (_tmp1_, NULL); - g_return_val_if_fail (start <= end, NULL); - start_string = g_utf8_offset_to_pointer (self, start); - result = g_strndup (start_string, ((gchar*) g_utf8_offset_to_pointer (start_string, end - start)) - ((gchar*) start_string)); - return result; -} - - -char* metadata_menuitem_sanitize_image_path (const char* path) { - char* result = NULL; - char* _result_; - g_return_val_if_fail (path != NULL, NULL); - _result_ = string_strip (path); - if (g_str_has_prefix (_result_, "file:///")) { - char* _tmp0_; - _result_ = (_tmp0_ = string_slice (_result_, (glong) 7, g_utf8_strlen (_result_, -1)), _g_free0 (_result_), _tmp0_); - } - g_debug ("metadata-menu-item.vala:32: Sanitize image path - result = %s", _result_); - result = _result_; + result = _tmp0_; return result; } -static void metadata_menuitem_real_handle_event (DbusmenuMenuitem* base, const char* name, GValue* input_value, guint timestamp) { - MetadataMenuitem * self; - self = (MetadataMenuitem*) base; - g_return_if_fail (name != NULL); - g_debug ("metadata-menu-item.vala:38: MetadataItem -> handle event caught!"); -} - - static void metadata_menuitem_class_init (MetadataMenuitemClass * klass) { metadata_menuitem_parent_class = g_type_class_peek_parent (klass); - DBUSMENU_MENUITEM_CLASS (klass)->handle_event = metadata_menuitem_real_handle_event; + PLAYER_ITEM_CLASS (klass)->check_layout = metadata_menuitem_real_check_layout; } @@ -175,12 +183,23 @@ GType metadata_menuitem_get_type (void) { if (g_once_init_enter (&metadata_menuitem_type_id__volatile)) { static const GTypeInfo g_define_type_info = { sizeof (MetadataMenuitemClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) metadata_menuitem_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (MetadataMenuitem), 0, (GInstanceInitFunc) metadata_menuitem_instance_init, NULL }; GType metadata_menuitem_type_id; - metadata_menuitem_type_id = g_type_register_static (DBUSMENU_TYPE_MENUITEM, "MetadataMenuitem", &g_define_type_info, 0); + metadata_menuitem_type_id = g_type_register_static (TYPE_PLAYER_ITEM, "MetadataMenuitem", &g_define_type_info, 0); g_once_init_leave (&metadata_menuitem_type_id__volatile, metadata_menuitem_type_id); } return metadata_menuitem_type_id__volatile; } +static int _vala_strcmp0 (const char * str1, const char * str2) { + if (str1 == NULL) { + return -(str1 != str2); + } + if (str2 == NULL) { + return str1 != str2; + } + return strcmp (str1, str2); +} + + diff --git a/src/metadata-menu-item.vala b/src/metadata-menu-item.vala index 82926b1..541fbf4 100644 --- a/src/metadata-menu-item.vala +++ b/src/metadata-menu-item.vala @@ -1,40 +1,52 @@ +/* +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/>. +*/ + using Dbusmenu; using Gee; +using DbusmenuMetadata; -public class MetadataMenuitem : Dbusmenu.Menuitem +public class MetadataMenuitem : PlayerItem { - /* Not ideal duplicate definition of const - see common-defs/h */ - const string DBUSMENU_METADATA_MENUITEM_TYPE = "x-canonical-metadata-menu-item"; - const string DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST = "x-canonical-metadata-text-artist"; - const string DBUSMENU_METADATA_MENUITEM_TEXT_PIECE = "x-canonical-metadata-text-piece"; - const string DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER = "x-canonical-metadata-text-container"; - const string DBUSMENU_METADATA_MENUITEM_IMAGE_PATH = "x-canonical-metadata-image"; - public MetadataMenuitem() { - this.property_set(MENUITEM_PROP_TYPE, DBUSMENU_METADATA_MENUITEM_TYPE); + this.property_set(MENUITEM_PROP_TYPE, MENUITEM_TYPE); } - public void update(HashMap<string, string> data) + public static HashSet<string> attributes_format() { - this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST, data.get("artist").strip()); - this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_PIECE, data.get("title").strip()); - this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER, data.get("album").strip()); - this.property_set(DBUSMENU_METADATA_MENUITEM_IMAGE_PATH, sanitize_image_path(data.get("arturl"))); + HashSet<string> attrs = new HashSet<string>(); + attrs.add(MENUITEM_TEXT_TITLE); + attrs.add(MENUITEM_TEXT_ARTIST); + attrs.add(MENUITEM_TEXT_ALBUM); + attrs.add(MENUITEM_ARTURL); + return attrs; } - public static string sanitize_image_path(string path) + public override void check_layout(){ + this.property_set_bool(MENUITEM_PROP_VISIBLE, this.populated()); + debug("check layout for the metadata = %s", this.populated().to_string()); + } + + public bool populated() { - string result = path.strip(); - if(result.has_prefix("file:///")){ - result = result.slice(7, result.len()); - } - debug("Sanitize image path - result = %s", result); - return result; + return (this.property_get(MENUITEM_TEXT_TITLE) != null && + this.property_get(MENUITEM_TEXT_TITLE) != ""); } - public override void handle_event(string name, GLib.Value input_value, uint timestamp) - { - debug("MetadataItem -> handle event caught!"); - } }
\ No newline at end of file diff --git a/src/metadata-widget.c b/src/metadata-widget.c index c4d3b50..66e8cac 100644 --- a/src/metadata-widget.c +++ b/src/metadata-widget.c @@ -93,7 +93,7 @@ metadata_widget_init (MetadataWidget *self) // image priv->album_art = gtk_image_new(); - priv->image_path = g_strdup(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_IMAGE_PATH)); + priv->image_path = g_strdup(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_ARTURL)); update_album_art(self); gtk_box_pack_start (GTK_BOX (priv->hbox), priv->album_art, FALSE, FALSE, 0); GtkWidget* vbox = gtk_vbox_new(TRUE, 0); @@ -106,13 +106,13 @@ metadata_widget_init (MetadataWidget *self) // piece GtkWidget* piece; - piece = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_PIECE)); + piece = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_TITLE)); priv->piece_label = piece; // container GtkWidget* container; - container = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER)); + container = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM)); priv->container_label = container; // Pack in the right order @@ -171,13 +171,13 @@ metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property, if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST, property) == 0){ gtk_label_set_text(GTK_LABEL(priv->artist_label), g_value_get_string(value)); } - else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_PIECE, property) == 0){ + else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_TITLE, property) == 0){ gtk_label_set_text(GTK_LABEL(priv->piece_label), g_value_get_string(value)); } - else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER, property) == 0){ + else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM, property) == 0){ gtk_label_set_text(GTK_LABEL(priv->container_label), g_value_get_string(value)); } - else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_IMAGE_PATH, property) == 0){ + else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ARTURL, property) == 0){ if(priv->image_path != NULL){ g_free(priv->image_path); } @@ -194,7 +194,7 @@ static void update_album_art(MetadataWidget* self){ MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self); GdkPixbuf* pixbuf; pixbuf = gdk_pixbuf_new_from_file(priv->image_path, NULL); - pixbuf = gdk_pixbuf_scale_simple(pixbuf,60, 60,GDK_INTERP_BILINEAR); + pixbuf = gdk_pixbuf_scale_simple(pixbuf,60, 60, GDK_INTERP_BILINEAR); g_debug("attempting to set the image with path %s", priv->image_path); gtk_image_set_from_pixbuf(GTK_IMAGE(priv->album_art), pixbuf); g_object_unref(pixbuf); diff --git a/src/mpris-controller.c b/src/mpris-controller.c index 594cdf2..075a475 100644 --- a/src/mpris-controller.c +++ b/src/mpris-controller.c @@ -28,6 +28,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <stdlib.h> #include <string.h> #include <gee.h> +#include <libdbusmenu-glib/client.h> +#include <libdbusmenu-glib/menuitem-proxy.h> +#include <libdbusmenu-glib/menuitem.h> +#include <libdbusmenu-glib/server.h> #define TYPE_MPRIS_CONTROLLER (mpris_controller_get_type ()) @@ -57,6 +61,27 @@ typedef struct _PlayerControllerClass PlayerControllerClass; #define MPRIS_CONTROLLER_TYPE_STATUS (mpris_controller_status_get_type ()) typedef struct _MprisControllerstatus MprisControllerstatus; +typedef struct _PlayerControllerPrivate PlayerControllerPrivate; + +#define TYPE_PLAYER_ITEM (player_item_get_type ()) +#define PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_ITEM, PlayerItem)) +#define PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_ITEM, PlayerItemClass)) +#define IS_PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_ITEM)) +#define IS_PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_ITEM)) +#define PLAYER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_ITEM, PlayerItemClass)) + +typedef struct _PlayerItem PlayerItem; +typedef struct _PlayerItemClass PlayerItemClass; + +#define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) +#define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) +#define TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) +#define IS_TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TRANSPORT_MENUITEM)) +#define IS_TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TRANSPORT_MENUITEM)) +#define TRANSPORT_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) + +typedef struct _TransportMenuitem TransportMenuitem; +typedef struct _TransportMenuitemClass TransportMenuitemClass; #define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL))) struct _MprisController { @@ -81,6 +106,16 @@ struct _MprisControllerstatus { gint32 endless; }; +struct _PlayerController { + GObject parent_instance; + PlayerControllerPrivate * priv; + GeeArrayList* custom_items; +}; + +struct _PlayerControllerClass { + GObjectClass parent_class; +}; + static gpointer mpris_controller_parent_class = NULL; @@ -99,15 +134,22 @@ static void mpris_controller_status_free (MprisControllerstatus* self); static void mpris_controller_onStatusChange (MprisController* self, DBusGProxy* mpris_client, MprisControllerstatus* st); static void _mpris_controller_onStatusChange_dynamic_StatusChange2_ (DBusGProxy* _sender, MprisControllerstatus* st, gpointer self); void _dynamic_StatusChange3_connect (gpointer obj, const char * signal_name, GCallback handler, gpointer data); -void player_controller_update_playing_info (PlayerController* self, GeeHashMap* data); -GeeHashMap* mpris_controller_get_track_data (MprisController* self); +static void _dynamic_GetStatus0 (DBusGProxy* self, MprisControllerstatus* result, GError** error); +GType player_item_get_type (void); +#define PLAYER_CONTROLLER_TRANSPORT 3 +GType transport_menuitem_get_type (void); +void transport_menuitem_change_play_state (TransportMenuitem* self, gint state); +static GHashTable* _dynamic_GetMetadata1 (DBusGProxy* self, GError** error); +#define PLAYER_CONTROLLER_METADATA 2 +void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes); +GeeHashSet* metadata_menuitem_attributes_format (void); MprisController* mpris_controller_new (const char* name, PlayerController* controller, const char* mpris_interface); MprisController* mpris_controller_construct (GType object_type, const char* name, PlayerController* controller, const char* mpris_interface); -static GHashTable* _dynamic_GetMetadata0 (DBusGProxy* self, GError** error); -static GeeHashMap* mpris_controller_format_metadata (GHashTable* data); -static void _dynamic_Play1 (DBusGProxy* self, GError** error); -static void _dynamic_Pause2 (DBusGProxy* self, GError** error); +static void _dynamic_Play2 (DBusGProxy* self, GError** error); +static void _dynamic_Pause3 (DBusGProxy* self, GError** error); void mpris_controller_toggle_playback (MprisController* self, gboolean state); +static GValue* _g_value_dup (GValue* self); +GeeHashSet* transport_menuitem_attributes_format (void); static void mpris_controller_finalize (GObject* obj); @@ -142,6 +184,29 @@ void _dynamic_StatusChange3_connect (gpointer obj, const char * signal_name, GCa } +static void _dynamic_GetStatus0 (DBusGProxy* self, MprisControllerstatus* result, GError** error) { + GValueArray* dbus_result; + dbus_g_proxy_call (self, "GetStatus", error, G_TYPE_INVALID, dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID), &dbus_result, G_TYPE_INVALID); + if (*error) { + return; + } + result->playback = g_value_get_int (&dbus_result->values[0]); + result->shuffle = g_value_get_int (&dbus_result->values[1]); + result->repeat = g_value_get_int (&dbus_result->values[2]); + result->endless = g_value_get_int (&dbus_result->values[3]); +} + + +static GHashTable* _dynamic_GetMetadata1 (DBusGProxy* self, GError** error) { + GHashTable* result; + dbus_g_proxy_call (self, "GetMetadata", error, G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &result, G_TYPE_INVALID); + if (*error) { + return NULL; + } + return result; +} + + MprisController* mpris_controller_construct (GType object_type, const char* name, PlayerController* controller, const char* mpris_interface) { GError * _inner_error_; MprisController * self; @@ -149,7 +214,15 @@ MprisController* mpris_controller_construct (GType object_type, const char* name DBusGProxy* _tmp5_; char* _tmp4_; char* _tmp3_; - GeeHashMap* _tmp6_; + MprisControllerstatus _tmp6_ = {0}; + MprisControllerstatus st; + gint play_state; + TransportMenuitem* _tmp8_; + PlayerItem* _tmp7_; + GHashTable* _tmp9_; + GeeHashSet* _tmp12_; + GHashTable* _tmp11_; + PlayerItem* _tmp10_; g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (controller != NULL, NULL); g_return_val_if_fail (mpris_interface != NULL, NULL); @@ -160,22 +233,22 @@ MprisController* mpris_controller_construct (GType object_type, const char* name DBusGConnection* _tmp1_; _tmp0_ = dbus_g_bus_get (DBUS_BUS_SESSION, &_inner_error_); if (_inner_error_ != NULL) { - goto __catch0_g_error; + goto __catch1_g_error; } self->priv->connection = (_tmp1_ = _tmp0_, _dbus_g_connection_unref0 (self->priv->connection), _tmp1_); } - goto __finally0; - __catch0_g_error: + goto __finally1; + __catch1_g_error: { GError * e; e = _inner_error_; _inner_error_ = NULL; { - g_error ("mpris-controller.vala:41: Problems connecting to the session bus - %s", e->message); + g_error ("mpris-controller.vala:39: Problems connecting to the session bus - %s", e->message); _g_error_free0 (e); } } - __finally0: + __finally1: if (_inner_error_ != NULL) { g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); g_clear_error (&_inner_error_); @@ -187,57 +260,49 @@ MprisController* mpris_controller_construct (GType object_type, const char* name _g_free0 (_tmp3_); _dynamic_TrackChange1_connect (self->mpris_player, "TrackChange", (GCallback) _mpris_controller_onTrackChange_dynamic_TrackChange0_, self); _dynamic_StatusChange3_connect (self->mpris_player, "StatusChange", (GCallback) _mpris_controller_onStatusChange_dynamic_StatusChange2_, self); - player_controller_update_playing_info (self->priv->controller, _tmp6_ = mpris_controller_get_track_data (self)); - _g_object_unref0 (_tmp6_); - return self; -} - - -MprisController* mpris_controller_new (const char* name, PlayerController* controller, const char* mpris_interface) { - return mpris_controller_construct (TYPE_MPRIS_CONTROLLER, name, controller, mpris_interface); -} - - -static GHashTable* _dynamic_GetMetadata0 (DBusGProxy* self, GError** error) { - GHashTable* result; - dbus_g_proxy_call (self, "GetMetadata", error, G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &result, G_TYPE_INVALID); - if (*error) { + st = (_dynamic_GetStatus0 (self->mpris_player, &_tmp6_, &_inner_error_), _tmp6_); + if (_inner_error_ != NULL) { + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); return NULL; } - return result; -} - - -GeeHashMap* mpris_controller_get_track_data (MprisController* self) { - GeeHashMap* result = NULL; - GError * _inner_error_; - GHashTable* _tmp0_; - GHashTable* _tmp1_; - GeeHashMap* _tmp2_; - g_return_val_if_fail (self != NULL, NULL); - _inner_error_ = NULL; - _tmp0_ = _dynamic_GetMetadata0 (self->mpris_player, &_inner_error_); + play_state = (gint) st.playback; + g_debug ("mpris-controller.vala:48: GetStatusChange - play state %i", play_state); + transport_menuitem_change_play_state (_tmp8_ = (_tmp7_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->controller->custom_items, PLAYER_CONTROLLER_TRANSPORT), IS_TRANSPORT_MENUITEM (_tmp7_) ? ((TransportMenuitem*) _tmp7_) : NULL), play_state); + _g_object_unref0 (_tmp8_); + _tmp9_ = _dynamic_GetMetadata1 (self->mpris_player, &_inner_error_); if (_inner_error_ != NULL) { g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); g_clear_error (&_inner_error_); return NULL; } - result = (_tmp2_ = mpris_controller_format_metadata (_tmp1_ = _tmp0_), _g_hash_table_unref0 (_tmp1_), _tmp2_); - return result; + player_item_update (_tmp10_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->controller->custom_items, PLAYER_CONTROLLER_METADATA), _tmp11_ = _tmp9_, _tmp12_ = metadata_menuitem_attributes_format ()); + _g_object_unref0 (_tmp12_); + _g_hash_table_unref0 (_tmp11_); + _g_object_unref0 (_tmp10_); + return self; +} + + +MprisController* mpris_controller_new (const char* name, PlayerController* controller, const char* mpris_interface) { + return mpris_controller_construct (TYPE_MPRIS_CONTROLLER, name, controller, mpris_interface); } static void mpris_controller_onTrackChange (MprisController* self, DBusGProxy* mpris_client, GHashTable* ht) { - GeeHashMap* _tmp0_; + GeeHashSet* _tmp1_; + PlayerItem* _tmp0_; g_return_if_fail (self != NULL); g_return_if_fail (mpris_client != NULL); g_return_if_fail (ht != NULL); - player_controller_update_playing_info (self->priv->controller, _tmp0_ = mpris_controller_format_metadata (ht)); + g_debug ("mpris-controller.vala:58: onTrackChange"); + player_item_update (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->controller->custom_items, PLAYER_CONTROLLER_METADATA), ht, _tmp1_ = metadata_menuitem_attributes_format ()); + _g_object_unref0 (_tmp1_); _g_object_unref0 (_tmp0_); } -static void _dynamic_Play1 (DBusGProxy* self, GError** error) { +static void _dynamic_Play2 (DBusGProxy* self, GError** error) { dbus_g_proxy_call (self, "Play", error, G_TYPE_INVALID, G_TYPE_INVALID); if (*error) { return; @@ -245,7 +310,7 @@ static void _dynamic_Play1 (DBusGProxy* self, GError** error) { } -static void _dynamic_Pause2 (DBusGProxy* self, GError** error) { +static void _dynamic_Pause3 (DBusGProxy* self, GError** error) { dbus_g_proxy_call (self, "Pause", error, G_TYPE_INVALID, G_TYPE_INVALID); if (*error) { return; @@ -258,16 +323,16 @@ void mpris_controller_toggle_playback (MprisController* self, gboolean state) { g_return_if_fail (self != NULL); _inner_error_ = NULL; if (state == TRUE) { - g_debug ("mpris-controller.vala:67: about to play"); - _dynamic_Play1 (self->mpris_player, &_inner_error_); + g_debug ("mpris-controller.vala:70: about to play"); + _dynamic_Play2 (self->mpris_player, &_inner_error_); if (_inner_error_ != NULL) { g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); g_clear_error (&_inner_error_); return; } } else { - g_debug ("mpris-controller.vala:71: about to pause"); - _dynamic_Pause2 (self->mpris_player, &_inner_error_); + g_debug ("mpris-controller.vala:74: about to pause"); + _dynamic_Pause3 (self->mpris_player, &_inner_error_); if (_inner_error_ != NULL) { g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); g_clear_error (&_inner_error_); @@ -277,25 +342,40 @@ void mpris_controller_toggle_playback (MprisController* self, gboolean state) { } -static void mpris_controller_onStatusChange (MprisController* self, DBusGProxy* mpris_client, MprisControllerstatus* st) { - g_return_if_fail (self != NULL); - g_return_if_fail (mpris_client != NULL); - g_debug ("mpris-controller.vala:78: onStatusChange - signal received"); +static GValue* _g_value_dup (GValue* self) { + return g_boxed_copy (G_TYPE_VALUE, self); } -static GeeHashMap* mpris_controller_format_metadata (GHashTable* data) { - GeeHashMap* result = NULL; - GeeHashMap* results; - g_return_val_if_fail (data != NULL, NULL); - results = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, NULL, NULL, NULL); - g_debug ("mpris-controller.vala:93: format_metadata - title = %s", g_value_get_string ((GValue*) g_hash_table_lookup (data, "title"))); - gee_abstract_map_set ((GeeAbstractMap*) results, "title", g_value_get_string ((GValue*) g_hash_table_lookup (data, "title"))); - gee_abstract_map_set ((GeeAbstractMap*) results, "artist", g_value_get_string ((GValue*) g_hash_table_lookup (data, "artist"))); - gee_abstract_map_set ((GeeAbstractMap*) results, "album", g_value_get_string ((GValue*) g_hash_table_lookup (data, "album"))); - gee_abstract_map_set ((GeeAbstractMap*) results, "arturl", g_value_get_string ((GValue*) g_hash_table_lookup (data, "arturl"))); - result = results; - return result; +static gpointer __g_value_dup0 (gpointer self) { + return self ? _g_value_dup (self) : NULL; +} + + +static void mpris_controller_onStatusChange (MprisController* self, DBusGProxy* mpris_client, MprisControllerstatus* st) { + MprisControllerstatus* status; + GValueArray* ar; + gint play_state; + GHashTable* ht; + GValue v = {0}; + GeeHashSet* _tmp1_; + PlayerItem* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (mpris_client != NULL); + g_debug ("mpris-controller.vala:81: onStatusChange - signal received"); + status = st; + ar = (GValueArray*) status; + play_state = g_value_get_int (g_value_array_get_nth (ar, (guint) 0)); + g_debug ("mpris-controller.vala:85: onStatusChange - play state %i", play_state); + ht = g_hash_table_new (g_str_hash, g_str_equal); + g_value_init (&v, G_TYPE_INT); + g_value_set_int (&v, play_state); + g_hash_table_insert (ht, g_strdup ("state"), __g_value_dup0 (&v)); + player_item_update (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->controller->custom_items, PLAYER_CONTROLLER_TRANSPORT), ht, _tmp1_ = transport_menuitem_attributes_format ()); + _g_object_unref0 (_tmp1_); + _g_object_unref0 (_tmp0_); + _g_hash_table_unref0 (ht); + G_IS_VALUE (&v) ? (g_value_unset (&v), NULL) : NULL; } diff --git a/src/mpris-controller.vala b/src/mpris-controller.vala index 7e65594..a6d27be 100644 --- a/src/mpris-controller.vala +++ b/src/mpris-controller.vala @@ -20,7 +20,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>. using Gee; - public class MprisController : GLib.Object { private DBus.Connection connection; @@ -33,7 +32,6 @@ public class MprisController : GLib.Object public int32 endless; } - public MprisController(string name, PlayerController controller, string mpris_interface="org.freedesktop.MediaPlayer"){ try { this.connection = DBus.Bus.get (DBus.BusType.SESSION); @@ -43,18 +41,23 @@ public class MprisController : GLib.Object this.controller = controller; this.mpris_player = this.connection.get_object ("org.mpris.".concat(name.down()) , "/Player", mpris_interface); this.mpris_player.TrackChange += onTrackChange; - this.mpris_player.StatusChange += onStatusChange; - this.controller.update_playing_info(get_track_data()); - } + this.mpris_player.StatusChange += onStatusChange; - public HashMap<string, string> get_track_data() - { - return format_metadata(this.mpris_player.GetMetadata()); + status st = this.mpris_player.GetStatus(); + int play_state = st.playback; + debug("GetStatusChange - play state %i", play_state); + (this.controller.custom_items[this.controller.TRANSPORT] as TransportMenuitem).change_play_state(play_state); + this.controller.custom_items[this.controller.METADATA].update(this.mpris_player.GetMetadata(), + MetadataMenuitem.attributes_format()); + } + private void onTrackChange(dynamic DBus.Object mpris_client, HashTable<string,Value?> ht) { - this.controller.update_playing_info(format_metadata(ht)); + debug("onTrackChange"); + this.controller.custom_items[this.controller.METADATA].update(ht, + MetadataMenuitem.attributes_format()); } /** @@ -76,26 +79,16 @@ public class MprisController : GLib.Object private void onStatusChange(dynamic DBus.Object mpris_client, status st) { debug("onStatusChange - signal received"); - //ValueArray a = new ValueArray(4); - //Value v = new Value(typeof(int32)); - //v.set_int(st.playback); - //a.append(v); - //debug("onStatusChange - play %i", a.get_nth(0).get_int()); - //int playback = (ValueArray)st.get_nth(0).get_int(); - //int shuffle = ar.get_nth(1).get_int(); - //int repeat = ar.get_nth(2).get_int(); - //int endless = ar.get_nth(3).get_int(); + status* status = &st; + unowned ValueArray ar = (ValueArray)status; + int play_state = ar.get_nth(0).get_int(); + debug("onStatusChange - play state %i", play_state); + HashTable<string, Value?> ht = new HashTable<string, Value?>(str_hash, str_equal); + Value v = Value(typeof(int)); + v.set_int(play_state); + ht.insert("state", v); + this.controller.custom_items[this.controller.TRANSPORT].update(ht, TransportMenuitem.attributes_format()); } - private static HashMap<string, string> format_metadata(HashTable<string,Value?> data) - { - HashMap<string,string> results = new HashMap<string, string>(); - debug("format_metadata - title = %s", (string)data.lookup("title")); - results.set("title", (string)data.lookup("title")); - results.set("artist", (string)data.lookup("artist")); - results.set("album", (string)data.lookup("album")); - results.set("arturl", (string)data.lookup("arturl")); - return results; - } } diff --git a/src/music-player-bridge.c b/src/music-player-bridge.c index c08a1e7..250f761 100644 --- a/src/music-player-bridge.c +++ b/src/music-player-bridge.c @@ -2,7 +2,6 @@ * generated from music-player-bridge.vala, do not modify */ /* -This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel. Copyright 2010 Canonical Ltd. Authors: @@ -35,6 +34,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <gee.h> #include <stdlib.h> #include <string.h> +#include <gio/gdesktopappinfo.h> +#include <gio/gio.h> #define TYPE_MUSIC_PLAYER_BRIDGE (music_player_bridge_get_type ()) @@ -57,8 +58,19 @@ typedef struct _MusicPlayerBridgePrivate MusicPlayerBridgePrivate; typedef struct _PlayerController PlayerController; typedef struct _PlayerControllerClass PlayerControllerClass; + +#define TYPE_FAMILIAR_PLAYERS_DB (familiar_players_db_get_type ()) +#define FAMILIAR_PLAYERS_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDB)) +#define FAMILIAR_PLAYERS_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDBClass)) +#define IS_FAMILIAR_PLAYERS_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_FAMILIAR_PLAYERS_DB)) +#define IS_FAMILIAR_PLAYERS_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_FAMILIAR_PLAYERS_DB)) +#define FAMILIAR_PLAYERS_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDBClass)) + +typedef struct _FamiliarPlayersDB FamiliarPlayersDB; +typedef struct _FamiliarPlayersDBClass FamiliarPlayersDBClass; #define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) #define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) struct _MusicPlayerBridge { GObject parent_instance; @@ -73,6 +85,7 @@ struct _MusicPlayerBridgePrivate { IndicateListener* listener; DbusmenuMenuitem* root_menu; GeeHashMap* registered_clients; + FamiliarPlayersDB* playersDB; }; @@ -80,10 +93,13 @@ static gpointer music_player_bridge_parent_class = NULL; GType music_player_bridge_get_type (void); GType player_controller_get_type (void); +GType familiar_players_db_get_type (void); #define MUSIC_PLAYER_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_MUSIC_PLAYER_BRIDGE, MusicPlayerBridgePrivate)) enum { MUSIC_PLAYER_BRIDGE_DUMMY_PROPERTY }; +FamiliarPlayersDB* familiar_players_db_new (void); +FamiliarPlayersDB* familiar_players_db_construct (GType object_type); void music_player_bridge_on_indicator_added (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0); static void _music_player_bridge_on_indicator_added_indicate_listener_indicator_added (IndicateListener* _sender, IndicateListenerServer* object, IndicateListenerIndicator* p0, gpointer self); void music_player_bridge_on_indicator_removed (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0); @@ -98,11 +114,15 @@ void music_player_bridge_on_server_count_changed (MusicPlayerBridge* self, Indic static void _music_player_bridge_on_server_count_changed_indicate_listener_server_count_changed (IndicateListener* _sender, IndicateListenerServer* object, guint p0, gpointer self); MusicPlayerBridge* music_player_bridge_new (void); MusicPlayerBridge* music_player_bridge_construct (GType object_type); -void music_player_bridge_set_root_menu_item (MusicPlayerBridge* self, DbusmenuMenuitem* menu); -static gboolean music_player_bridge_server_is_not_of_interest (MusicPlayerBridge* self, const char* type); +GeeSet* familiar_players_db_records (FamiliarPlayersDB* self); PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* client_name, gboolean active); PlayerController* player_controller_construct (GType object_type, DbusmenuMenuitem* root, const char* client_name, gboolean active); +static void music_player_bridge_try_to_add_inactive_familiar_clients (MusicPlayerBridge* self); +static gboolean music_player_bridge_server_is_not_of_interest (MusicPlayerBridge* self, const char* type); +static void music_player_bridge_desktop_info_callback (MusicPlayerBridge* self, IndicateListenerServer* server, char* path, void* data); void player_controller_vanish (PlayerController* self); +void familiar_players_db_insert (FamiliarPlayersDB* self, const char* desktop); +void music_player_bridge_set_root_menu_item (MusicPlayerBridge* self, DbusmenuMenuitem* menu); static void music_player_bridge_finalize (GObject* obj); 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); @@ -142,11 +162,13 @@ static void _music_player_bridge_on_server_count_changed_indicate_listener_serve MusicPlayerBridge* music_player_bridge_construct (GType object_type) { MusicPlayerBridge * self; - GeeHashMap* _tmp0_; - IndicateListener* _tmp1_; + FamiliarPlayersDB* _tmp0_; + GeeHashMap* _tmp1_; + IndicateListener* _tmp2_; self = (MusicPlayerBridge*) g_object_new (object_type, NULL); - self->priv->registered_clients = (_tmp0_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, TYPE_PLAYER_CONTROLLER, (GBoxedCopyFunc) g_object_ref, g_object_unref, NULL, NULL, NULL), _g_object_unref0 (self->priv->registered_clients), _tmp0_); - self->priv->listener = (_tmp1_ = indicate_listener_ref_default (), _g_object_unref0 (self->priv->listener), _tmp1_); + self->priv->playersDB = (_tmp0_ = familiar_players_db_new (), _g_object_unref0 (self->priv->playersDB), _tmp0_); + self->priv->registered_clients = (_tmp1_ = gee_hash_map_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, TYPE_PLAYER_CONTROLLER, (GBoxedCopyFunc) g_object_ref, g_object_unref, NULL, NULL, NULL), _g_object_unref0 (self->priv->registered_clients), _tmp1_); + self->priv->listener = (_tmp2_ = indicate_listener_ref_default (), _g_object_unref0 (self->priv->listener), _tmp2_); g_signal_connect_object (self->priv->listener, "indicator-added", (GCallback) _music_player_bridge_on_indicator_added_indicate_listener_indicator_added, self, 0); g_signal_connect_object (self->priv->listener, "indicator-removed", (GCallback) _music_player_bridge_on_indicator_removed_indicate_listener_indicator_removed, self, 0); g_signal_connect_object (self->priv->listener, "indicator-modified", (GCallback) _music_player_bridge_on_indicator_modified_indicate_listener_indicator_modified, self, 0); @@ -162,36 +184,81 @@ MusicPlayerBridge* music_player_bridge_new (void) { } -static gpointer _g_object_ref0 (gpointer self) { - return self ? g_object_ref (self) : NULL; -} - - -void music_player_bridge_set_root_menu_item (MusicPlayerBridge* self, DbusmenuMenuitem* menu) { - DbusmenuMenuitem* _tmp0_; - g_return_if_fail (self != NULL); - g_return_if_fail (menu != NULL); - self->priv->root_menu = (_tmp0_ = _g_object_ref0 (menu), _g_object_unref0 (self->priv->root_menu), _tmp0_); -} - - -void music_player_bridge_on_indicator_added (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0) { +static void music_player_bridge_try_to_add_inactive_familiar_clients (MusicPlayerBridge* self) { + GError * _inner_error_; + gint count; g_return_if_fail (self != NULL); - g_debug ("music-player-bridge.vala:51: MusicPlayerBridge-> on_indicator_added"); -} - - -void music_player_bridge_on_indicator_removed (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0) { - g_return_if_fail (self != NULL); - g_debug ("music-player-bridge.vala:56: MusicPlayerBridge -> on_indicator_removed"); -} - - -void music_player_bridge_on_indicator_modified (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0, const char* s) { - g_return_if_fail (self != NULL); - g_return_if_fail (s != NULL); - g_debug ("music-player-bridge.vala:61: MusicPlayerBridge -> indicator_modified w" \ -"ith vale %s", s); + _inner_error_ = NULL; + count = 0; + { + GeeSet* _tmp0_; + GeeIterator* _tmp1_; + GeeIterator* _app_it; + _app_it = (_tmp1_ = gee_iterable_iterator ((GeeIterable*) (_tmp0_ = familiar_players_db_records (self->priv->playersDB))), _g_object_unref0 (_tmp0_), _tmp1_); + while (TRUE) { + char* app; + if (!gee_iterator_next (_app_it)) { + break; + } + app = (char*) gee_iterator_get (_app_it); + if (count == 0) { + char** _tmp3_; + gint _bits_size_; + gint bits_length1; + char** _tmp2_; + char** bits; + g_debug ("music-player-bridge.vala:51: we have found %s", app); + bits = (_tmp3_ = _tmp2_ = g_strsplit (app, "/", 0), bits_length1 = _vala_array_length (_tmp2_), _bits_size_ = bits_length1, _tmp3_); + { + gint _tmp5__length1; + char** _tmp5_; + char** _tmp4_; + char* _tmp6_; + char* app_name; + PlayerController* ctrl; + GDesktopAppInfo* info; + char* desc; + app_name = (_tmp6_ = g_strdup ((_tmp5_ = _tmp4_ = g_strsplit (bits[bits_length1 - 1], ".", 0), _tmp5__length1 = _vala_array_length (_tmp4_), _tmp5_)[0]), _tmp5_ = (_vala_array_free (_tmp5_, _tmp5__length1, (GDestroyNotify) g_free), NULL), _tmp6_); + g_debug ("music-player-bridge.vala:56: we have found %s", app_name); + ctrl = player_controller_new (self->priv->root_menu, app_name, FALSE); + gee_abstract_map_set ((GeeAbstractMap*) self->priv->registered_clients, app_name, ctrl); + info = g_desktop_app_info_new_from_filename (app_name); + desc = g_strdup (g_app_info_get_display_name ((GAppInfo*) info)); + g_debug ("music-player-bridge.vala:63: description from app %s", desc); + count = count + 1; + _g_free0 (app_name); + _g_object_unref0 (ctrl); + _g_object_unref0 (info); + _g_free0 (desc); + } + goto __finally0; + __catch0_g_error: + { + GError * er; + er = _inner_error_; + _inner_error_ = NULL; + { + g_warning ("music-player-bridge.vala:67: desktop path in cache is not formatted as" \ +" we have anticipated"); + _g_error_free0 (er); + } + } + __finally0: + if (_inner_error_ != NULL) { + bits = (_vala_array_free (bits, bits_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (app); + _g_object_unref0 (_app_it); + g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return; + } + bits = (_vala_array_free (bits, bits_length1, (GDestroyNotify) g_free), NULL); + } + _g_free0 (app); + break; + } + _g_object_unref0 (_app_it); + } } @@ -204,7 +271,7 @@ void music_player_bridge_on_server_added (MusicPlayerBridge* self, IndicateListe gboolean _tmp3_ = FALSE; g_return_if_fail (self != NULL); g_return_if_fail (type != NULL); - g_debug ("music-player-bridge.vala:66: MusicPlayerBridge -> on_server_added with" \ + g_debug ("music-player-bridge.vala:76: MusicPlayerBridge -> on_server_added with" \ " value %s", type); if (music_player_bridge_server_is_not_of_interest (self, type)) { return; @@ -216,10 +283,13 @@ void music_player_bridge_on_server_added (MusicPlayerBridge* self, IndicateListe _tmp3_ = FALSE; } if (_tmp3_) { + indicate_listener_get_server_property_cb cb; PlayerController* ctrl; + cb = (indicate_listener_get_server_property_cb) music_player_bridge_desktop_info_callback; + indicate_listener_server_get_desktop (self->priv->listener, object, cb, self); ctrl = player_controller_new (self->priv->root_menu, client_name, TRUE); gee_abstract_map_set ((GeeAbstractMap*) self->priv->registered_clients, client_name, ctrl); - g_debug ("music-player-bridge.vala:72: client of name %s has successfully regist" \ + g_debug ("music-player-bridge.vala:84: client of name %s has successfully regist" \ "ered with us", client_name); _g_object_unref0 (ctrl); } @@ -236,7 +306,7 @@ void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateLis gboolean _tmp3_ = FALSE; g_return_if_fail (self != NULL); g_return_if_fail (type != NULL); - g_debug ("music-player-bridge.vala:78: MusicPlayerBridge -> on_server_removed wi" \ + g_debug ("music-player-bridge.vala:90: MusicPlayerBridge -> on_server_removed wi" \ "th value %s", type); if (music_player_bridge_server_is_not_of_interest (self, type)) { return; @@ -252,7 +322,7 @@ void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateLis player_controller_vanish (_tmp4_ = (PlayerController*) gee_abstract_map_get ((GeeAbstractMap*) self->priv->registered_clients, client_name)); _g_object_unref0 (_tmp4_); gee_map_remove ((GeeMap*) self->priv->registered_clients, client_name, NULL); - g_debug ("music-player-bridge.vala:84: Successively removed menu_item for client" \ + g_debug ("music-player-bridge.vala:96: Successively removed menu_item for client" \ " %s from registered_clients", client_name); } _g_free0 (client_name); @@ -277,8 +347,8 @@ static gboolean music_player_bridge_server_is_not_of_interest (MusicPlayerBridge return result; } if (string_contains (type, "music") == FALSE) { - g_debug ("music-player-bridge.vala:91: server is of no interest, it is not an m" \ -"usic server"); + g_debug ("music-player-bridge.vala:103: server is of no interest, it is not an " \ +"music server"); result = TRUE; return result; } @@ -287,10 +357,57 @@ static gboolean music_player_bridge_server_is_not_of_interest (MusicPlayerBridge } +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +static void music_player_bridge_desktop_info_callback (MusicPlayerBridge* self, IndicateListenerServer* server, char* path, void* data) { + void* _tmp0_; + MusicPlayerBridge* bridge; + g_return_if_fail (self != NULL); + g_return_if_fail (path != NULL); + g_debug ("music-player-bridge.vala:112: we got a desktop file path hopefully: %s", path); + bridge = _g_object_ref0 ((_tmp0_ = data, IS_MUSIC_PLAYER_BRIDGE (_tmp0_) ? ((MusicPlayerBridge*) _tmp0_) : NULL)); + familiar_players_db_insert (bridge->priv->playersDB, path); + _g_object_unref0 (bridge); + _g_free0 (path); +} + + +void music_player_bridge_set_root_menu_item (MusicPlayerBridge* self, DbusmenuMenuitem* menu) { + DbusmenuMenuitem* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (menu != NULL); + self->priv->root_menu = (_tmp0_ = _g_object_ref0 (menu), _g_object_unref0 (self->priv->root_menu), _tmp0_); +} + + void music_player_bridge_on_server_count_changed (MusicPlayerBridge* self, IndicateListenerServer* object, guint i) { g_return_if_fail (self != NULL); - g_debug ("music-player-bridge.vala:99: MusicPlayerBridge-> on_server_count_chang" \ -"ed with value %u", i); + g_debug ("music-player-bridge.vala:125: MusicPlayerBridge-> on_server_count_chan" \ +"ged with value %u", i); +} + + +void music_player_bridge_on_indicator_added (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0) { + g_return_if_fail (self != NULL); + g_debug ("music-player-bridge.vala:129: MusicPlayerBridge-> on_indicator_added"); +} + + +void music_player_bridge_on_indicator_removed (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0) { + g_return_if_fail (self != NULL); + g_debug ("music-player-bridge.vala:134: MusicPlayerBridge -> on_indicator_remove" \ +"d"); +} + + +void music_player_bridge_on_indicator_modified (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0, const char* s) { + g_return_if_fail (self != NULL); + g_return_if_fail (s != NULL); + g_debug ("music-player-bridge.vala:139: MusicPlayerBridge -> indicator_modified " \ +"with vale %s", s); } @@ -312,6 +429,7 @@ static void music_player_bridge_finalize (GObject* obj) { _g_object_unref0 (self->priv->listener); _g_object_unref0 (self->priv->root_menu); _g_object_unref0 (self->priv->registered_clients); + _g_object_unref0 (self->priv->playersDB); G_OBJECT_CLASS (music_player_bridge_parent_class)->finalize (obj); } diff --git a/src/music-player-bridge.h b/src/music-player-bridge.h index 6a31b30..fd680c1 100644 --- a/src/music-player-bridge.h +++ b/src/music-player-bridge.h @@ -6,10 +6,6 @@ #include <glib.h> #include <glib-object.h> -#include <libdbusmenu-glib/client.h> -#include <libdbusmenu-glib/menuitem-proxy.h> -#include <libdbusmenu-glib/menuitem.h> -#include <libdbusmenu-glib/server.h> #include <libindicate/./indicator-messages.h> #include <libindicate/./indicator.h> #include <libindicate/./interests.h> @@ -17,6 +13,10 @@ #include <libindicate/./server.h> #include <stdlib.h> #include <string.h> +#include <libdbusmenu-glib/client.h> +#include <libdbusmenu-glib/menuitem-proxy.h> +#include <libdbusmenu-glib/menuitem.h> +#include <libdbusmenu-glib/server.h> #include <gee.h> #include <dbus/dbus-glib-lowlevel.h> #include <dbus/dbus-glib.h> @@ -35,16 +35,16 @@ typedef struct _MusicPlayerBridge MusicPlayerBridge; typedef struct _MusicPlayerBridgeClass MusicPlayerBridgeClass; typedef struct _MusicPlayerBridgePrivate MusicPlayerBridgePrivate; -#define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) -#define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) -#define TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) -#define IS_TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TRANSPORT_MENUITEM)) -#define IS_TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TRANSPORT_MENUITEM)) -#define TRANSPORT_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) +#define TYPE_PLAYER_ITEM (player_item_get_type ()) +#define PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_ITEM, PlayerItem)) +#define PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_ITEM, PlayerItemClass)) +#define IS_PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_ITEM)) +#define IS_PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_ITEM)) +#define PLAYER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_ITEM, PlayerItemClass)) -typedef struct _TransportMenuitem TransportMenuitem; -typedef struct _TransportMenuitemClass TransportMenuitemClass; -typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate; +typedef struct _PlayerItem PlayerItem; +typedef struct _PlayerItemClass PlayerItemClass; +typedef struct _PlayerItemPrivate PlayerItemPrivate; #define TYPE_MPRIS_CONTROLLER (mpris_controller_get_type ()) #define MPRIS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER, MprisController)) @@ -56,6 +56,17 @@ typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate; typedef struct _MprisController MprisController; typedef struct _MprisControllerClass MprisControllerClass; +#define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) +#define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) +#define TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) +#define IS_TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TRANSPORT_MENUITEM)) +#define IS_TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TRANSPORT_MENUITEM)) +#define TRANSPORT_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) + +typedef struct _TransportMenuitem TransportMenuitem; +typedef struct _TransportMenuitemClass TransportMenuitemClass; +typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate; + #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)) @@ -90,6 +101,17 @@ typedef struct _MprisControllerV2 MprisControllerV2; typedef struct _MprisControllerV2Class MprisControllerV2Class; typedef struct _MprisControllerV2Private MprisControllerV2Private; +#define TYPE_FAMILIAR_PLAYERS_DB (familiar_players_db_get_type ()) +#define FAMILIAR_PLAYERS_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDB)) +#define FAMILIAR_PLAYERS_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDBClass)) +#define IS_FAMILIAR_PLAYERS_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_FAMILIAR_PLAYERS_DB)) +#define IS_FAMILIAR_PLAYERS_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_FAMILIAR_PLAYERS_DB)) +#define FAMILIAR_PLAYERS_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_FAMILIAR_PLAYERS_DB, FamiliarPlayersDBClass)) + +typedef struct _FamiliarPlayersDB FamiliarPlayersDB; +typedef struct _FamiliarPlayersDBClass FamiliarPlayersDBClass; +typedef struct _FamiliarPlayersDBPrivate FamiliarPlayersDBPrivate; + struct _MusicPlayerBridge { GObject parent_instance; MusicPlayerBridgePrivate * priv; @@ -99,27 +121,39 @@ struct _MusicPlayerBridgeClass { GObjectClass parent_class; }; -struct _TransportMenuitem { +struct _PlayerItem { DbusmenuMenuitem parent_instance; + PlayerItemPrivate * priv; + MprisController* mpris_adaptor; +}; + +struct _PlayerItemClass { + DbusmenuMenuitemClass parent_class; + void (*check_layout) (PlayerItem* self); +}; + +struct _TransportMenuitem { + PlayerItem parent_instance; TransportMenuitemPrivate * priv; }; struct _TransportMenuitemClass { - DbusmenuMenuitemClass parent_class; + PlayerItemClass parent_class; }; struct _MetadataMenuitem { - DbusmenuMenuitem parent_instance; + PlayerItem parent_instance; MetadataMenuitemPrivate * priv; }; struct _MetadataMenuitemClass { - DbusmenuMenuitemClass parent_class; + PlayerItemClass parent_class; }; struct _PlayerController { GObject parent_instance; PlayerControllerPrivate * priv; + GeeArrayList* custom_items; }; struct _PlayerControllerClass { @@ -145,39 +179,63 @@ struct _MprisControllerV2Class { MprisControllerClass parent_class; }; +struct _FamiliarPlayersDB { + GObject parent_instance; + FamiliarPlayersDBPrivate * priv; +}; + +struct _FamiliarPlayersDBClass { + GObjectClass parent_class; +}; + GType music_player_bridge_get_type (void); MusicPlayerBridge* music_player_bridge_new (void); MusicPlayerBridge* music_player_bridge_construct (GType object_type); +void music_player_bridge_on_server_added (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type); +void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type); void music_player_bridge_set_root_menu_item (MusicPlayerBridge* self, DbusmenuMenuitem* menu); +void music_player_bridge_on_server_count_changed (MusicPlayerBridge* self, IndicateListenerServer* object, guint i); void music_player_bridge_on_indicator_added (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0); void music_player_bridge_on_indicator_removed (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0); void music_player_bridge_on_indicator_modified (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0, const char* s); -void music_player_bridge_on_server_added (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type); -void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type); -void music_player_bridge_on_server_count_changed (MusicPlayerBridge* self, IndicateListenerServer* object, guint i); +GType player_item_get_type (void); +GType mpris_controller_get_type (void); GType transport_menuitem_get_type (void); TransportMenuitem* transport_menuitem_new (void); TransportMenuitem* transport_menuitem_construct (GType object_type); -GType mpris_controller_get_type (void); -void transport_menuitem_set_adaptor (TransportMenuitem* self, MprisController* adaptor); +void transport_menuitem_change_play_state (TransportMenuitem* self, gint state); +GeeHashSet* transport_menuitem_attributes_format (void); GType metadata_menuitem_get_type (void); MetadataMenuitem* metadata_menuitem_new (void); MetadataMenuitem* metadata_menuitem_construct (GType object_type); -void metadata_menuitem_update (MetadataMenuitem* self, GeeHashMap* data); -char* metadata_menuitem_sanitize_image_path (const char* path); +GeeHashSet* metadata_menuitem_attributes_format (void); +gboolean metadata_menuitem_populated (MetadataMenuitem* self); GType player_controller_get_type (void); +#define PLAYER_CONTROLLER_METADATA 2 PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* client_name, gboolean active); PlayerController* player_controller_construct (GType object_type, DbusmenuMenuitem* root, const char* client_name, gboolean active); void player_controller_vanish (PlayerController* self); -void player_controller_update_playing_info (PlayerController* self, GeeHashMap* data); GType mpris_controller_v2_get_type (void); MprisControllerV2* mpris_controller_v2_new (const char* name, PlayerController* controller); MprisControllerV2* mpris_controller_v2_construct (GType object_type, const char* name, PlayerController* controller); MprisController* mpris_controller_new (const char* name, PlayerController* controller, const char* mpris_interface); MprisController* mpris_controller_construct (GType object_type, const char* name, PlayerController* controller, const char* mpris_interface); -GeeHashMap* mpris_controller_get_track_data (MprisController* self); void mpris_controller_toggle_playback (MprisController* self, gboolean state); +PlayerItem* player_item_new (void); +PlayerItem* player_item_construct (GType object_type); +void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes); +void player_item_set_adaptor (PlayerItem* self, MprisController* adaptor); +char* player_item_sanitize_string (const char* st); +PlayerItem* player_item_new_title_item (const char* name); +PlayerItem* player_item_new_separator_item (void); +void player_item_check_layout (PlayerItem* self); +GType familiar_players_db_get_type (void); +FamiliarPlayersDB* familiar_players_db_new (void); +FamiliarPlayersDB* familiar_players_db_construct (GType object_type); +void familiar_players_db_insert (FamiliarPlayersDB* self, const char* desktop); +gboolean familiar_players_db_already_familiar (FamiliarPlayersDB* self, const char* desktop); +GeeSet* familiar_players_db_records (FamiliarPlayersDB* self); G_END_DECLS diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala index b03ecbd..6fc9032 100644 --- a/src/music-player-bridge.vala +++ b/src/music-player-bridge.vala @@ -1,5 +1,4 @@ /* -This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel. Copyright 2010 Canonical Ltd. Authors: @@ -21,6 +20,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. using Indicate; using Dbusmenu; using Gee; +using GLib; public class MusicPlayerBridge : GLib.Object { @@ -28,9 +28,11 @@ public class MusicPlayerBridge : GLib.Object private Listener listener; private Dbusmenu.Menuitem root_menu; private HashMap<string, PlayerController> registered_clients; + private FamiliarPlayersDB playersDB; public MusicPlayerBridge() { + playersDB = new FamiliarPlayersDB(); registered_clients = new HashMap<string, PlayerController> (); listener = Listener.ref_default(); listener.indicator_added.connect(on_indicator_added); @@ -40,33 +42,43 @@ public class MusicPlayerBridge : GLib.Object listener.server_removed.connect(on_server_removed); listener.server_count_changed.connect(on_server_count_changed); } - - public void set_root_menu_item(Dbusmenu.Menuitem menu) - { - root_menu = menu; - } - - public void on_indicator_added(Indicate.ListenerServer object, Indicate.ListenerIndicator p0) - { - debug("MusicPlayerBridge-> on_indicator_added"); - } - - public void on_indicator_removed(Indicate.ListenerServer object, Indicate.ListenerIndicator p0) - { - debug("MusicPlayerBridge -> on_indicator_removed"); - } - - public void on_indicator_modified(Indicate.ListenerServer object, Indicate.ListenerIndicator p0, string s) - { - debug("MusicPlayerBridge -> indicator_modified with vale %s", s ); - } - - public void on_server_added(Indicate.ListenerServer object, string type) + // Alpha 2 not in use ... yet. + private void try_to_add_inactive_familiar_clients(){ + // for now just use one of the entries. + int count = 0; + foreach(string app in this.playersDB.records()){ + if(count == 0){ + debug("we have found %s", app); + string[] bits = app.split("/"); + + try{ + string app_name = bits[bits.length -1].split(".")[0]; + debug("we have found %s", app_name); + PlayerController ctrl = new PlayerController(this.root_menu, + app_name, + false); + this.registered_clients.set(app_name, ctrl); + DesktopAppInfo info = new DesktopAppInfo.from_filename(app_name); + string desc = info.get_display_name(); + debug("description from app %s", desc); + count += 1; + } + catch(Error er){ + warning("desktop path in cache is not formatted as we have anticipated"); + } + } + break; + } + } + + public void on_server_added(Indicate.ListenerServer object, string type) { debug("MusicPlayerBridge -> on_server_added with value %s", type); if(server_is_not_of_interest(type)) return; - string client_name = type.split(".")[1]; + string client_name = type.split(".")[1]; if (root_menu != null && client_name != null){ + listener_get_server_property_cb cb = (listener_get_server_property_cb)desktop_info_callback; + this.listener.server_get_desktop(object, cb, this); PlayerController ctrl = new PlayerController(root_menu, client_name, true); registered_clients.set(client_name, ctrl); debug("client of name %s has successfully registered with us", client_name); @@ -94,10 +106,38 @@ public class MusicPlayerBridge : GLib.Object return false; } - public void on_server_count_changed(Indicate.ListenerServer object, uint i) + private void desktop_info_callback(Indicate.ListenerServer server, + owned string path, void* data) + { + debug("we got a desktop file path hopefully: %s", path); + MusicPlayerBridge bridge = data as MusicPlayerBridge; + bridge.playersDB.insert(path); + } + + public void set_root_menu_item(Dbusmenu.Menuitem menu) + { + this.root_menu = menu; + //try_to_add_inactive_familiar_clients(); + } + + public void on_server_count_changed(Indicate.ListenerServer object, uint i) { debug("MusicPlayerBridge-> on_server_count_changed with value %u", i); } + public void on_indicator_added(Indicate.ListenerServer object, Indicate.ListenerIndicator p0) + { + debug("MusicPlayerBridge-> on_indicator_added"); + } + + public void on_indicator_removed(Indicate.ListenerServer object, Indicate.ListenerIndicator p0) + { + debug("MusicPlayerBridge -> on_indicator_removed"); + } + + public void on_indicator_modified(Indicate.ListenerServer object, Indicate.ListenerIndicator p0, string s) + { + debug("MusicPlayerBridge -> indicator_modified with vale %s", s ); + } } diff --git a/src/player-controller.c b/src/player-controller.c index 7c37346..5c4e0cc 100644 --- a/src/player-controller.c +++ b/src/player-controller.c @@ -23,13 +23,13 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <glib.h> #include <glib-object.h> +#include <gee.h> #include <libdbusmenu-glib/client.h> #include <libdbusmenu-glib/menuitem-proxy.h> #include <libdbusmenu-glib/menuitem.h> #include <libdbusmenu-glib/server.h> #include <stdlib.h> #include <string.h> -#include <gee.h> #define TYPE_PLAYER_CONTROLLER (player_controller_get_type ()) @@ -43,6 +43,16 @@ typedef struct _PlayerController PlayerController; typedef struct _PlayerControllerClass PlayerControllerClass; typedef struct _PlayerControllerPrivate PlayerControllerPrivate; +#define TYPE_PLAYER_ITEM (player_item_get_type ()) +#define PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_ITEM, PlayerItem)) +#define PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_ITEM, PlayerItemClass)) +#define IS_PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_ITEM)) +#define IS_PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_ITEM)) +#define PLAYER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_ITEM, PlayerItemClass)) + +typedef struct _PlayerItem PlayerItem; +typedef struct _PlayerItemClass PlayerItemClass; + #define TYPE_MPRIS_CONTROLLER (mpris_controller_get_type ()) #define MPRIS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER, MprisController)) #define MPRIS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MPRIS_CONTROLLER, MprisControllerClass)) @@ -65,16 +75,6 @@ typedef struct _MprisControllerClass MprisControllerClass; typedef struct _MprisControllerV2 MprisControllerV2; typedef struct _MprisControllerV2Class MprisControllerV2Class; -#define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) -#define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) -#define TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) -#define IS_TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TRANSPORT_MENUITEM)) -#define IS_TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TRANSPORT_MENUITEM)) -#define TRANSPORT_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) - -typedef struct _TransportMenuitem TransportMenuitem; -typedef struct _TransportMenuitemClass TransportMenuitemClass; - #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)) @@ -85,9 +85,20 @@ typedef struct _TransportMenuitemClass TransportMenuitemClass; typedef struct _MetadataMenuitem MetadataMenuitem; typedef struct _MetadataMenuitemClass MetadataMenuitemClass; +#define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) +#define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) +#define TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) +#define IS_TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TRANSPORT_MENUITEM)) +#define IS_TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TRANSPORT_MENUITEM)) +#define TRANSPORT_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) + +typedef struct _TransportMenuitem TransportMenuitem; +typedef struct _TransportMenuitemClass TransportMenuitemClass; + struct _PlayerController { GObject parent_instance; PlayerControllerPrivate * priv; + GeeArrayList* custom_items; }; struct _PlayerControllerClass { @@ -98,14 +109,15 @@ struct _PlayerControllerPrivate { DbusmenuMenuitem* root_menu; char* name; gboolean is_active; - GeeArrayList* custom_items; MprisController* mpris_adaptor; + char* desktop_path; }; static gpointer player_controller_parent_class = NULL; GType player_controller_get_type (void); +GType player_item_get_type (void); GType mpris_controller_get_type (void); #define PLAYER_CONTROLLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PLAYER_CONTROLLER, PlayerControllerPrivate)) enum { @@ -120,18 +132,18 @@ MprisControllerV2* mpris_controller_v2_construct (GType object_type, const char* GType mpris_controller_v2_get_type (void); MprisController* mpris_controller_new (const char* name, PlayerController* controller, const char* mpris_interface); MprisController* mpris_controller_construct (GType object_type, const char* name, PlayerController* controller, const char* mpris_interface); -GType transport_menuitem_get_type (void); -void transport_menuitem_set_adaptor (TransportMenuitem* self, MprisController* adaptor); +void player_item_set_adaptor (PlayerItem* self, MprisController* adaptor); PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* client_name, gboolean active); PlayerController* player_controller_construct (GType object_type, DbusmenuMenuitem* root, const char* client_name, gboolean active); void player_controller_vanish (PlayerController* self); +PlayerItem* player_item_new_separator_item (void); +PlayerItem* player_item_new_title_item (const char* name); MetadataMenuitem* metadata_menuitem_new (void); MetadataMenuitem* metadata_menuitem_construct (GType object_type); GType metadata_menuitem_get_type (void); TransportMenuitem* transport_menuitem_new (void); TransportMenuitem* transport_menuitem_construct (GType object_type); -void metadata_menuitem_update (MetadataMenuitem* self, GeeHashMap* data); -void player_controller_update_playing_info (PlayerController* self, GeeHashMap* data); +GType transport_menuitem_get_type (void); static void player_controller_finalize (GObject* obj); static int _vala_strcmp0 (const char * str1, const char * str2); @@ -159,7 +171,7 @@ PlayerController* player_controller_construct (GType object_type, DbusmenuMenuit char* _tmp2_; char* _tmp1_; GeeArrayList* _tmp3_; - TransportMenuitem* t; + PlayerItem* _tmp6_; g_return_val_if_fail (root != NULL, NULL); g_return_val_if_fail (client_name != NULL, NULL); self = (PlayerController*) g_object_new (object_type, NULL); @@ -167,7 +179,7 @@ PlayerController* player_controller_construct (GType object_type, DbusmenuMenuit self->priv->name = (_tmp2_ = player_controller_format_client_name (_tmp1_ = string_strip (client_name)), _g_free0 (self->priv->name), _tmp2_); _g_free0 (_tmp1_); self->priv->is_active = active; - self->priv->custom_items = (_tmp3_ = gee_array_list_new (DBUSMENU_TYPE_MENUITEM, (GBoxedCopyFunc) g_object_ref, g_object_unref, NULL), _g_object_unref0 (self->priv->custom_items), _tmp3_); + self->custom_items = (_tmp3_ = gee_array_list_new (TYPE_PLAYER_ITEM, (GBoxedCopyFunc) g_object_ref, g_object_unref, NULL), _g_object_unref0 (self->custom_items), _tmp3_); player_controller_self_construct (self); if (_vala_strcmp0 (self->priv->name, "Vlc") == 0) { MprisController* _tmp4_; @@ -176,9 +188,8 @@ PlayerController* player_controller_construct (GType object_type, DbusmenuMenuit MprisController* _tmp5_; self->priv->mpris_adaptor = (_tmp5_ = mpris_controller_new (self->priv->name, self, "org.freedesktop.MediaPlayer"), _g_object_unref0 (self->priv->mpris_adaptor), _tmp5_); } - t = TRANSPORT_MENUITEM ((DbusmenuMenuitem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->custom_items, PLAYER_CONTROLLER_TRANSPORT)); - transport_menuitem_set_adaptor (t, self->priv->mpris_adaptor); - _g_object_unref0 (t); + player_item_set_adaptor (_tmp6_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, PLAYER_CONTROLLER_TRANSPORT), self->priv->mpris_adaptor); + _g_object_unref0 (_tmp6_); return self; } @@ -192,13 +203,13 @@ void player_controller_vanish (PlayerController* self) { g_return_if_fail (self != NULL); { GeeIterator* _item_it; - _item_it = gee_abstract_collection_iterator ((GeeAbstractCollection*) self->priv->custom_items); + _item_it = gee_abstract_collection_iterator ((GeeAbstractCollection*) self->custom_items); while (TRUE) { DbusmenuMenuitem* item; if (!gee_iterator_next (_item_it)) { break; } - item = (DbusmenuMenuitem*) gee_iterator_get (_item_it); + item = (DbusmenuMenuitem*) ((PlayerItem*) gee_iterator_get (_item_it)); dbusmenu_menuitem_child_delete (self->priv->root_menu, item); _g_object_unref0 (item); } @@ -209,58 +220,42 @@ void player_controller_vanish (PlayerController* self) { static gboolean player_controller_self_construct (PlayerController* self) { gboolean result = FALSE; - DbusmenuMenuitem* separator_item; - DbusmenuMenuitem* title_item; + PlayerItem* _tmp0_; + PlayerItem* _tmp1_; MetadataMenuitem* metadata_item; TransportMenuitem* transport_item; gint offset; g_return_val_if_fail (self != NULL, FALSE); - separator_item = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (separator_item, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - gee_abstract_collection_add ((GeeAbstractCollection*) self->priv->custom_items, separator_item); - title_item = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (title_item, DBUSMENU_MENUITEM_PROP_LABEL, self->priv->name); - dbusmenu_menuitem_property_set (title_item, DBUSMENU_MENUITEM_PROP_ICON_NAME, "applications-multimedia"); - gee_abstract_collection_add ((GeeAbstractCollection*) self->priv->custom_items, title_item); + gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, _tmp0_ = player_item_new_separator_item ()); + _g_object_unref0 (_tmp0_); + gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, _tmp1_ = player_item_new_title_item (self->priv->name)); + _g_object_unref0 (_tmp1_); metadata_item = metadata_menuitem_new (); - gee_abstract_collection_add ((GeeAbstractCollection*) self->priv->custom_items, (DbusmenuMenuitem*) metadata_item); + gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, (PlayerItem*) metadata_item); transport_item = transport_menuitem_new (); - gee_abstract_collection_add ((GeeAbstractCollection*) self->priv->custom_items, (DbusmenuMenuitem*) transport_item); + gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, (PlayerItem*) transport_item); offset = 2; { GeeIterator* _item_it; - _item_it = gee_abstract_collection_iterator ((GeeAbstractCollection*) self->priv->custom_items); + _item_it = gee_abstract_collection_iterator ((GeeAbstractCollection*) self->custom_items); while (TRUE) { - DbusmenuMenuitem* item; + PlayerItem* item; if (!gee_iterator_next (_item_it)) { break; } - item = (DbusmenuMenuitem*) gee_iterator_get (_item_it); - dbusmenu_menuitem_child_add_position (self->priv->root_menu, item, (guint) (offset + gee_abstract_list_index_of ((GeeAbstractList*) self->priv->custom_items, item))); + item = (PlayerItem*) gee_iterator_get (_item_it); + dbusmenu_menuitem_child_add_position (self->priv->root_menu, (DbusmenuMenuitem*) item, (guint) (offset + gee_abstract_list_index_of ((GeeAbstractList*) self->custom_items, item))); _g_object_unref0 (item); } _g_object_unref0 (_item_it); } result = TRUE; - _g_object_unref0 (separator_item); - _g_object_unref0 (title_item); _g_object_unref0 (metadata_item); _g_object_unref0 (transport_item); return result; } -void player_controller_update_playing_info (PlayerController* self, GeeHashMap* data) { - MetadataMenuitem* item; - g_return_if_fail (self != NULL); - g_return_if_fail (data != NULL); - g_debug ("player-controller.vala:95: PlayerController - update_playing_info"); - item = METADATA_MENUITEM ((DbusmenuMenuitem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->custom_items, PLAYER_CONTROLLER_METADATA)); - metadata_menuitem_update (item, data); - _g_object_unref0 (item); -} - - static char* string_slice (const char* self, glong start, glong end) { char* result = NULL; glong string_length; @@ -306,8 +301,7 @@ static char* player_controller_format_client_name (const char* client_name) { formatted = (_tmp2_ = g_strconcat (_tmp0_ = g_utf8_strup (client_name, (gssize) 1), _tmp1_ = string_slice (client_name, (glong) 1, g_utf8_strlen (client_name, -1)), NULL), _g_free0 (formatted), _tmp2_); _g_free0 (_tmp1_); _g_free0 (_tmp0_); - g_debug ("player-controller.vala:105: PlayerController->format_client_name - : %" \ -"s", formatted); + g_debug ("player-controller.vala:93: PlayerController->format_client_name - : %s", formatted); } result = formatted; return result; @@ -331,8 +325,9 @@ static void player_controller_finalize (GObject* obj) { self = PLAYER_CONTROLLER (obj); _g_object_unref0 (self->priv->root_menu); _g_free0 (self->priv->name); - _g_object_unref0 (self->priv->custom_items); + _g_object_unref0 (self->custom_items); _g_object_unref0 (self->priv->mpris_adaptor); + _g_free0 (self->priv->desktop_path); G_OBJECT_CLASS (player_controller_parent_class)->finalize (obj); } diff --git a/src/player-controller.vala b/src/player-controller.vala index aa72cac..0d8dc01 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -23,21 +23,22 @@ using Gee; public class PlayerController : GLib.Object { - private const int METADATA = 2; + public const int METADATA = 2; private const int TRANSPORT = 3; private Dbusmenu.Menuitem root_menu; private string name; private bool is_active; - private ArrayList<Dbusmenu.Menuitem> custom_items; + public ArrayList<PlayerItem> custom_items; private MprisController mpris_adaptor; - + private string desktop_path; + public PlayerController(Dbusmenu.Menuitem root, string client_name, bool active) { this.root_menu = root; this.name = format_client_name(client_name.strip()); this.is_active = active; - this.custom_items = new ArrayList<Dbusmenu.Menuitem>(); + this.custom_items = new ArrayList<PlayerItem>(); self_construct(); // Temporary scenario to handle both v1 and v2 of MPRIS. @@ -47,12 +48,11 @@ public class PlayerController : GLib.Object else{ this.mpris_adaptor = new MprisController(this.name, this); } + this.custom_items[TRANSPORT].set_adaptor(this.mpris_adaptor); - // TODO subclass dbusmenuMenuitem to something like a playermenuitem - // and use this type to collectively - // control widgets. - TransportMenuitem t = (TransportMenuitem)this.custom_items[TRANSPORT]; - t.set_adaptor(this.mpris_adaptor); + // At start up if there is no metadata then hide the item. + // TODO: NOT working -> dbus menu bug ? + //((MetadataMenuitem)this.custom_items[METADATA]).check_layout(); } public void vanish() @@ -65,15 +65,10 @@ public class PlayerController : GLib.Object private bool self_construct() { // Separator item - Dbusmenu.Menuitem separator_item = new Dbusmenu.Menuitem(); - separator_item.property_set(MENUITEM_PROP_TYPE, CLIENT_TYPES_SEPARATOR); - this.custom_items.add(separator_item); + this.custom_items.add(PlayerItem.new_separator_item()); // Title item - Dbusmenu.Menuitem title_item = new Dbusmenu.Menuitem(); - title_item.property_set(MENUITEM_PROP_LABEL, this.name); - title_item.property_set(MENUITEM_PROP_ICON_NAME, "applications-multimedia"); - this.custom_items.add(title_item); + this.custom_items.add(PlayerItem.new_title_item(this.name)); // Metadata item MetadataMenuitem metadata_item = new MetadataMenuitem(); @@ -84,19 +79,12 @@ public class PlayerController : GLib.Object this.custom_items.add(transport_item); int offset = 2; - foreach(Dbusmenu.Menuitem item in this.custom_items){ + foreach(PlayerItem item in this.custom_items){ root_menu.child_add_position(item, offset + this.custom_items.index_of(item)); } return true; } - public void update_playing_info(HashMap<string, string> data) - { - debug("PlayerController - update_playing_info"); - MetadataMenuitem item = (MetadataMenuitem)this.custom_items[METADATA]; - item.update(data); - } - private static string format_client_name(string client_name) { string formatted = client_name; diff --git a/src/player-item.c b/src/player-item.c new file mode 100644 index 0000000..806be04 --- /dev/null +++ b/src/player-item.c @@ -0,0 +1,348 @@ +/* player-item.c generated by valac, the Vala compiler + * generated from player-item.vala, do not modify */ + +/* +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 <glib.h> +#include <glib-object.h> +#include <libdbusmenu-glib/client.h> +#include <libdbusmenu-glib/menuitem-proxy.h> +#include <libdbusmenu-glib/menuitem.h> +#include <libdbusmenu-glib/server.h> +#include <stdlib.h> +#include <string.h> +#include <gee.h> + + +#define TYPE_PLAYER_ITEM (player_item_get_type ()) +#define PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_ITEM, PlayerItem)) +#define PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_ITEM, PlayerItemClass)) +#define IS_PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_ITEM)) +#define IS_PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_ITEM)) +#define PLAYER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_ITEM, PlayerItemClass)) + +typedef struct _PlayerItem PlayerItem; +typedef struct _PlayerItemClass PlayerItemClass; +typedef struct _PlayerItemPrivate PlayerItemPrivate; + +#define TYPE_MPRIS_CONTROLLER (mpris_controller_get_type ()) +#define MPRIS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER, MprisController)) +#define MPRIS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MPRIS_CONTROLLER, MprisControllerClass)) +#define IS_MPRIS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MPRIS_CONTROLLER)) +#define IS_MPRIS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MPRIS_CONTROLLER)) +#define MPRIS_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MPRIS_CONTROLLER, MprisControllerClass)) + +typedef struct _MprisController MprisController; +typedef struct _MprisControllerClass MprisControllerClass; +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_free0(var) (var = (g_free (var), NULL)) + +struct _PlayerItem { + DbusmenuMenuitem parent_instance; + PlayerItemPrivate * priv; + MprisController* mpris_adaptor; +}; + +struct _PlayerItemClass { + DbusmenuMenuitemClass parent_class; + void (*check_layout) (PlayerItem* self); +}; + + +static gpointer player_item_parent_class = NULL; + +GType player_item_get_type (void); +GType mpris_controller_get_type (void); +enum { + PLAYER_ITEM_DUMMY_PROPERTY +}; +PlayerItem* player_item_new (void); +PlayerItem* player_item_construct (GType object_type); +static gboolean player_item_ensure_valid_updates (GHashTable* data, GeeHashSet* attributes); +char* player_item_sanitize_string (const char* st); +void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes); +void player_item_set_adaptor (PlayerItem* self, MprisController* adaptor); +PlayerItem* player_item_new_title_item (const char* name); +PlayerItem* player_item_new_separator_item (void); +void player_item_check_layout (PlayerItem* self); +static void player_item_real_check_layout (PlayerItem* self); +static void player_item_finalize (GObject* obj); +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); +static gint _vala_array_length (gpointer array); + + + +PlayerItem* player_item_construct (GType object_type) { + PlayerItem * self; + self = g_object_newv (object_type, 0, NULL); + return self; +} + + +PlayerItem* player_item_new (void) { + return player_item_construct (TYPE_PLAYER_ITEM); +} + + +void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes) { + g_return_if_fail (self != NULL); + g_return_if_fail (data != NULL); + g_return_if_fail (attributes != NULL); + g_debug ("player-item.vala:33: PlayerItem::update()"); + if (player_item_ensure_valid_updates (data, attributes) == FALSE) { + g_debug ("player-item.vala:35: PlayerItem::Update -> The hashtable update does n" \ +"ot contain what we were expecting - just leave it!"); + return; + } + { + GeeIterator* _property_it; + _property_it = gee_abstract_collection_iterator ((GeeAbstractCollection*) attributes); + while (TRUE) { + char* property; + char** _tmp1_; + gint _input_keys_size_; + gint input_keys_length1; + char** _tmp0_; + char** input_keys; + char** _tmp3_ = NULL; + gint _tmp2_; + char* search_key; + GValue _tmp4_ = {0}; + GValue v; + if (!gee_iterator_next (_property_it)) { + break; + } + property = (char*) gee_iterator_get (_property_it); + input_keys = (_tmp1_ = _tmp0_ = g_strsplit (property, "-", 0), input_keys_length1 = _vala_array_length (_tmp0_), _input_keys_size_ = input_keys_length1, _tmp1_); + search_key = g_strdup ((_tmp3_ = input_keys + (input_keys_length1 - 1), _tmp2_ = input_keys_length1 - (input_keys_length1 - 1), _tmp3_)[0]); + g_debug ("player-item.vala:41: search key = %s", search_key); + v = G_IS_VALUE ((GValue*) g_hash_table_lookup (data, search_key)) ? (g_value_init (&_tmp4_, G_VALUE_TYPE ((GValue*) g_hash_table_lookup (data, search_key))), g_value_copy ((GValue*) g_hash_table_lookup (data, search_key), &_tmp4_), _tmp4_) : (*((GValue*) g_hash_table_lookup (data, search_key))); + if (G_VALUE_HOLDS (&v, G_TYPE_STRING)) { + char* _tmp5_; + g_debug ("player-item.vala:44: with value : %s", g_value_get_string (&v)); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, property, _tmp5_ = player_item_sanitize_string (g_value_get_string (&v))); + _g_free0 (_tmp5_); + } else { + if (G_VALUE_HOLDS (&v, G_TYPE_INT)) { + g_debug ("player-item.vala:48: with value : %i", g_value_get_int (&v)); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, property, g_value_get_int (&v)); + } else { + if (G_VALUE_HOLDS (&v, G_TYPE_BOOLEAN)) { + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, property, g_value_get_boolean (&v)); + } + } + } + _g_free0 (property); + input_keys = (_vala_array_free (input_keys, input_keys_length1, (GDestroyNotify) g_free), NULL); + _g_free0 (search_key); + G_IS_VALUE (&v) ? (g_value_unset (&v), NULL) : NULL; + } + _g_object_unref0 (_property_it); + } +} + + +static gpointer _g_object_ref0 (gpointer self) { + return self ? g_object_ref (self) : NULL; +} + + +void player_item_set_adaptor (PlayerItem* self, MprisController* adaptor) { + MprisController* _tmp0_; + g_return_if_fail (self != NULL); + g_return_if_fail (adaptor != NULL); + self->mpris_adaptor = (_tmp0_ = _g_object_ref0 (adaptor), _g_object_unref0 (self->mpris_adaptor), _tmp0_); +} + + +static gboolean player_item_ensure_valid_updates (GHashTable* data, GeeHashSet* attributes) { + gboolean result = FALSE; + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (attributes != NULL, FALSE); + if (data == NULL) { + result = FALSE; + return result; + } + if (g_hash_table_size (data) < gee_collection_get_size ((GeeCollection*) attributes)) { + g_warning ("player-item.vala:70: update hash was too small for the target"); + result = FALSE; + return result; + } + result = TRUE; + return result; +} + + +static char* string_strip (const char* self) { + char* result = NULL; + char* _result_; + g_return_val_if_fail (self != NULL, NULL); + _result_ = g_strdup (self); + g_strstrip (_result_); + result = _result_; + return result; +} + + +static char* string_slice (const char* self, glong start, glong end) { + char* result = NULL; + glong string_length; + gboolean _tmp0_ = FALSE; + gboolean _tmp1_ = FALSE; + const char* start_string; + g_return_val_if_fail (self != NULL, NULL); + string_length = g_utf8_strlen (self, -1); + if (start < 0) { + start = string_length + start; + } + if (end < 0) { + end = string_length + end; + } + if (start >= 0) { + _tmp0_ = start <= string_length; + } else { + _tmp0_ = FALSE; + } + g_return_val_if_fail (_tmp0_, NULL); + if (end >= 0) { + _tmp1_ = end <= string_length; + } else { + _tmp1_ = FALSE; + } + g_return_val_if_fail (_tmp1_, NULL); + g_return_val_if_fail (start <= end, NULL); + start_string = g_utf8_offset_to_pointer (self, start); + result = g_strndup (start_string, ((gchar*) g_utf8_offset_to_pointer (start_string, end - start)) - ((gchar*) start_string)); + return result; +} + + +char* player_item_sanitize_string (const char* st) { + char* result = NULL; + char* _result_; + g_return_val_if_fail (st != NULL, NULL); + _result_ = string_strip (st); + if (g_str_has_prefix (_result_, "file:///")) { + char* _tmp0_; + _result_ = (_tmp0_ = string_slice (_result_, (glong) 7, g_utf8_strlen (_result_, -1)), _g_free0 (_result_), _tmp0_); + } + g_debug ("player-item.vala:82: Sanitize string - result = %s", _result_); + result = _result_; + return result; +} + + +PlayerItem* player_item_new_title_item (const char* name) { + PlayerItem* result = NULL; + PlayerItem* item; + g_return_val_if_fail (name != NULL, NULL); + item = player_item_new (); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) item, DBUSMENU_MENUITEM_PROP_LABEL, name); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) item, DBUSMENU_MENUITEM_PROP_ICON_NAME, "applications-multimedia"); + result = item; + return result; +} + + +PlayerItem* player_item_new_separator_item (void) { + PlayerItem* result = NULL; + PlayerItem* separator; + separator = player_item_new (); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + result = separator; + return result; +} + + +static void player_item_real_check_layout (PlayerItem* self) { + g_return_if_fail (self != NULL); + g_warning ("player-item.vala:106: this should not be hit"); +} + + +void player_item_check_layout (PlayerItem* self) { + PLAYER_ITEM_GET_CLASS (self)->check_layout (self); +} + + +static void player_item_class_init (PlayerItemClass * klass) { + player_item_parent_class = g_type_class_peek_parent (klass); + PLAYER_ITEM_CLASS (klass)->check_layout = player_item_real_check_layout; + G_OBJECT_CLASS (klass)->finalize = player_item_finalize; +} + + +static void player_item_instance_init (PlayerItem * self) { +} + + +static void player_item_finalize (GObject* obj) { + PlayerItem * self; + self = PLAYER_ITEM (obj); + _g_object_unref0 (self->mpris_adaptor); + G_OBJECT_CLASS (player_item_parent_class)->finalize (obj); +} + + +GType player_item_get_type (void) { + static volatile gsize player_item_type_id__volatile = 0; + if (g_once_init_enter (&player_item_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (PlayerItemClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) player_item_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PlayerItem), 0, (GInstanceInitFunc) player_item_instance_init, NULL }; + GType player_item_type_id; + player_item_type_id = g_type_register_static (DBUSMENU_TYPE_MENUITEM, "PlayerItem", &g_define_type_info, 0); + g_once_init_leave (&player_item_type_id__volatile, player_item_type_id); + } + return player_item_type_id__volatile; +} + + +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { + if ((array != NULL) && (destroy_func != NULL)) { + int i; + for (i = 0; i < array_length; i = i + 1) { + if (((gpointer*) array)[i] != NULL) { + destroy_func (((gpointer*) array)[i]); + } + } + } +} + + +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { + _vala_array_destroy (array, array_length, destroy_func); + g_free (array); +} + + +static gint _vala_array_length (gpointer array) { + int length; + length = 0; + if (array) { + while (((gpointer*) array)[length]) { + length++; + } + } + return length; +} + + + + diff --git a/src/player-item.vala b/src/player-item.vala new file mode 100644 index 0000000..7fcf912 --- /dev/null +++ b/src/player-item.vala @@ -0,0 +1,109 @@ +/* +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/>. +*/ + +using Dbusmenu; +using Gee; + +public class PlayerItem : Dbusmenu.Menuitem +{ + public MprisController mpris_adaptor; + + public PlayerItem() + { + } + + public void update(HashTable<string, Value?> data, HashSet<string> attributes) + { + debug("PlayerItem::update()"); + if(ensure_valid_updates(data, attributes) == false){ + debug("PlayerItem::Update -> The hashtable update does not contain what we were expecting - 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); + Value v = data.lookup(search_key); + if (v.holds (typeof (string))){ + debug("with value : %s", v.get_string()); + this.property_set(property, this.sanitize_string(v.get_string())); + } + else if (v.holds (typeof (int))){ + debug("with value : %i", v.get_int()); + this.property_set_int(property, v.get_int()); + } + else if(v.holds (typeof (bool))){ + this.property_set_bool(property, v.get_boolean()); + } + } + // TODO: not working + //this.check_layout(); + } + + public void set_adaptor(MprisController adaptor) + { + this.mpris_adaptor = adaptor; + } + + private static bool ensure_valid_updates(HashTable<string, Value?> data, HashSet<string> attributes) + { + if(data == null){ + return false; + } + if(data.size() < attributes.size){ + warning("update hash was too small for the target"); + return false; + } + return true; + } + + public static string sanitize_string(string st) + { + string result = st.strip(); + if(result.has_prefix("file:///")){ + result = result.slice(7, result.len()); + } + debug("Sanitize string - result = %s", result); + return result; + } + + + //----- Custom constructors for player items ----------------// + // Title item + public static PlayerItem new_title_item(dynamic string name) + { + PlayerItem item = new PlayerItem(); + item.property_set(MENUITEM_PROP_LABEL, name); + item.property_set(MENUITEM_PROP_ICON_NAME, "applications-multimedia"); + return item; + } + + // Separator item + public static PlayerItem new_separator_item() + { + PlayerItem separator = new PlayerItem(); + separator.property_set(MENUITEM_PROP_TYPE, CLIENT_TYPES_SEPARATOR); + return separator; + } + + public virtual void check_layout(){ + warning("this should not be hit"); + } +} + diff --git a/src/pulse-manager.c b/src/pulse-manager.c index 7323797..a9a47e4 100644 --- a/src/pulse-manager.c +++ b/src/pulse-manager.c @@ -50,7 +50,7 @@ static pa_cvolume construct_mono_volume(const pa_cvolume* vol); /** Future Refactoring notes - - Push all UI updates out through update PA state in the service. + - Push all UI updates out through update PA state in the service. - Collapse 3 update_sink_info into one. The essentially do the same thing from different contexts. **/ @@ -59,18 +59,18 @@ 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), "ayatana.indicator.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); - dbus_menu_manager_update_pa_state(FALSE, FALSE, FALSE, 0); - pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); + 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), "ayatana.indicator.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); + dbus_menu_manager_update_pa_state(FALSE, FALSE, FALSE, 0); + pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); } /** @@ -79,7 +79,7 @@ Needed for testing - bah! **/ pa_context* get_context() { - return pulse_context; + return pulse_context; } /** @@ -88,44 +88,44 @@ 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");*/ + 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");*/ } -/** +/** reconnect_to_pulse() In the event of Pulseaudio flapping in the wind handle gracefully without memory leaks ! */ static void reconnect_to_pulse() { - // reset - if (pulse_context != NULL){ - g_debug("freeing the pulse context"); - pa_context_unref(pulse_context); - pulse_context = NULL; - } - - if(sink_hash != NULL){ - g_hash_table_destroy(sink_hash); - sink_hash = NULL; - } - - // reconnect - pulse_context = pa_context_new(pa_glib_mainloop_get_api(pa_main_loop), "ayatana.indicator.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); - dbus_menu_manager_update_pa_state(FALSE, FALSE, FALSE, 0); - pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); + // reset + if (pulse_context != NULL) { + g_debug("freeing the pulse context"); + pa_context_unref(pulse_context); + pulse_context = NULL; + } + + if (sink_hash != NULL) { + g_hash_table_destroy(sink_hash); + sink_hash = NULL; + } + + // reconnect + pulse_context = pa_context_new(pa_glib_mainloop_get_api(pa_main_loop), "ayatana.indicator.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); + dbus_menu_manager_update_pa_state(FALSE, FALSE, FALSE, 0); + pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOFAIL, NULL); } /** @@ -134,9 +134,9 @@ 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); + sink_info *sink = (sink_info*)value; + g_free(sink->name); + g_free(sink); } /* @@ -144,125 +144,122 @@ 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 rebust 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; + // 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 rebust 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; } static 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; + 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");*/ + /* 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_sink_input_while_muted (dbus_service, TRUE); - } - else{ - sound_service_dbus_sink_input_while_muted(dbus_service, FALSE); - } + if (default_sink_is_muted(sink_index) == TRUE) { + sound_service_dbus_sink_input_while_muted (dbus_service, TRUE); + } 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; + 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_sink_volume(dbus_service, get_default_sink_volume()); - } - -/* g_debug("in the pulse manager: mute each sink %i", GPOINTER_TO_INT(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_sink_volume(dbus_service, get_default_sink_volume()); + } + + /* g_debug("in the pulse manager: mute each sink %i", GPOINTER_TO_INT(user_data));*/ } 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);*/ + 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. +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; - } + 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)); + 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)); + 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; -} + 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 @@ -270,24 +267,22 @@ static pa_cvolume construct_mono_volume(const pa_cvolume* vol) 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 *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; + } + 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);*/ + /* g_debug("Context Success Callback - result = %i", success);*/ } /** @@ -298,296 +293,270 @@ 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) - { - dbus_menu_manager_update_pa_state(TRUE, - 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 ..."); - dbus_menu_manager_update_pa_state(FALSE, 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");*/ + if (eol > 0) { + + gboolean device_available = determine_sink_availability(); + if (device_available == TRUE) { + dbus_menu_manager_update_pa_state(TRUE, + 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 ..."); + dbus_menu_manager_update_pa_state(FALSE, 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) { - if (pa_context_errno(c) == PA_ERR_NOENTITY) - return; - g_warning("Default Sink info callback failure"); - 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 - { - dbus_menu_manager_update_pa_state(TRUE, determine_sink_availability(), default_sink_is_muted(), get_default_sink_volume()); - } + if (eol > 0) { + if (pa_context_errno(c) == PA_ERR_NOENTITY) + return; + g_warning("Default Sink info callback failure"); + 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 { + dbus_menu_manager_update_pa_state(TRUE, 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; +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; } - 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); - } + /* 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 (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; - 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_sink_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); - dbus_menu_manager_update_mute_ui(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_sink_volume(dbus_service, volume_percent); - } - } + 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_sink_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); + dbus_menu_manager_update_mute_ui(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_sink_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_sink_availability(dbus_service, TRUE); - } + } 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_sink_availability(dbus_service, TRUE); + } } 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; + 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); + 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; + 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"); - dbus_menu_manager_update_pa_state(FALSE, 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; - } + /* g_debug("server info callback");*/ + pa_operation *operation; + if (info == NULL) { + g_warning("No server - get the hell out of here"); + dbus_menu_manager_update_pa_state(FALSE, 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); + } + 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_sink_availability(dbus_service, FALSE); - -/* 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; - } + 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_sink_availability(dbus_service, FALSE); + + /* 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("FAILED to retrieve context - Is PulseAudio Daemon running ?"); - pa_server_available = FALSE; - reconnect_to_pulse(); - break; - case PA_CONTEXT_TERMINATED: -/* g_debug("context terminated");*/ - break; - case PA_CONTEXT_READY: - g_debug("PA daemon is 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; +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("FAILED to retrieve context - Is PulseAudio Daemon running ?"); + pa_server_available = FALSE; + reconnect_to_pulse(); + break; + case PA_CONTEXT_TERMINATED: + /* g_debug("context terminated");*/ + break; + case PA_CONTEXT_READY: + g_debug("PA daemon is 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/pulse-manager.h b/src/pulse-manager.h index 54978bb..fc01f1c 100644 --- a/src/pulse-manager.h +++ b/src/pulse-manager.h @@ -29,19 +29,19 @@ with this program. If not, see <http://www.gnu.org/licenses/>. typedef struct { - gchar* name; - gint index; - pa_cvolume volume; - pa_channel_map channel_map; - gboolean mute; - pa_volume_t base_volume; + 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 toggle_global_mute(gboolean mute_value); void close_pulse_activites(); #endif diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c index 8a21fcf..d56422a 100644 --- a/src/slider-menu-item.c +++ b/src/slider-menu-item.c @@ -4,16 +4,16 @@ 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 +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 +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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H @@ -28,9 +28,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>. typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate; -struct _SliderMenuItemPrivate -{ - gdouble slider_value; +struct _SliderMenuItemPrivate { + gdouble slider_value; }; #define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate)) @@ -46,58 +45,58 @@ G_DEFINE_TYPE (SliderMenuItem, slider_menu_item, DBUSMENU_TYPE_MENUITEM); static void slider_menu_item_class_init (SliderMenuItemClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (klass, sizeof (SliderMenuItemPrivate)); + g_type_class_add_private (klass, sizeof (SliderMenuItemPrivate)); - object_class->dispose = slider_menu_item_dispose; - object_class->finalize = slider_menu_item_finalize; + object_class->dispose = slider_menu_item_dispose; + object_class->finalize = slider_menu_item_finalize; DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass); mclass->handle_event = handle_event; - return; + return; } static void slider_menu_item_init (SliderMenuItem *self) { - g_debug("Building new Slider Menu Item"); - return; + g_debug("Building new Slider Menu Item"); + return; } static void slider_menu_item_dispose (GObject *object) { - G_OBJECT_CLASS (slider_menu_item_parent_class)->dispose (object); - return; + G_OBJECT_CLASS (slider_menu_item_parent_class)->dispose (object); + return; } static void slider_menu_item_finalize (GObject *object) { - G_OBJECT_CLASS (slider_menu_item_parent_class)->finalize (object); + G_OBJECT_CLASS (slider_menu_item_parent_class)->finalize (object); } static void handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp) { - g_debug("in the handle event method of slider_menu_item"); + g_debug("in the handle event method of slider_menu_item"); gdouble volume_input = 0; volume_input = g_value_get_double(value); - if(value != NULL) - set_sink_volume(volume_input); + if (value != NULL) + set_sink_volume(volume_input); } SliderMenuItem* slider_menu_item_new(gboolean sinks_available, gdouble start_volume) { - SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL); + SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL); dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_SLIDER_MENUITEM_TYPE); dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_ENABLED, sinks_available); dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_VISIBLE, sinks_available); - return self; + return self; } - + diff --git a/src/slider-menu-item.h b/src/slider-menu-item.h index c2acf63..763944f 100644 --- a/src/slider-menu-item.h +++ b/src/slider-menu-item.h @@ -4,16 +4,16 @@ 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 +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 +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 +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 __SLIDER_MENU_ITEM_H__ @@ -37,11 +37,11 @@ typedef struct _SliderMenuItem SliderMenuItem; typedef struct _SliderMenuItemClass SliderMenuItemClass; struct _SliderMenuItemClass { - DbusmenuMenuitemClass parent_class; + DbusmenuMenuitemClass parent_class; }; struct _SliderMenuItem { - DbusmenuMenuitem parent; + DbusmenuMenuitem parent; }; GType slider_menu_item_get_type (void); diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c index d1ddfc4..85945d0 100644 --- a/src/sound-service-dbus.c +++ b/src/sound-service-dbus.c @@ -28,7 +28,7 @@ #include "common-defs.h" #include "pulse-manager.h" -// DBUS methods +// DBUS methods static gboolean sound_service_dbus_get_sink_volume(SoundServiceDbus* service, gdouble* volume_percent_input, GError** gerror); static gboolean sound_service_dbus_get_sink_mute(SoundServiceDbus* service, gboolean* mute_input, GError** gerror); static gboolean sound_service_dbus_get_sink_availability(SoundServiceDbus* service, gboolean* availability_input, GError** gerror); @@ -38,12 +38,11 @@ static void sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const typedef struct _SoundServiceDbusPrivate SoundServiceDbusPrivate; -struct _SoundServiceDbusPrivate -{ - DBusGConnection *connection; - gdouble volume_percent; - gboolean mute; - gboolean sink_availability; +struct _SoundServiceDbusPrivate { + DBusGConnection *connection; + gdouble volume_percent; + gboolean mute; + gboolean sink_availability; }; @@ -73,47 +72,47 @@ G_DEFINE_TYPE (SoundServiceDbus, sound_service_dbus, G_TYPE_OBJECT); static void sound_service_dbus_class_init (SoundServiceDbusClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof(SoundServiceDbusPrivate)); - - object_class->dispose = sound_service_dbus_dispose; - object_class->finalize = sound_service_dbus_finalize; - - g_assert(klass != NULL); - dbus_g_object_type_install_info(SOUND_SERVICE_DBUS_TYPE, - &dbus_glib__sound_service_server_object_info); - - signals[SINK_INPUT_WHILE_MUTED] = g_signal_new("sink-input-while-muted", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - signals[SINK_VOLUME_UPDATE] = g_signal_new("sink-volume-update", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__DOUBLE, - G_TYPE_NONE, 1, G_TYPE_DOUBLE); - - signals[SINK_MUTE_UPDATE] = g_signal_new("sink-mute-update", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - signals[SINK_AVAILABLE_UPDATE] = g_signal_new("sink-available-update", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof(SoundServiceDbusPrivate)); + + object_class->dispose = sound_service_dbus_dispose; + object_class->finalize = sound_service_dbus_finalize; + + g_assert(klass != NULL); + dbus_g_object_type_install_info(SOUND_SERVICE_DBUS_TYPE, + &dbus_glib__sound_service_server_object_info); + + signals[SINK_INPUT_WHILE_MUTED] = g_signal_new("sink-input-while-muted", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[SINK_VOLUME_UPDATE] = g_signal_new("sink-volume-update", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, G_TYPE_DOUBLE); + + signals[SINK_MUTE_UPDATE] = g_signal_new("sink-mute-update", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + signals[SINK_AVAILABLE_UPDATE] = g_signal_new("sink-available-update", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); @@ -122,41 +121,41 @@ sound_service_dbus_class_init (SoundServiceDbusClass *klass) static void sound_service_dbus_init (SoundServiceDbus *self) { - GError *error = NULL; - SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self); - - priv->connection = NULL; - priv->volume_percent = 0; - priv->mute = FALSE; - priv->sink_availability = FALSE; - - /* Fetch the session bus */ - priv->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - - if (error != NULL) { - g_error("sound-service-dbus:Unable to connect to the session bus when creating indicator sound service : %s", error->message); - g_error_free(error); - return; - } - /* register the service on it */ - dbus_g_connection_register_g_object(priv->connection, - INDICATOR_SOUND_SERVICE_DBUS_OBJECT, - G_OBJECT(self)); + GError *error = NULL; + SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self); + + priv->connection = NULL; + priv->volume_percent = 0; + priv->mute = FALSE; + priv->sink_availability = FALSE; + + /* Fetch the session bus */ + priv->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + + if (error != NULL) { + g_error("sound-service-dbus:Unable to connect to the session bus when creating indicator sound service : %s", error->message); + g_error_free(error); + return; + } + /* register the service on it */ + dbus_g_connection_register_g_object(priv->connection, + INDICATOR_SOUND_SERVICE_DBUS_OBJECT, + G_OBJECT(self)); } static void sound_service_dbus_dispose (GObject *object) { - G_OBJECT_CLASS (sound_service_dbus_parent_class)->dispose (object); - return; + G_OBJECT_CLASS (sound_service_dbus_parent_class)->dispose (object); + return; } static void sound_service_dbus_finalize (GObject *object) { - G_OBJECT_CLASS (sound_service_dbus_parent_class)->finalize (object); - return; + G_OBJECT_CLASS (sound_service_dbus_parent_class)->finalize (object); + return; } @@ -165,32 +164,32 @@ DBUS Method Callbacks **/ static void sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint volume_percent, GError** gerror) { - g_debug("in the set sink volume method in the sound service dbus!, with volume_percent of %i", volume_percent); - set_sink_volume(volume_percent); + g_debug("in the set sink volume method in the sound service dbus!, with volume_percent of %i", volume_percent); + set_sink_volume(volume_percent); } static gboolean sound_service_dbus_get_sink_volume (SoundServiceDbus *self, gdouble *volume_percent_input, GError** gerror) { - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); - g_debug("Get sink volume method in the sound service dbus!, about to send over volume percent of %f", priv->volume_percent); - *volume_percent_input = priv->volume_percent; - return TRUE; + SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); + g_debug("Get sink volume method in the sound service dbus!, about to send over volume percent of %f", priv->volume_percent); + *volume_percent_input = priv->volume_percent; + return TRUE; } static gboolean sound_service_dbus_get_sink_mute (SoundServiceDbus *self, gboolean *mute_input, GError** gerror) { - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); - g_debug("Get sink mute - sound service dbus!, about to send over mute_value of %i", priv->mute); - *mute_input = priv->mute; - return TRUE; + SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); + g_debug("Get sink mute - sound service dbus!, about to send over mute_value of %i", priv->mute); + *mute_input = priv->mute; + return TRUE; } static gboolean sound_service_dbus_get_sink_availability (SoundServiceDbus *self, gboolean *availability_input, GError** gerror) { - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); - g_debug("Get sink availability - sound service dbus!, about to send over availability_value of %i", priv->sink_availability); - *availability_input = priv->sink_availability; - return TRUE; + SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self); + g_debug("Get sink availability - sound service dbus!, about to send over availability_value of %i", priv->sink_availability); + *availability_input = priv->sink_availability; + return TRUE; } /** @@ -199,8 +198,8 @@ Utility methods to emit signals from the service into the ether. **/ void sound_service_dbus_sink_input_while_muted(SoundServiceDbus* obj, gboolean block_value) { -/* g_debug("Emitting signal: SINK_INPUT_WHILE_MUTED, with block_value: %i", block_value);*/ - g_signal_emit(obj, + /* g_debug("Emitting signal: SINK_INPUT_WHILE_MUTED, with block_value: %i", block_value);*/ + g_signal_emit(obj, signals[SINK_INPUT_WHILE_MUTED], 0, block_value); @@ -208,11 +207,11 @@ void sound_service_dbus_sink_input_while_muted(SoundServiceDbus* obj, gboolean void sound_service_dbus_update_sink_volume(SoundServiceDbus* obj, gdouble sink_volume) { - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj); - priv->volume_percent = sink_volume; + SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj); + priv->volume_percent = sink_volume; -/* g_debug("Emitting signal: SINK_VOLUME_UPDATE, with sink_volme %f", priv->volume_percent);*/ - g_signal_emit(obj, + /* g_debug("Emitting signal: SINK_VOLUME_UPDATE, with sink_volme %f", priv->volume_percent);*/ + g_signal_emit(obj, signals[SINK_VOLUME_UPDATE], 0, priv->volume_percent); @@ -220,12 +219,12 @@ void sound_service_dbus_update_sink_volume(SoundServiceDbus* obj, gdouble sink_v void sound_service_dbus_update_sink_mute(SoundServiceDbus* obj, gboolean sink_mute) { -/* g_debug("Emitting signal: SINK_MUTE_UPDATE, with sink mute %i", sink_mute);*/ + /* g_debug("Emitting signal: SINK_MUTE_UPDATE, with sink mute %i", sink_mute);*/ - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj); - priv->mute = sink_mute; + SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj); + priv->mute = sink_mute; - g_signal_emit(obj, + g_signal_emit(obj, signals[SINK_MUTE_UPDATE], 0, priv->mute); @@ -233,16 +232,16 @@ void sound_service_dbus_update_sink_mute(SoundServiceDbus* obj, gboolean sink_mu void sound_service_dbus_update_sink_availability(SoundServiceDbus* obj, gboolean sink_availability) { -/* g_debug("Emitting signal: SINK_AVAILABILITY_UPDATE, with value %i", sink_availability);*/ + /* g_debug("Emitting signal: SINK_AVAILABILITY_UPDATE, with value %i", sink_availability);*/ - SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj); - priv->sink_availability = sink_availability; + SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj); + priv->sink_availability = sink_availability; - g_signal_emit(obj, + g_signal_emit(obj, signals[SINK_AVAILABLE_UPDATE], 0, priv->sink_availability); } - + diff --git a/src/sound-service-dbus.h b/src/sound-service-dbus.h index ae4953e..258b610 100644 --- a/src/sound-service-dbus.h +++ b/src/sound-service-dbus.h @@ -38,8 +38,7 @@ typedef struct _SoundServiceDbus SoundServiceDbus; typedef struct _SoundServiceDbusClass SoundServiceDbusClass; typedef struct _SoundData SoundData; -struct _SoundData -{ +struct _SoundData { SoundServiceDbus *service; }; @@ -49,7 +48,7 @@ struct _SoundServiceDbus { struct _SoundServiceDbusClass { GObjectClass parent_class; -}; +}; GType sound_service_dbus_get_type (void) G_GNUC_CONST; // Utility methods to get the SIGNAL messages across into the sound-service-dbus diff --git a/src/sound-service.c b/src/sound-service.c index 38e5fba..bcdac07 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -7,16 +7,16 @@ Authors: Ted Gould <ted@canonical.com> Cody Russell <crussell@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 +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 +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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -35,49 +35,49 @@ static GMainLoop *mainloop = NULL; /** service_shutdown: When the service interface starts to shutdown, we -should follow it. +should follow it. **/ void service_shutdown (IndicatorService *service, gpointer user_data) { - if (mainloop != NULL) { - g_debug("Service shutdown !"); + if (mainloop != NULL) { + g_debug("Service shutdown !"); // TODO: uncomment for release !! - close_pulse_activites(); + close_pulse_activites(); g_main_loop_quit(mainloop); - } - return; + } + return; } /** -main: +main: **/ int main (int argc, char ** argv) { g_type_init(); - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - textdomain (GETTEXT_PACKAGE); + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + textdomain (GETTEXT_PACKAGE); - IndicatorService *service = indicator_service_new_version(INDICATOR_SOUND_DBUS_NAME, - INDICATOR_SOUND_DBUS_VERSION); - g_signal_connect(G_OBJECT(service), - INDICATOR_SERVICE_SIGNAL_SHUTDOWN, - G_CALLBACK(service_shutdown), NULL); + IndicatorService *service = indicator_service_new_version(INDICATOR_SOUND_DBUS_NAME, + INDICATOR_SOUND_DBUS_VERSION); + g_signal_connect(G_OBJECT(service), + INDICATOR_SERVICE_SIGNAL_SHUTDOWN, + G_CALLBACK(service_shutdown), NULL); - DbusmenuMenuitem* root_menuitem = dbus_menu_manager_setup(); - MusicPlayerBridge* server = music_player_bridge_new(); - music_player_bridge_set_root_menu_item(server, root_menuitem); + DbusmenuMenuitem* root_menuitem = dbus_menu_manager_setup(); + MusicPlayerBridge* server = music_player_bridge_new(); + music_player_bridge_set_root_menu_item(server, root_menuitem); - // Run the loop + // Run the loop mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); - + return 0; } diff --git a/src/sound-service.h b/src/sound-service.h index cefbf45..e95d4c7 100644 --- a/src/sound-service.h +++ b/src/sound-service.h @@ -10,16 +10,16 @@ Authors: Ted Gould <ted@canonical.com> Cody Russell <crussell@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 +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 +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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ diff --git a/src/transport-menu-item.c b/src/transport-menu-item.c index bcddc55..96d3576 100644 --- a/src/transport-menu-item.c +++ b/src/transport-menu-item.c @@ -2,7 +2,6 @@ * generated from transport-menu-item.vala, do not modify */ /* -This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel. Copyright 2010 Canonical Ltd. Authors: @@ -27,20 +26,22 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/menuitem-proxy.h> #include <libdbusmenu-glib/menuitem.h> #include <libdbusmenu-glib/server.h> +#include <common-defs.h> #include <stdlib.h> #include <string.h> +#include <gee.h> -#define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) -#define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) -#define TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) -#define IS_TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TRANSPORT_MENUITEM)) -#define IS_TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TRANSPORT_MENUITEM)) -#define TRANSPORT_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) +#define TYPE_PLAYER_ITEM (player_item_get_type ()) +#define PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_ITEM, PlayerItem)) +#define PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_ITEM, PlayerItemClass)) +#define IS_PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_ITEM)) +#define IS_PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_ITEM)) +#define PLAYER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_ITEM, PlayerItemClass)) -typedef struct _TransportMenuitem TransportMenuitem; -typedef struct _TransportMenuitemClass TransportMenuitemClass; -typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate; +typedef struct _PlayerItem PlayerItem; +typedef struct _PlayerItemClass PlayerItemClass; +typedef struct _PlayerItemPrivate PlayerItemPrivate; #define TYPE_MPRIS_CONTROLLER (mpris_controller_get_type ()) #define MPRIS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER, MprisController)) @@ -51,48 +52,66 @@ typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate; typedef struct _MprisController MprisController; typedef struct _MprisControllerClass MprisControllerClass; -#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) + +#define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) +#define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) +#define TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) +#define IS_TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TRANSPORT_MENUITEM)) +#define IS_TRANSPORT_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TRANSPORT_MENUITEM)) +#define TRANSPORT_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitemClass)) + +typedef struct _TransportMenuitem TransportMenuitem; +typedef struct _TransportMenuitemClass TransportMenuitemClass; +typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate; #define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) -struct _TransportMenuitem { +struct _PlayerItem { DbusmenuMenuitem parent_instance; - TransportMenuitemPrivate * priv; + PlayerItemPrivate * priv; + MprisController* mpris_adaptor; }; -struct _TransportMenuitemClass { +struct _PlayerItemClass { DbusmenuMenuitemClass parent_class; + void (*check_layout) (PlayerItem* self); }; -struct _TransportMenuitemPrivate { - MprisController* mpris_adaptor; +struct _TransportMenuitem { + PlayerItem parent_instance; + TransportMenuitemPrivate * priv; +}; + +struct _TransportMenuitemClass { + PlayerItemClass parent_class; }; static gpointer transport_menuitem_parent_class = NULL; -GType transport_menuitem_get_type (void); +GType player_item_get_type (void); GType mpris_controller_get_type (void); -#define TRANSPORT_MENUITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_TRANSPORT_MENUITEM, TransportMenuitemPrivate)) +GType transport_menuitem_get_type (void); enum { TRANSPORT_MENUITEM_DUMMY_PROPERTY }; -#define TRANSPORT_MENUITEM_DBUSMENU_TRANSPORT_MENUITEM_TYPE "x-canonical-transport-bar" -#define TRANSPORT_MENUITEM_DBUSMENU_TRANSPORT_MENUITEM_STATE "x-canonical-transport-state" +PlayerItem* player_item_new (void); +PlayerItem* player_item_construct (GType object_type); TransportMenuitem* transport_menuitem_new (void); TransportMenuitem* transport_menuitem_construct (GType object_type); -void transport_menuitem_set_adaptor (TransportMenuitem* self, MprisController* adaptor); +void transport_menuitem_change_play_state (TransportMenuitem* self, gint state); void mpris_controller_toggle_playback (MprisController* self, gboolean state); static void transport_menuitem_real_handle_event (DbusmenuMenuitem* base, const char* name, GValue* input_value, guint timestamp); -static void transport_menuitem_finalize (GObject* obj); +static void transport_menuitem_real_check_layout (PlayerItem* base); +GeeHashSet* transport_menuitem_attributes_format (void); TransportMenuitem* transport_menuitem_construct (GType object_type) { TransportMenuitem * self; - self = g_object_newv (object_type, 0, NULL); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_MENUITEM_PROP_TYPE, TRANSPORT_MENUITEM_DBUSMENU_TRANSPORT_MENUITEM_TYPE); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, TRANSPORT_MENUITEM_DBUSMENU_TRANSPORT_MENUITEM_STATE, FALSE); - g_debug ("transport-menu-item.vala:36: transport on the vala side"); + self = (TransportMenuitem*) player_item_construct (object_type); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_TRANSPORT_MENUITEM_TYPE); + g_debug ("transport-menu-item.vala:30: transport on the vala side"); return self; } @@ -102,16 +121,9 @@ TransportMenuitem* transport_menuitem_new (void) { } -static gpointer _g_object_ref0 (gpointer self) { - return self ? g_object_ref (self) : NULL; -} - - -void transport_menuitem_set_adaptor (TransportMenuitem* self, MprisController* adaptor) { - MprisController* _tmp0_; +void transport_menuitem_change_play_state (TransportMenuitem* self, gint state) { g_return_if_fail (self != NULL); - g_return_if_fail (adaptor != NULL); - self->priv->mpris_adaptor = (_tmp0_ = _g_object_ref0 (adaptor), _g_object_unref0 (self->priv->mpris_adaptor), _tmp0_); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE, state); } @@ -132,30 +144,36 @@ static void transport_menuitem_real_handle_event (DbusmenuMenuitem* base, const char* _tmp0_; self = (TransportMenuitem*) base; g_return_if_fail (name != NULL); - g_debug ("transport-menu-item.vala:51: handle_event with bool value %s", _tmp0_ = bool_to_string (g_value_get_boolean (input_value))); + g_debug ("transport-menu-item.vala:40: handle_event with bool value %s", _tmp0_ = bool_to_string (g_value_get_boolean (input_value))); _g_free0 (_tmp0_); - mpris_controller_toggle_playback (self->priv->mpris_adaptor, g_value_get_boolean (input_value)); + mpris_controller_toggle_playback (((PlayerItem*) self)->mpris_adaptor, g_value_get_boolean (input_value)); +} + + +static void transport_menuitem_real_check_layout (PlayerItem* base) { + TransportMenuitem * self; + self = (TransportMenuitem*) base; +} + + +GeeHashSet* transport_menuitem_attributes_format (void) { + GeeHashSet* result = NULL; + GeeHashSet* attrs; + attrs = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, NULL, NULL); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE); + result = attrs; + return result; } static void transport_menuitem_class_init (TransportMenuitemClass * klass) { transport_menuitem_parent_class = g_type_class_peek_parent (klass); - g_type_class_add_private (klass, sizeof (TransportMenuitemPrivate)); DBUSMENU_MENUITEM_CLASS (klass)->handle_event = transport_menuitem_real_handle_event; - G_OBJECT_CLASS (klass)->finalize = transport_menuitem_finalize; + PLAYER_ITEM_CLASS (klass)->check_layout = transport_menuitem_real_check_layout; } static void transport_menuitem_instance_init (TransportMenuitem * self) { - self->priv = TRANSPORT_MENUITEM_GET_PRIVATE (self); -} - - -static void transport_menuitem_finalize (GObject* obj) { - TransportMenuitem * self; - self = TRANSPORT_MENUITEM (obj); - _g_object_unref0 (self->priv->mpris_adaptor); - G_OBJECT_CLASS (transport_menuitem_parent_class)->finalize (obj); } @@ -164,7 +182,7 @@ GType transport_menuitem_get_type (void) { if (g_once_init_enter (&transport_menuitem_type_id__volatile)) { static const GTypeInfo g_define_type_info = { sizeof (TransportMenuitemClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) transport_menuitem_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (TransportMenuitem), 0, (GInstanceInitFunc) transport_menuitem_instance_init, NULL }; GType transport_menuitem_type_id; - transport_menuitem_type_id = g_type_register_static (DBUSMENU_TYPE_MENUITEM, "TransportMenuitem", &g_define_type_info, 0); + transport_menuitem_type_id = g_type_register_static (TYPE_PLAYER_ITEM, "TransportMenuitem", &g_define_type_info, 0); g_once_init_leave (&transport_menuitem_type_id__volatile, transport_menuitem_type_id); } return transport_menuitem_type_id__volatile; diff --git a/src/transport-menu-item.vala b/src/transport-menu-item.vala index 2e1ed0b..264e153 100644 --- a/src/transport-menu-item.vala +++ b/src/transport-menu-item.vala @@ -1,5 +1,4 @@ /* -This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel. Copyright 2010 Canonical Ltd. Authors: @@ -20,35 +19,37 @@ with this program. If not, see <http://www.gnu.org/licenses/>. using Dbusmenu; using Gee; +using DbusmenuTransport; -public class TransportMenuitem : Dbusmenu.Menuitem +public class TransportMenuitem : PlayerItem { - /* Not ideal duplicate definition of const - see common-defs/h */ - const string DBUSMENU_TRANSPORT_MENUITEM_TYPE = "x-canonical-transport-bar"; - const string DBUSMENU_TRANSPORT_MENUITEM_STATE = "x-canonical-transport-state"; - private MprisController mpris_adaptor; public TransportMenuitem() { - this.property_set(MENUITEM_PROP_TYPE, DBUSMENU_TRANSPORT_MENUITEM_TYPE); - // Hardcode the set up state until we can get the struct vala bug fixed - this.property_set_bool(DBUSMENU_TRANSPORT_MENUITEM_STATE, false); + this.property_set(MENUITEM_PROP_TYPE, MENUITEM_TYPE); debug("transport on the vala side"); } - public void set_adaptor(MprisController adaptor) + public void change_play_state(int state) { - this.mpris_adaptor = adaptor; + this.property_set_int(MENUITEM_PLAY_STATE, state); } - /** - Callback method for the handle_event - * TRUE => Playing - * FALSE => Paused - **/ public override void handle_event(string name, GLib.Value input_value, uint timestamp) { debug("handle_event with bool value %s", input_value.get_boolean().to_string()); this.mpris_adaptor.toggle_playback(input_value.get_boolean()); + } + + public override void check_layout(){ + // nothing to be done for this item - always active + } + + + public static HashSet<string> attributes_format() + { + HashSet<string> attrs = new HashSet<string>(); + attrs.add(MENUITEM_PLAY_STATE); + return attrs; } }
\ No newline at end of file diff --git a/src/transport-widget.c b/src/transport-widget.c index c53513d..bc9df53 100644 --- a/src/transport-widget.c +++ b/src/transport-widget.c @@ -61,13 +61,15 @@ static gboolean transport_widget_button_press_event (GtkWidget *men GdkEventButton *event); static gboolean transport_widget_button_release_event (GtkWidget *menuitem, GdkEventButton *event); - +static void transport_widget_play_clicked (GtkWidget* button, + TransportWidget* self); + static void transport_widget_property_update(DbusmenuMenuitem* item, gchar * property, GValue * value, gpointer userdata); // utility methods -static gchar* transport_widget_toggle_play_label(const gchar* state); +static gchar* transport_widget_toggle_play_label(gint state); G_DEFINE_TYPE (TransportWidget, transport_widget, GTK_TYPE_MENU_ITEM); @@ -78,7 +80,9 @@ transport_widget_class_init (TransportWidgetClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GtkMenuItemClass *menu_item_class = GTK_MENU_ITEM_CLASS(klass); + menu_item_class->hide_on_activate = FALSE; widget_class->button_press_event = transport_widget_button_press_event; widget_class->button_release_event = transport_widget_button_release_event; @@ -130,19 +134,17 @@ transport_widget_init (TransportWidget *self) GtkWidget *hbox; hbox = gtk_hbox_new(TRUE, 2); - - gchar* label = ">"; - if(dbusmenu_menuitem_property_get_bool(twin_item, DBUSMENU_TRANSPORT_MENUITEM_STATE) == TRUE){ - label = "||"; - } - - priv->play_button = gtk_button_new_with_label(g_strdup(label)); + gchar* symbol = transport_widget_toggle_play_label(dbusmenu_menuitem_property_get_int(twin_item, DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE)); + priv->play_button = gtk_button_new_with_label(symbol); + //g_free(symbol); gtk_box_pack_start (GTK_BOX (hbox), priv->play_button, FALSE, TRUE, 0); priv->hbox = hbox; g_signal_connect(G_OBJECT(twin_item), "property-changed", G_CALLBACK(transport_widget_property_update), self); + g_signal_connect(priv->play_button, "clicked", G_CALLBACK(transport_widget_play_clicked), self); + gtk_container_add (GTK_CONTAINER (self), priv->hbox); gtk_widget_show_all (priv->hbox); @@ -166,11 +168,16 @@ transport_widget_button_press_event (GtkWidget *menuitem, GdkEventButton *event) { g_debug("TransportWidget::menu_press_event"); + if(IS_TRANSPORT_WIDGET(menuitem) == FALSE){ + return FALSE; + } + TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem)); + gtk_widget_event (priv->hbox, (GdkEvent*)event); gboolean state = g_ascii_strcasecmp(gtk_button_get_label(GTK_BUTTON(priv->play_button)), ">") == 0; - gtk_button_set_label(GTK_BUTTON(priv->play_button), transport_widget_toggle_play_label(gtk_button_get_label(GTK_BUTTON(priv->play_button)))); + gtk_button_set_label(GTK_BUTTON(priv->play_button), transport_widget_toggle_play_label((gint)state)); GValue value = {0}; g_value_init(&value, G_TYPE_BOOLEAN); g_debug("TransportWidget::menu_press_event - going to send value %i", state); @@ -181,11 +188,25 @@ transport_widget_button_press_event (GtkWidget *menuitem, return TRUE; } +static void +transport_widget_play_clicked(GtkWidget* button, + TransportWidget* self) +{ + g_debug("Transport_widget_play_clicked"); +} + static gboolean transport_widget_button_release_event (GtkWidget *menuitem, GdkEventButton *event) { g_debug("TransportWidget::menu_release_event"); + if(IS_TRANSPORT_WIDGET(menuitem) == FALSE){ + return FALSE; + } + + TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem)); + gtk_widget_event (priv->hbox, (GdkEvent*)event); + return TRUE; } @@ -195,23 +216,23 @@ transport_widget_button_release_event (GtkWidget *menuitem, **/ static void transport_widget_property_update(DbusmenuMenuitem* item, gchar* property, - GValue* value, gpointer userdata) + GValue* value, gpointer userdata) { g_debug("transport_widget_update_state - with property %s", property); - gchar* input = g_strdup(g_value_get_string(value)); - g_debug("transport_widget_update_state - with value %s", input); + int update_value = g_value_get_int(value); + g_debug("transport_widget_update_state - with value %i", update_value); TransportWidget* bar = (TransportWidget*)userdata; TransportWidgetPrivate *priv = TRANSPORT_WIDGET_GET_PRIVATE(bar); - gtk_button_set_label(GTK_BUTTON(priv->play_button), g_strdup(transport_widget_toggle_play_label(property))); + gtk_button_set_label(GTK_BUTTON(priv->play_button), transport_widget_toggle_play_label(update_value)); } // will be needed for image swapping -static gchar* transport_widget_toggle_play_label(const gchar* state) +static gchar* transport_widget_toggle_play_label(int play_state) { gchar* label = ">"; - if(g_strcmp0(state, ">") == 0){ + if(play_state == 1){ label = "||"; } return label; |