aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am111
-rw-r--r--src/Makefile.in247
-rw-r--r--src/common-defs.h13
-rw-r--r--src/dbus-menu-manager.c4
-rw-r--r--src/dbus-menu-manager.h4
-rwxr-xr-xsrc/indicator-sound.c339
-rw-r--r--src/metadata-menu-item.c186
-rw-r--r--src/metadata-menu-item.vala40
-rw-r--r--src/metadata-widget.c214
-rw-r--r--src/metadata-widget.h51
-rw-r--r--src/mpris-controller-v2.c135
-rw-r--r--src/mpris-controller-v2.vala28
-rw-r--r--src/mpris-controller.c380
-rw-r--r--src/mpris-controller.vala101
-rw-r--r--src/music-player-bridge.c362
-rw-r--r--src/music-player-bridge.h185
-rw-r--r--src/music-player-bridge.vala106
-rw-r--r--src/player-controller.c364
-rw-r--r--src/player-controller.vala110
-rw-r--r--src/pulse-manager.c74
-rw-r--r--src/slider-menu-item.c18
-rw-r--r--src/sound-service-dbus.c8
-rw-r--r--src/sound-service.c21
-rw-r--r--src/transport-menu-item.c175
-rw-r--r--src/transport-menu-item.vala54
-rw-r--r--src/transport-widget.c230
-rw-r--r--src/transport-widget.h51
27 files changed, 3337 insertions, 274 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f472662..5a42dc6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,11 +7,15 @@ libexec_PROGRAMS = indicator-sound-service
soundmenulibdir = $(INDICATORDIR)
soundmenulib_LTLIBRARIES = libsoundmenu.la
libsoundmenu_la_SOURCES = \
- common-defs.h \
+ common-defs.h \
indicator-sound.h \
+ transport-widget.c \
+ transport-widget.h \
+ metadata-widget.c \
+ metadata-widget.h \
indicator-sound.c \
dbus-shared-names.h \
- sound-service-client.h
+ sound-service-client.h
libsoundmenu_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Werror -DG_LOG_DOMAIN=\"Indicator-Sound\"
libsoundmenu_la_LIBADD = $(APPLET_LIBS)
@@ -29,25 +33,13 @@ sound-service-client.h: $(srcdir)/sound-service.xml
$(srcdir)/sound-service.xml
+####################################################################
+# Sound Service
+####################################################################
+
#################
-# Session Stuff
+# dbus interface
#################
-indicator_sound_service_SOURCES = \
- common-defs.h \
- sound-service.h \
- sound-service.c \
- dbus-menu-manager.c \
- dbus-menu-manager.h \
- pulse-manager.h \
- pulse-manager.c \
- sound-service-dbus.h \
- sound-service-dbus.c \
- sound-service-server.h \
- slider-menu-item.h \
- slider-menu-item.c
-indicator_sound_service_CFLAGS = $(PULSEAUDIO_CFLAGS) $(SOUNDSERVICE_CFLAGS) $(GCONF_CFLAGS) -DLIBEXECDIR=\"$(libexecdir)\" -Wall -Werror
-indicator_sound_service_LDADD = $(PULSEAUDIO_LIBS) $(SOUNDSERVICE_LIBS) $(GCONF_LIBS)
-
sound-service-server.h: $(srcdir)/sound-service.xml
dbus-binding-tool \
--prefix=_sound_service_server \
@@ -55,21 +47,78 @@ sound-service-server.h: $(srcdir)/sound-service.xml
--output=sound-service-server.h \
$(srcdir)/sound-service.xml
-###############
-# Other Stuff
-###############
-BUILT_SOURCES = \
- sound-service-client.h \
- sound-service-server.h
+#####################
+# libsoundmenu vala
+#####################
+music_bridge_VALASOURCES = \
+ music-player-bridge.vala \
+ transport-menu-item.vala \
+ metadata-menu-item.vala \
+ player-controller.vala \
+ mpris-controller-v2.vala \
+ mpris-controller.vala
+
+music_bridge_VALAFLAGS = \
+ --ccode \
+ -H music-player-bridge.h -d . \
+ --library music-bridge \
+ --vapidir=./ \
+ --thread \
+ --pkg gee-1.0 \
+ --pkg Indicate-0.2 \
+ --pkg Dbusmenu-Glib-0.2 \
+ --pkg dbus-glib-1
+
+ $(MAINTAINER_VALAFLAGS)
+
+music_bridge_APIFILES = \
+ music-player-bridge.h
+
+music_bridge_vala.stamp $(music_bridge_APIFILES): $(music_bridge_VALASOURCES)
+ $(AM_V_GEN) $(VALAC) $(music_bridge_VALAFLAGS) $^
+ touch music_bridge_vala.stamp
+
+###############################
+# libsoundmenu C
+###############################
+indicator_sound_service_SOURCES = \
+ common-defs.h \
+ sound-service.h \
+ sound-service.c \
+ dbus-menu-manager.c \
+ dbus-menu-manager.h \
+ pulse-manager.h \
+ pulse-manager.c \
+ sound-service-dbus.h \
+ sound-service-dbus.c \
+ sound-service-server.h \
+ slider-menu-item.h \
+ slider-menu-item.c \
+ $(music_bridge_VALASOURCES:.vala=.c)
+
+indicator_sound_service_CFLAGS = $(PULSEAUDIO_CFLAGS) $(SOUNDSERVICE_CFLAGS) $(GCONF_CFLAGS) -DLIBEXECDIR=\"$(libexecdir)\" -Wall
+indicator_sound_service_LDADD = $(PULSEAUDIO_LIBS) $(SOUNDSERVICE_LIBS) $(GCONF_LIBS)
+#########################
+# Extra stuff to package
+#########################
EXTRA_DIST = \
- sound-service.xml \
- sound-service.list
+ sound-service.xml \
+ sound-service.list \
+ $(music_bridge_APIFILES) \
+ $(music_bridge_VALASOURCES)
+
+#######################
+# Stuff to clean Stuff
+#######################
+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)
CLEANFILES = \
$(BUILT_SOURCES)
-
-
-
-
diff --git a/src/Makefile.in b/src/Makefile.in
index 7970677..c78ee32 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -39,10 +39,7 @@ libexec_PROGRAMS = indicator-sound-service$(EXEEXT)
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/intltool.m4 \
- $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
- $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -75,7 +72,9 @@ am__installdirs = "$(DESTDIR)$(soundmenulibdir)" \
LTLIBRARIES = $(soundmenulib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libsoundmenu_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
-am_libsoundmenu_la_OBJECTS = libsoundmenu_la-indicator-sound.lo
+am_libsoundmenu_la_OBJECTS = libsoundmenu_la-transport-widget.lo \
+ libsoundmenu_la-metadata-widget.lo \
+ libsoundmenu_la-indicator-sound.lo
libsoundmenu_la_OBJECTS = $(am_libsoundmenu_la_OBJECTS)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@@ -85,12 +84,19 @@ libsoundmenu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(libsoundmenu_la_CFLAGS) $(CFLAGS) $(libsoundmenu_la_LDFLAGS) \
$(LDFLAGS) -o $@
PROGRAMS = $(libexec_PROGRAMS)
+am__objects_1 = indicator_sound_service-music-player-bridge.$(OBJEXT) \
+ indicator_sound_service-transport-menu-item.$(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)
am_indicator_sound_service_OBJECTS = \
indicator_sound_service-sound-service.$(OBJEXT) \
indicator_sound_service-dbus-menu-manager.$(OBJEXT) \
indicator_sound_service-pulse-manager.$(OBJEXT) \
indicator_sound_service-sound-service-dbus.$(OBJEXT) \
- indicator_sound_service-slider-menu-item.$(OBJEXT)
+ indicator_sound_service-slider-menu-item.$(OBJEXT) \
+ $(am__objects_1)
indicator_sound_service_OBJECTS = \
$(am_indicator_sound_service_OBJECTS)
indicator_sound_service_DEPENDENCIES = $(am__DEPENDENCIES_1) \
@@ -231,6 +237,7 @@ SOUNDSERVICE_CFLAGS = @SOUNDSERVICE_CFLAGS@
SOUNDSERVICE_LIBS = @SOUNDSERVICE_LIBS@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
+VALAC = @VALAC@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
abs_builddir = @abs_builddir@
@@ -292,46 +299,87 @@ top_srcdir = @top_srcdir@
soundmenulibdir = $(INDICATORDIR)
soundmenulib_LTLIBRARIES = libsoundmenu.la
libsoundmenu_la_SOURCES = \
- common-defs.h \
+ common-defs.h \
indicator-sound.h \
+ transport-widget.c \
+ transport-widget.h \
+ metadata-widget.c \
+ metadata-widget.h \
indicator-sound.c \
dbus-shared-names.h \
- sound-service-client.h
+ sound-service-client.h
libsoundmenu_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Werror -DG_LOG_DOMAIN=\"Indicator-Sound\"
libsoundmenu_la_LIBADD = $(APPLET_LIBS)
libsoundmenu_la_LDFLAGS = -module -avoid-version
-#################
-# Session Stuff
-#################
+#####################
+# libsoundmenu vala
+#####################
+music_bridge_VALASOURCES = \
+ music-player-bridge.vala \
+ transport-menu-item.vala \
+ metadata-menu-item.vala \
+ player-controller.vala \
+ mpris-controller-v2.vala \
+ mpris-controller.vala
+
+music_bridge_VALAFLAGS = \
+ --ccode \
+ -H music-player-bridge.h -d . \
+ --library music-bridge \
+ --vapidir=./ \
+ --thread \
+ --pkg gee-1.0 \
+ --pkg Indicate-0.2 \
+ --pkg Dbusmenu-Glib-0.2 \
+ --pkg dbus-glib-1
+
+music_bridge_APIFILES = \
+ music-player-bridge.h
+
+
+###############################
+# libsoundmenu C
+###############################
indicator_sound_service_SOURCES = \
- common-defs.h \
- sound-service.h \
- sound-service.c \
- dbus-menu-manager.c \
- dbus-menu-manager.h \
- pulse-manager.h \
- pulse-manager.c \
- sound-service-dbus.h \
- sound-service-dbus.c \
- sound-service-server.h \
- slider-menu-item.h \
- slider-menu-item.c
-
-indicator_sound_service_CFLAGS = $(PULSEAUDIO_CFLAGS) $(SOUNDSERVICE_CFLAGS) $(GCONF_CFLAGS) -DLIBEXECDIR=\"$(libexecdir)\" -Wall -Werror
+ common-defs.h \
+ sound-service.h \
+ sound-service.c \
+ dbus-menu-manager.c \
+ dbus-menu-manager.h \
+ pulse-manager.h \
+ pulse-manager.c \
+ sound-service-dbus.h \
+ sound-service-dbus.c \
+ sound-service-server.h \
+ slider-menu-item.h \
+ slider-menu-item.c \
+ $(music_bridge_VALASOURCES:.vala=.c)
+
+indicator_sound_service_CFLAGS = $(PULSEAUDIO_CFLAGS) $(SOUNDSERVICE_CFLAGS) $(GCONF_CFLAGS) -DLIBEXECDIR=\"$(libexecdir)\" -Wall
indicator_sound_service_LDADD = $(PULSEAUDIO_LIBS) $(SOUNDSERVICE_LIBS) $(GCONF_LIBS)
-###############
-# Other Stuff
-###############
+#########################
+# Extra stuff to package
+#########################
+EXTRA_DIST = \
+ sound-service.xml \
+ sound-service.list \
+ $(music_bridge_APIFILES) \
+ $(music_bridge_VALASOURCES)
+
+
+#######################
+# Stuff to clean Stuff
+#######################
BUILT_SOURCES = \
+ music_bridge_vala.stamp \
sound-service-client.h \
- sound-service-server.h
-
-EXTRA_DIST = \
- sound-service.xml \
- sound-service.list
+ sound-service-server.h \
+ music-bridge.vapi \
+ $(music_bridge_APIFILES) \
+ $(music_bridge_VALASOURCES:.vala=.c)
CLEANFILES = \
$(BUILT_SOURCES)
@@ -458,11 +506,19 @@ 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-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-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@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-sound-service.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-transport-menu-item.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoundmenu_la-indicator-sound.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoundmenu_la-metadata-widget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoundmenu_la-transport-widget.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -488,6 +544,22 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+libsoundmenu_la-transport-widget.lo: transport-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoundmenu_la_CFLAGS) $(CFLAGS) -MT libsoundmenu_la-transport-widget.lo -MD -MP -MF $(DEPDIR)/libsoundmenu_la-transport-widget.Tpo -c -o libsoundmenu_la-transport-widget.lo `test -f 'transport-widget.c' || echo '$(srcdir)/'`transport-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoundmenu_la-transport-widget.Tpo $(DEPDIR)/libsoundmenu_la-transport-widget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='transport-widget.c' object='libsoundmenu_la-transport-widget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoundmenu_la_CFLAGS) $(CFLAGS) -c -o libsoundmenu_la-transport-widget.lo `test -f 'transport-widget.c' || echo '$(srcdir)/'`transport-widget.c
+
+libsoundmenu_la-metadata-widget.lo: metadata-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoundmenu_la_CFLAGS) $(CFLAGS) -MT libsoundmenu_la-metadata-widget.lo -MD -MP -MF $(DEPDIR)/libsoundmenu_la-metadata-widget.Tpo -c -o libsoundmenu_la-metadata-widget.lo `test -f 'metadata-widget.c' || echo '$(srcdir)/'`metadata-widget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoundmenu_la-metadata-widget.Tpo $(DEPDIR)/libsoundmenu_la-metadata-widget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='metadata-widget.c' object='libsoundmenu_la-metadata-widget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoundmenu_la_CFLAGS) $(CFLAGS) -c -o libsoundmenu_la-metadata-widget.lo `test -f 'metadata-widget.c' || echo '$(srcdir)/'`metadata-widget.c
+
libsoundmenu_la-indicator-sound.lo: indicator-sound.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsoundmenu_la_CFLAGS) $(CFLAGS) -MT libsoundmenu_la-indicator-sound.lo -MD -MP -MF $(DEPDIR)/libsoundmenu_la-indicator-sound.Tpo -c -o libsoundmenu_la-indicator-sound.lo `test -f 'indicator-sound.c' || echo '$(srcdir)/'`indicator-sound.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoundmenu_la-indicator-sound.Tpo $(DEPDIR)/libsoundmenu_la-indicator-sound.Plo
@@ -576,6 +648,102 @@ indicator_sound_service-slider-menu-item.obj: slider-menu-item.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-slider-menu-item.obj `if test -f 'slider-menu-item.c'; then $(CYGPATH_W) 'slider-menu-item.c'; else $(CYGPATH_W) '$(srcdir)/slider-menu-item.c'; fi`
+indicator_sound_service-music-player-bridge.o: music-player-bridge.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-music-player-bridge.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-music-player-bridge.Tpo -c -o indicator_sound_service-music-player-bridge.o `test -f 'music-player-bridge.c' || echo '$(srcdir)/'`music-player-bridge.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-music-player-bridge.Tpo $(DEPDIR)/indicator_sound_service-music-player-bridge.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='music-player-bridge.c' object='indicator_sound_service-music-player-bridge.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-music-player-bridge.o `test -f 'music-player-bridge.c' || echo '$(srcdir)/'`music-player-bridge.c
+
+indicator_sound_service-music-player-bridge.obj: music-player-bridge.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-music-player-bridge.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-music-player-bridge.Tpo -c -o indicator_sound_service-music-player-bridge.obj `if test -f 'music-player-bridge.c'; then $(CYGPATH_W) 'music-player-bridge.c'; else $(CYGPATH_W) '$(srcdir)/music-player-bridge.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-music-player-bridge.Tpo $(DEPDIR)/indicator_sound_service-music-player-bridge.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='music-player-bridge.c' object='indicator_sound_service-music-player-bridge.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-music-player-bridge.obj `if test -f 'music-player-bridge.c'; then $(CYGPATH_W) 'music-player-bridge.c'; else $(CYGPATH_W) '$(srcdir)/music-player-bridge.c'; fi`
+
+indicator_sound_service-transport-menu-item.o: transport-menu-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-transport-menu-item.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-transport-menu-item.Tpo -c -o indicator_sound_service-transport-menu-item.o `test -f 'transport-menu-item.c' || echo '$(srcdir)/'`transport-menu-item.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-transport-menu-item.Tpo $(DEPDIR)/indicator_sound_service-transport-menu-item.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='transport-menu-item.c' object='indicator_sound_service-transport-menu-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-transport-menu-item.o `test -f 'transport-menu-item.c' || echo '$(srcdir)/'`transport-menu-item.c
+
+indicator_sound_service-transport-menu-item.obj: transport-menu-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-transport-menu-item.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-transport-menu-item.Tpo -c -o indicator_sound_service-transport-menu-item.obj `if test -f 'transport-menu-item.c'; then $(CYGPATH_W) 'transport-menu-item.c'; else $(CYGPATH_W) '$(srcdir)/transport-menu-item.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-transport-menu-item.Tpo $(DEPDIR)/indicator_sound_service-transport-menu-item.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='transport-menu-item.c' object='indicator_sound_service-transport-menu-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-transport-menu-item.obj `if test -f 'transport-menu-item.c'; then $(CYGPATH_W) 'transport-menu-item.c'; else $(CYGPATH_W) '$(srcdir)/transport-menu-item.c'; fi`
+
+indicator_sound_service-metadata-menu-item.o: metadata-menu-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-metadata-menu-item.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-metadata-menu-item.Tpo -c -o indicator_sound_service-metadata-menu-item.o `test -f 'metadata-menu-item.c' || echo '$(srcdir)/'`metadata-menu-item.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-metadata-menu-item.Tpo $(DEPDIR)/indicator_sound_service-metadata-menu-item.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='metadata-menu-item.c' object='indicator_sound_service-metadata-menu-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-metadata-menu-item.o `test -f 'metadata-menu-item.c' || echo '$(srcdir)/'`metadata-menu-item.c
+
+indicator_sound_service-metadata-menu-item.obj: metadata-menu-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-metadata-menu-item.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-metadata-menu-item.Tpo -c -o indicator_sound_service-metadata-menu-item.obj `if test -f 'metadata-menu-item.c'; then $(CYGPATH_W) 'metadata-menu-item.c'; else $(CYGPATH_W) '$(srcdir)/metadata-menu-item.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-metadata-menu-item.Tpo $(DEPDIR)/indicator_sound_service-metadata-menu-item.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='metadata-menu-item.c' object='indicator_sound_service-metadata-menu-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-metadata-menu-item.obj `if test -f 'metadata-menu-item.c'; then $(CYGPATH_W) 'metadata-menu-item.c'; else $(CYGPATH_W) '$(srcdir)/metadata-menu-item.c'; fi`
+
+indicator_sound_service-player-controller.o: player-controller.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-controller.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-player-controller.Tpo -c -o indicator_sound_service-player-controller.o `test -f 'player-controller.c' || echo '$(srcdir)/'`player-controller.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-player-controller.Tpo $(DEPDIR)/indicator_sound_service-player-controller.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='player-controller.c' object='indicator_sound_service-player-controller.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-controller.o `test -f 'player-controller.c' || echo '$(srcdir)/'`player-controller.c
+
+indicator_sound_service-player-controller.obj: player-controller.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-controller.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-player-controller.Tpo -c -o indicator_sound_service-player-controller.obj `if test -f 'player-controller.c'; then $(CYGPATH_W) 'player-controller.c'; else $(CYGPATH_W) '$(srcdir)/player-controller.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-player-controller.Tpo $(DEPDIR)/indicator_sound_service-player-controller.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='player-controller.c' object='indicator_sound_service-player-controller.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-controller.obj `if test -f 'player-controller.c'; then $(CYGPATH_W) 'player-controller.c'; else $(CYGPATH_W) '$(srcdir)/player-controller.c'; fi`
+
+indicator_sound_service-mpris-controller-v2.o: mpris-controller-v2.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-mpris-controller-v2.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-mpris-controller-v2.Tpo -c -o indicator_sound_service-mpris-controller-v2.o `test -f 'mpris-controller-v2.c' || echo '$(srcdir)/'`mpris-controller-v2.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-mpris-controller-v2.Tpo $(DEPDIR)/indicator_sound_service-mpris-controller-v2.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpris-controller-v2.c' object='indicator_sound_service-mpris-controller-v2.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-mpris-controller-v2.o `test -f 'mpris-controller-v2.c' || echo '$(srcdir)/'`mpris-controller-v2.c
+
+indicator_sound_service-mpris-controller-v2.obj: mpris-controller-v2.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-mpris-controller-v2.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-mpris-controller-v2.Tpo -c -o indicator_sound_service-mpris-controller-v2.obj `if test -f 'mpris-controller-v2.c'; then $(CYGPATH_W) 'mpris-controller-v2.c'; else $(CYGPATH_W) '$(srcdir)/mpris-controller-v2.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-mpris-controller-v2.Tpo $(DEPDIR)/indicator_sound_service-mpris-controller-v2.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpris-controller-v2.c' object='indicator_sound_service-mpris-controller-v2.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-mpris-controller-v2.obj `if test -f 'mpris-controller-v2.c'; then $(CYGPATH_W) 'mpris-controller-v2.c'; else $(CYGPATH_W) '$(srcdir)/mpris-controller-v2.c'; fi`
+
+indicator_sound_service-mpris-controller.o: mpris-controller.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-mpris-controller.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-mpris-controller.Tpo -c -o indicator_sound_service-mpris-controller.o `test -f 'mpris-controller.c' || echo '$(srcdir)/'`mpris-controller.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-mpris-controller.Tpo $(DEPDIR)/indicator_sound_service-mpris-controller.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpris-controller.c' object='indicator_sound_service-mpris-controller.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-mpris-controller.o `test -f 'mpris-controller.c' || echo '$(srcdir)/'`mpris-controller.c
+
+indicator_sound_service-mpris-controller.obj: mpris-controller.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-mpris-controller.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-mpris-controller.Tpo -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`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-mpris-controller.Tpo $(DEPDIR)/indicator_sound_service-mpris-controller.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpris-controller.c' object='indicator_sound_service-mpris-controller.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-mpris-controller.obj `if test -f 'mpris-controller.c'; then $(CYGPATH_W) 'mpris-controller.c'; else $(CYGPATH_W) '$(srcdir)/mpris-controller.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
@@ -802,6 +970,13 @@ sound-service-client.h: $(srcdir)/sound-service.xml
--output=sound-service-client.h \
$(srcdir)/sound-service.xml
+####################################################################
+# Sound Service
+####################################################################
+
+#################
+# dbus interface
+#################
sound-service-server.h: $(srcdir)/sound-service.xml
dbus-binding-tool \
--prefix=_sound_service_server \
@@ -809,6 +984,12 @@ sound-service-server.h: $(srcdir)/sound-service.xml
--output=sound-service-server.h \
$(srcdir)/sound-service.xml
+ $(MAINTAINER_VALAFLAGS)
+
+music_bridge_vala.stamp $(music_bridge_APIFILES): $(music_bridge_VALASOURCES)
+ $(AM_V_GEN) $(VALAC) $(music_bridge_VALAFLAGS) $^
+ touch music_bridge_vala.stamp
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/common-defs.h b/src/common-defs.h
index 9be1da5..014d864 100644
--- a/src/common-defs.h
+++ b/src/common-defs.h
@@ -24,6 +24,13 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#define SIGNAL_SINK_MUTE_UPDATE "SinkMuteUpdate"
#define SIGNAL_SINK_AVAILABLE_UPDATE "SinkAvailableUpdate"
-// DBUS items
-#define DBUSMENU_SLIDER_MENUITEM_TYPE "x-canonical-ido-slider-item"
-#define DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME "volume"
+/* 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_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"
diff --git a/src/dbus-menu-manager.c b/src/dbus-menu-manager.c
index e084bb1..9d62adb 100644
--- a/src/dbus-menu-manager.c
+++ b/src/dbus-menu-manager.c
@@ -25,7 +25,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <dbus/dbus-glib-bindings.h>
#include <libdbusmenu-glib/server.h>
-#include <libdbusmenu-glib/menuitem.h>
#include <libdbusmenu-glib/client.h>
#include "dbus-menu-manager.h"
@@ -60,7 +59,7 @@ static void refresh_menu();
/**
setup:
**/
-void dbus_menu_manager_setup()
+DbusmenuMenuitem* dbus_menu_manager_setup()
{
root_menuitem = dbusmenu_menuitem_new();
g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem));
@@ -72,6 +71,7 @@ void dbus_menu_manager_setup()
DbusmenuServer *server = dbusmenu_server_new(INDICATOR_SOUND_DBUS_OBJECT);
dbusmenu_server_set_root(server, root_menuitem);
establish_pulse_activities(dbus_interface);
+ return root_menuitem;
}
/**
diff --git a/src/dbus-menu-manager.h b/src/dbus-menu-manager.h
index 5f49e5f..a5286ca 100644
--- a/src/dbus-menu-manager.h
+++ b/src/dbus-menu-manager.h
@@ -1,6 +1,8 @@
#ifndef __INCLUDE_DBUS_MENU_MANAGER_H__
#define __INCLUDE_DBUS_MENU_MANAGER_H__
+#include <libdbusmenu-glib/menuitem.h>
+
/*
This handles the management of the dbusmeneu items.
Copyright 2010 Canonical Ltd.
@@ -21,7 +23,7 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-void dbus_menu_manager_setup();
+DbusmenuMenuitem* dbus_menu_manager_setup();
void dbus_menu_manager_teardown();
void dbus_menu_manager_update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_muted, gdouble current_vol);
// TODO update pa_state should incorporate the method below !
diff --git a/src/indicator-sound.c b/src/indicator-sound.c
index 18f48d8..9f7e136 100755
--- a/src/indicator-sound.c
+++ b/src/indicator-sound.c
@@ -38,6 +38,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libindicator/indicator-image-helper.h>
#include "indicator-sound.h"
+#include "transport-widget.h"
+#include "metadata-widget.h"
#include "dbus-shared-names.h"
#include "sound-service-client.h"
#include "common-defs.h"
@@ -61,7 +63,7 @@ struct _IndicatorSoundClass {
//GObject instance struct
struct _IndicatorSound {
IndicatorObject parent;
- GtkWidget *slider;
+ GtkWidget *slider;
IndicatorServiceManager *service;
};
// GObject Boiler plate
@@ -91,6 +93,10 @@ static void slider_grabbed(GtkWidget *widget, gpointer user_data);
static void slider_released(GtkWidget *widget, gpointer user_data);
static void style_changed_cb(GtkWidget *widget, gpointer user_data);
+//player widgets related
+static gboolean new_transport_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+static gboolean new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+
// DBUS communication
static DBusGProxy *sound_dbus_proxy = NULL;
static void connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer userdata);
@@ -150,9 +156,9 @@ indicator_sound_class_init (IndicatorSoundClass *klass)
io_class->get_label = get_label;
io_class->get_image = get_icon;
io_class->get_menu = get_menu;
- io_class->scroll = scroll;
+ io_class->scroll = scroll;
- design_team_size = gtk_icon_size_register("design-team-size", 22, 22);
+ design_team_size = gtk_icon_size_register("design-team-size", 22, 22);
return;
}
@@ -162,17 +168,17 @@ indicator_sound_init (IndicatorSound *self)
{
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;
- blocked_id = 0;
- initial_mute = FALSE;
- device_available = TRUE;
- slider_in_direct_use = FALSE;
- exterior_vol_update = OUT_OF_RANGE;
+ prepare_state_machine();
+ prepare_blocked_animation();
+ animation_id = 0;
+ blocked_id = 0;
+ initial_mute = FALSE;
+ device_available = TRUE;
+ 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);
- return;
+ return;
}
static void
@@ -184,9 +190,9 @@ indicator_sound_dispose (GObject *object)
g_object_unref(G_OBJECT(self->service));
self->service = NULL;
}
- g_hash_table_destroy(volume_states);
+ g_hash_table_destroy(volume_states);
- free_the_animation_list();
+ free_the_animation_list();
G_OBJECT_CLASS (indicator_sound_parent_class)->dispose (object);
return;
@@ -195,11 +201,11 @@ indicator_sound_dispose (GObject *object)
static void
free_the_animation_list()
{
- 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;
- }
+ 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;
+ }
}
static void
@@ -217,9 +223,9 @@ get_label (IndicatorObject * io)
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);
+{
+ 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;
@@ -231,16 +237,16 @@ get_icon (IndicatorObject * io)
static GtkMenu *
get_menu (IndicatorObject * io)
{
- DbusmenuGtkMenu *menu = dbusmenu_gtkmenu_new(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_OBJECT);
- DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(menu);
+ DbusmenuGtkMenu *menu = dbusmenu_gtkmenu_new(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_OBJECT);
+ 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);
- g_object_set_data (G_OBJECT (client),
- "indicator", io);
- dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_SLIDER_MENUITEM_TYPE, new_slider_item);
-
- // 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);
- return GTK_MENU(menu);
+ // 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);
+ return GTK_MENU(menu);
}
static void
@@ -307,6 +313,51 @@ new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuC
return TRUE;
}
+static gboolean
+new_transport_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+{
+ g_debug("indicator-sound: new_transport_bar() called ");
+
+ GtkWidget* bar = NULL;
+
+ 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);
+ 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;
+}
+
+static gboolean
+new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+{
+ g_debug("indicator-sound: new_metadata_widget");
+
+ GtkWidget* metadata = NULL;
+
+ 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);
+
+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_metadata_widget, parent);
+
+ gtk_widget_show_all(metadata);
+
+ return TRUE;
+}
+
+//const gchar* path = dbusmenu_menuitem_property_get(new_item, DBUSMENU_METADATA_MENUITEM_IMAGE_PATH);
+
+//g_debug("New transport bar path = %s", path);
+
+
static void
connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer userdata)
{
@@ -337,11 +388,11 @@ connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer u
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();
+ // 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 {
@@ -376,34 +427,34 @@ Only called at startup.
static void
prepare_blocked_animation()
{
- gchar* blocked_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT));
- gchar* muted_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED));
+ gchar* blocked_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT));
+ gchar* muted_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_MUTED));
- GtkImage* temp_image = indicator_image_helper(muted_name);
- GdkPixbuf* mute_buf = gtk_image_get_pixbuf(temp_image);
+ GtkImage* temp_image = indicator_image_helper(muted_name);
+ GdkPixbuf* mute_buf = gtk_image_get_pixbuf(temp_image);
- temp_image = indicator_image_helper(blocked_name);
- GdkPixbuf* blocked_buf = gtk_image_get_pixbuf(temp_image);
+ temp_image = indicator_image_helper(blocked_name);
+ GdkPixbuf* blocked_buf = gtk_image_get_pixbuf(temp_image);
- if(mute_buf == NULL || blocked_buf == NULL){
- g_debug("Don bother with the animation, the theme aint got the goods !");
- return;
- }
-
- int i;
-
- // sample 51 snapshots - range : 0-256
- 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),
- 0, 0, 1, 1, GDK_INTERP_BILINEAR, MIN(255, i * 5));
- blocked_animation_list = g_list_append(blocked_animation_list, gdk_pixbuf_copy(blocked_buf));
- }
- g_object_ref_sink(mute_buf);
+ if(mute_buf == NULL || blocked_buf == NULL){
+ g_debug("Don bother with the animation, the theme aint got the goods !");
+ return;
+ }
+
+ int i;
+
+ // sample 51 snapshots - range : 0-256
+ 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),
+ 0, 0, 1, 1, GDK_INTERP_BILINEAR, MIN(255, i * 5));
+ 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_ref_sink(blocked_buf);
+ g_object_ref_sink(blocked_buf);
g_object_unref(blocked_buf);
}
@@ -411,26 +462,26 @@ prepare_blocked_animation()
gint
get_state()
{
- return current_state;
+ return current_state;
}
gchar*
get_state_image_name(gint state)
{
- return g_hash_table_lookup(volume_states, GINT_TO_POINTER(state));
+ return g_hash_table_lookup(volume_states, GINT_TO_POINTER(state));
}
void
prepare_for_tests(IndicatorObject *io)
{
- prepare_state_machine();
- get_icon(io);
+ prepare_state_machine();
+ get_icon(io);
}
void
tidy_up_hash()
{
- g_hash_table_destroy(volume_states);
+ g_hash_table_destroy(volume_states);
}
static void
@@ -438,13 +489,13 @@ update_state(const gint state)
{
/* g_debug("update state beginning - previous_state = %i", previous_state);*/
- previous_state = current_state;
+ previous_state = current_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));
- indicator_image_helper_update(speaker_image, image_name);
+ current_state = state;
+ gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));
+ indicator_image_helper_update(speaker_image, image_name);
}
@@ -645,7 +696,6 @@ catch_signal_sink_availability_update(DBusGProxy *proxy, gboolean available_valu
/*******************************************************************/
//UI callbacks
/******************************************************************/
-
/**
value_changed_event_cb:
This callback will get triggered irregardless of whether its a user change or a programmatic change.
@@ -692,94 +742,93 @@ key_press_cb:
static gboolean
key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data)
{
- gboolean digested = FALSE;
+ gboolean digested = FALSE;
- GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
- GtkRange* range = (GtkRange*)slider;
- gdouble current_value = gtk_range_get_value(range);
- gdouble new_value = current_value;
- const gdouble five_percent = 5;
- GtkWidget *menuitem;
-
- menuitem = GTK_MENU_SHELL (widget)->active_menu_item;
- if(IDO_IS_SCALE_MENU_ITEM(menuitem) == TRUE)
+ GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
+ GtkRange* range = (GtkRange*)slider;
+ gdouble current_value = gtk_range_get_value(range);
+ gdouble new_value = current_value;
+ const gdouble five_percent = 5;
+ GtkWidget *menuitem;
+
+ menuitem = GTK_MENU_SHELL (widget)->active_menu_item;
+ 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
+ {
+ 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:
+ digested = TRUE;
+ new_value = current_value + five_percent;
+ break;
+ case GDK_minus:
+ digested = TRUE;
+ new_value = current_value - five_percent;
+ break;
+ default:
+ break;
+ }
+
+ new_value = CLAMP(new_value, 0, 100);
+ if(new_value != current_value && current_state != STATE_MUTED)
{
- switch(event->keyval)
- {
- case GDK_Right:
- 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_plus:
- digested = TRUE;
- new_value = current_value + five_percent;
- break;
- case GDK_minus:
- digested = TRUE;
- new_value = current_value - five_percent;
- break;
- default:
- break;
- }
-
- new_value = CLAMP(new_value, 0, 100);
- 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.
- exterior_vol_update = OUT_OF_RANGE;
- gtk_range_set_value(range, new_value);
- }
+ 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.
+ exterior_vol_update = OUT_OF_RANGE;
+ gtk_range_set_value(range, new_value);
}
- return digested;
+ }
+ return digested;
}
static void
style_changed_cb(GtkWidget *widget, gpointer user_data)
{
- g_debug("Just caught a style change event");
- update_state(current_state);
- reset_mute_blocking_animation();
- update_state(current_state);
- free_the_animation_list();
- prepare_blocked_animation();
+ g_debug("Just caught a style change event");
+ update_state(current_state);
+ reset_mute_blocking_animation();
+ update_state(current_state);
+ free_the_animation_list();
+ prepare_blocked_animation();
}
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));
+ 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;
- }
- gtk_range_set_value (GTK_RANGE (sound->slider),
- value);
+ 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/metadata-menu-item.c b/src/metadata-menu-item.c
new file mode 100644
index 0000000..f111baa
--- /dev/null
+++ b/src/metadata-menu-item.c
@@ -0,0 +1,186 @@
+/* metadata-menu-item.c generated by valac, the Vala compiler
+ * generated from metadata-menu-item.vala, do not modify */
+
+
+#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_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))
+#define IS_METADATA_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_METADATA_MENUITEM))
+#define IS_METADATA_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_METADATA_MENUITEM))
+#define METADATA_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_METADATA_MENUITEM, MetadataMenuitemClass))
+
+typedef struct _MetadataMenuitem MetadataMenuitem;
+typedef struct _MetadataMenuitemClass MetadataMenuitemClass;
+typedef struct _MetadataMenuitemPrivate MetadataMenuitemPrivate;
+#define _g_free0(var) (var = (g_free (var), NULL))
+
+struct _MetadataMenuitem {
+ DbusmenuMenuitem parent_instance;
+ MetadataMenuitemPrivate * priv;
+};
+
+struct _MetadataMenuitemClass {
+ DbusmenuMenuitemClass parent_class;
+};
+
+
+static gpointer metadata_menuitem_parent_class = NULL;
+
+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"
+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);
+
+
+
+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);
+ return self;
+}
+
+
+MetadataMenuitem* metadata_menuitem_new (void) {
+ return metadata_menuitem_construct (TYPE_METADATA_MENUITEM);
+}
+
+
+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;
+}
+
+
+void metadata_menuitem_update (MetadataMenuitem* self, GeeHashMap* data) {
+ char* _tmp1_;
+ 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_);
+ _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 _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* 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_;
+ 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;
+}
+
+
+static void metadata_menuitem_instance_init (MetadataMenuitem * self) {
+}
+
+
+GType metadata_menuitem_get_type (void) {
+ static volatile gsize metadata_menuitem_type_id__volatile = 0;
+ 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);
+ g_once_init_leave (&metadata_menuitem_type_id__volatile, metadata_menuitem_type_id);
+ }
+ return metadata_menuitem_type_id__volatile;
+}
+
+
+
+
diff --git a/src/metadata-menu-item.vala b/src/metadata-menu-item.vala
new file mode 100644
index 0000000..82926b1
--- /dev/null
+++ b/src/metadata-menu-item.vala
@@ -0,0 +1,40 @@
+using Dbusmenu;
+using Gee;
+
+public class MetadataMenuitem : Dbusmenu.Menuitem
+{
+ /* 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);
+ }
+
+ public void update(HashMap<string, string> data)
+ {
+ 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")));
+ }
+
+ public static string sanitize_image_path(string path)
+ {
+ string result = path.strip();
+ if(result.has_prefix("file:///")){
+ result = result.slice(7, result.len());
+ }
+ debug("Sanitize image path - result = %s", result);
+ return result;
+ }
+
+ 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
new file mode 100644
index 0000000..c4d3b50
--- /dev/null
+++ b/src/metadata-widget.c
@@ -0,0 +1,214 @@
+/*
+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/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include "metadata-widget.h"
+#include "common-defs.h"
+#include <gtk/gtk.h>
+
+static DbusmenuMenuitem* twin_item;
+
+typedef struct _MetadataWidgetPrivate MetadataWidgetPrivate;
+
+struct _MetadataWidgetPrivate
+{
+ GtkWidget* hbox;
+ GtkWidget* album_art;
+ gchar* image_path;
+ GtkWidget* artist_label;
+ GtkWidget* piece_label;
+ GtkWidget* container_label;
+};
+
+#define METADATA_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), METADATA_WIDGET_TYPE, MetadataWidgetPrivate))
+
+/* Prototypes */
+static void metadata_widget_class_init (MetadataWidgetClass *klass);
+static void metadata_widget_init (MetadataWidget *self);
+static void metadata_widget_dispose (GObject *object);
+static void metadata_widget_finalize (GObject *object);
+// keyevent consumers
+static gboolean metadata_widget_button_press_event (GtkWidget *menuitem,
+ GdkEventButton *event);
+static gboolean metadata_widget_button_release_event (GtkWidget *menuitem,
+ GdkEventButton *event);
+// Dbusmenuitem properties update callback
+static void metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property,
+ GValue* value, gpointer userdata);
+
+static void update_album_art(MetadataWidget* self);
+
+
+G_DEFINE_TYPE (MetadataWidget, metadata_widget, GTK_TYPE_MENU_ITEM);
+
+
+
+static void
+metadata_widget_class_init (MetadataWidgetClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->button_press_event = metadata_widget_button_press_event;
+ widget_class->button_release_event = metadata_widget_button_release_event;
+
+ g_type_class_add_private (klass, sizeof (MetadataWidgetPrivate));
+
+ gobject_class->dispose = metadata_widget_dispose;
+ gobject_class->finalize = metadata_widget_finalize;
+
+}
+
+static void
+metadata_widget_init (MetadataWidget *self)
+{
+ g_debug("MetadataWidget::metadata_widget_init");
+
+ MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self);
+
+ GtkWidget *hbox;
+
+ hbox = gtk_hbox_new(TRUE, 0);
+ priv->hbox = hbox;
+
+ // image
+ priv->album_art = gtk_image_new();
+ priv->image_path = g_strdup(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_IMAGE_PATH));
+ 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);
+
+ // artist
+ GtkWidget* artist;
+ artist = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST));
+ priv->artist_label = artist;
+
+
+ // piece
+ GtkWidget* piece;
+ piece = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_PIECE));
+ priv->piece_label = piece;
+
+
+ // container
+ GtkWidget* container;
+ container = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER));
+ priv->container_label = container;
+
+ // Pack in the right order
+ gtk_box_pack_start (GTK_BOX (vbox), priv->piece_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), priv->artist_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), priv->container_label, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (priv->hbox), vbox, FALSE, FALSE, 0);
+
+ g_signal_connect(G_OBJECT(twin_item), "property-changed",
+ G_CALLBACK(metadata_widget_property_update), self);
+ gtk_widget_show_all (priv->hbox);
+ gtk_container_add (GTK_CONTAINER (self), hbox);
+
+}
+
+static void
+metadata_widget_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (metadata_widget_parent_class)->dispose (object);
+}
+
+static void
+metadata_widget_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (metadata_widget_parent_class)->finalize (object);
+}
+
+/* Suppress/consume keyevents */
+static gboolean
+metadata_widget_button_press_event (GtkWidget *menuitem,
+ GdkEventButton *event)
+{
+ g_debug("MetadataWidget::menu_press_event");
+ return TRUE;
+}
+
+static gboolean
+metadata_widget_button_release_event (GtkWidget *menuitem,
+ GdkEventButton *event)
+{
+ g_debug("MetadataWidget::menu_release_event");
+ return TRUE;
+}
+
+// TODO: Manage empty/mangled music details <unknown artist> etc.
+static void
+metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property,
+ GValue* value, gpointer userdata)
+{
+ g_return_if_fail (IS_METADATA_WIDGET (userdata));
+
+ MetadataWidget* mitem = METADATA_WIDGET(userdata);
+ MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(mitem);
+
+ 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){
+ 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){
+ 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){
+ if(priv->image_path != NULL){
+ g_free(priv->image_path);
+ }
+
+ priv->image_path = g_value_dup_string(value);
+
+ if(priv->image_path != NULL){
+ update_album_art(mitem);
+ }
+ }
+}
+
+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);
+ 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);
+}
+
+
+ /**
+ * transport_new:
+ * @returns: a new #MetadataWidget.
+ **/
+GtkWidget*
+metadata_widget_new(DbusmenuMenuitem *item)
+{
+ twin_item = item;
+ return g_object_new(METADATA_WIDGET_TYPE, NULL);
+}
+
diff --git a/src/metadata-widget.h b/src/metadata-widget.h
new file mode 100644
index 0000000..6f1d4d3
--- /dev/null
+++ b/src/metadata-widget.h
@@ -0,0 +1,51 @@
+/*
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Conor Curran <conor.curran@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __METADATA_WIDGET_H__
+#define __METADATA_WIDGET_H__
+
+#include <gtk/gtkmenuitem.h>
+#include <libdbusmenu-gtk/menu.h>
+
+G_BEGIN_DECLS
+
+#define METADATA_WIDGET_TYPE (metadata_widget_get_type ())
+#define METADATA_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), METADATA_WIDGET_TYPE, MetadataWidget))
+#define METADATA_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), METADATA_WIDGET_TYPE, MetadataWidgetClass))
+#define IS_METADATA_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), METADATA_WIDGET_TYPE))
+#define IS_METADATA_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), METADATA_WIDGET_TYPE))
+#define METADATA_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), METADATA_WIDGET_TYPE, MetadataWidgetClass))
+
+typedef struct _MetadataWidget MetadataWidget;
+typedef struct _MetadataWidgetClass MetadataWidgetClass;
+
+struct _MetadataWidgetClass {
+ GtkMenuItemClass parent_class;
+};
+
+struct _MetadataWidget {
+ GtkMenuItem parent;
+};
+
+GType metadata_widget_get_type (void);
+GtkWidget* metadata_widget_new(DbusmenuMenuitem *twin_item);
+
+G_END_DECLS
+
+#endif
+
diff --git a/src/mpris-controller-v2.c b/src/mpris-controller-v2.c
new file mode 100644
index 0000000..4a48165
--- /dev/null
+++ b/src/mpris-controller-v2.c
@@ -0,0 +1,135 @@
+/* mpris-controller-v2.c generated by valac, the Vala compiler
+ * generated from mpris-controller-v2.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:
+ 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 <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#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;
+typedef struct _MprisControllerPrivate MprisControllerPrivate;
+
+#define TYPE_MPRIS_CONTROLLER_V2 (mpris_controller_v2_get_type ())
+#define MPRIS_CONTROLLER_V2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2))
+#define MPRIS_CONTROLLER_V2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2Class))
+#define IS_MPRIS_CONTROLLER_V2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MPRIS_CONTROLLER_V2))
+#define IS_MPRIS_CONTROLLER_V2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MPRIS_CONTROLLER_V2))
+#define MPRIS_CONTROLLER_V2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2Class))
+
+typedef struct _MprisControllerV2 MprisControllerV2;
+typedef struct _MprisControllerV2Class MprisControllerV2Class;
+typedef struct _MprisControllerV2Private MprisControllerV2Private;
+
+#define TYPE_PLAYER_CONTROLLER (player_controller_get_type ())
+#define PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_CONTROLLER, PlayerController))
+#define PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+#define IS_PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_CONTROLLER))
+#define IS_PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_CONTROLLER))
+#define PLAYER_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+
+typedef struct _PlayerController PlayerController;
+typedef struct _PlayerControllerClass PlayerControllerClass;
+
+struct _MprisController {
+ GObject parent_instance;
+ MprisControllerPrivate * priv;
+ DBusGProxy* mpris_player;
+};
+
+struct _MprisControllerClass {
+ GObjectClass parent_class;
+};
+
+struct _MprisControllerV2 {
+ MprisController parent_instance;
+ MprisControllerV2Private * priv;
+};
+
+struct _MprisControllerV2Class {
+ MprisControllerClass parent_class;
+};
+
+
+static gpointer mpris_controller_v2_parent_class = NULL;
+
+GType mpris_controller_get_type (void);
+GType mpris_controller_v2_get_type (void);
+enum {
+ MPRIS_CONTROLLER_V2_DUMMY_PROPERTY
+};
+GType player_controller_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);
+MprisControllerV2* mpris_controller_v2_new (const char* name, PlayerController* controller);
+MprisControllerV2* mpris_controller_v2_construct (GType object_type, const char* name, PlayerController* controller);
+
+
+
+MprisControllerV2* mpris_controller_v2_construct (GType object_type, const char* name, PlayerController* controller) {
+ MprisControllerV2 * self;
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (controller != NULL, NULL);
+ self = (MprisControllerV2*) mpris_controller_construct (object_type, name, controller, "org.mpris.MediaPlayer.Player");
+ return self;
+}
+
+
+MprisControllerV2* mpris_controller_v2_new (const char* name, PlayerController* controller) {
+ return mpris_controller_v2_construct (TYPE_MPRIS_CONTROLLER_V2, name, controller);
+}
+
+
+static void mpris_controller_v2_class_init (MprisControllerV2Class * klass) {
+ mpris_controller_v2_parent_class = g_type_class_peek_parent (klass);
+}
+
+
+static void mpris_controller_v2_instance_init (MprisControllerV2 * self) {
+}
+
+
+GType mpris_controller_v2_get_type (void) {
+ static volatile gsize mpris_controller_v2_type_id__volatile = 0;
+ if (g_once_init_enter (&mpris_controller_v2_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (MprisControllerV2Class), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) mpris_controller_v2_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (MprisControllerV2), 0, (GInstanceInitFunc) mpris_controller_v2_instance_init, NULL };
+ GType mpris_controller_v2_type_id;
+ mpris_controller_v2_type_id = g_type_register_static (TYPE_MPRIS_CONTROLLER, "MprisControllerV2", &g_define_type_info, 0);
+ g_once_init_leave (&mpris_controller_v2_type_id__volatile, mpris_controller_v2_type_id);
+ }
+ return mpris_controller_v2_type_id__volatile;
+}
+
+
+
+
diff --git a/src/mpris-controller-v2.vala b/src/mpris-controller-v2.vala
new file mode 100644
index 0000000..0392cfc
--- /dev/null
+++ b/src/mpris-controller-v2.vala
@@ -0,0 +1,28 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+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;
+
+public class MprisControllerV2 : MprisController
+{
+ public MprisControllerV2(string name, PlayerController controller){
+ base(name, controller, "org.mpris.MediaPlayer.Player");
+ }
+
+}
diff --git a/src/mpris-controller.c b/src/mpris-controller.c
new file mode 100644
index 0000000..594cdf2
--- /dev/null
+++ b/src/mpris-controller.c
@@ -0,0 +1,380 @@
+/* mpris-controller.c generated by valac, the Vala compiler
+ * generated from mpris-controller.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:
+ 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 <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gee.h>
+
+
+#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;
+typedef struct _MprisControllerPrivate MprisControllerPrivate;
+
+#define TYPE_PLAYER_CONTROLLER (player_controller_get_type ())
+#define PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_CONTROLLER, PlayerController))
+#define PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+#define IS_PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_CONTROLLER))
+#define IS_PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_CONTROLLER))
+#define PLAYER_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+
+typedef struct _PlayerController PlayerController;
+typedef struct _PlayerControllerClass PlayerControllerClass;
+#define _dbus_g_connection_unref0(var) ((var == NULL) ? NULL : (var = (dbus_g_connection_unref (var), NULL)))
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+
+#define MPRIS_CONTROLLER_TYPE_STATUS (mpris_controller_status_get_type ())
+typedef struct _MprisControllerstatus MprisControllerstatus;
+#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
+
+struct _MprisController {
+ GObject parent_instance;
+ MprisControllerPrivate * priv;
+ DBusGProxy* mpris_player;
+};
+
+struct _MprisControllerClass {
+ GObjectClass parent_class;
+};
+
+struct _MprisControllerPrivate {
+ DBusGConnection* connection;
+ PlayerController* controller;
+};
+
+struct _MprisControllerstatus {
+ gint32 playback;
+ gint32 shuffle;
+ gint32 repeat;
+ gint32 endless;
+};
+
+
+static gpointer mpris_controller_parent_class = NULL;
+
+GType mpris_controller_get_type (void);
+GType player_controller_get_type (void);
+#define MPRIS_CONTROLLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_MPRIS_CONTROLLER, MprisControllerPrivate))
+enum {
+ MPRIS_CONTROLLER_DUMMY_PROPERTY
+};
+static void mpris_controller_onTrackChange (MprisController* self, DBusGProxy* mpris_client, GHashTable* ht);
+static void _mpris_controller_onTrackChange_dynamic_TrackChange0_ (DBusGProxy* _sender, GHashTable* ht, gpointer self);
+void _dynamic_TrackChange1_connect (gpointer obj, const char * signal_name, GCallback handler, gpointer data);
+static GType mpris_controller_status_get_type (void) G_GNUC_UNUSED;
+static MprisControllerstatus* mpris_controller_status_dup (const MprisControllerstatus* self);
+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);
+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);
+void mpris_controller_toggle_playback (MprisController* self, gboolean state);
+static void mpris_controller_finalize (GObject* obj);
+
+
+static void g_cclosure_user_marshal_VOID__BOXED (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+
+static gpointer _g_object_ref0 (gpointer self) {
+ return self ? g_object_ref (self) : NULL;
+}
+
+
+static void _mpris_controller_onTrackChange_dynamic_TrackChange0_ (DBusGProxy* _sender, GHashTable* ht, gpointer self) {
+ mpris_controller_onTrackChange (self, _sender, ht);
+}
+
+
+void _dynamic_TrackChange1_connect (gpointer obj, const char * signal_name, GCallback handler, gpointer data) {
+ dbus_g_object_register_marshaller (g_cclosure_user_marshal_VOID__BOXED, G_TYPE_NONE, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (obj, "TrackChange", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (obj, signal_name, handler, data, NULL);
+}
+
+
+static void _mpris_controller_onStatusChange_dynamic_StatusChange2_ (DBusGProxy* _sender, MprisControllerstatus* st, gpointer self) {
+ mpris_controller_onStatusChange (self, _sender, st);
+}
+
+
+void _dynamic_StatusChange3_connect (gpointer obj, const char * signal_name, GCallback handler, gpointer data) {
+ dbus_g_object_register_marshaller (g_cclosure_user_marshal_VOID__BOXED, G_TYPE_NONE, dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID), G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (obj, "StatusChange", dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID), G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (obj, signal_name, handler, data, NULL);
+}
+
+
+MprisController* mpris_controller_construct (GType object_type, const char* name, PlayerController* controller, const char* mpris_interface) {
+ GError * _inner_error_;
+ MprisController * self;
+ PlayerController* _tmp2_;
+ DBusGProxy* _tmp5_;
+ char* _tmp4_;
+ char* _tmp3_;
+ GeeHashMap* _tmp6_;
+ 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);
+ _inner_error_ = NULL;
+ self = (MprisController*) g_object_new (object_type, NULL);
+ {
+ DBusGConnection* _tmp0_;
+ DBusGConnection* _tmp1_;
+ _tmp0_ = dbus_g_bus_get (DBUS_BUS_SESSION, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch0_g_error;
+ }
+ self->priv->connection = (_tmp1_ = _tmp0_, _dbus_g_connection_unref0 (self->priv->connection), _tmp1_);
+ }
+ goto __finally0;
+ __catch0_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_free0 (e);
+ }
+ }
+ __finally0:
+ 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;
+ }
+ self->priv->controller = (_tmp2_ = _g_object_ref0 (controller), _g_object_unref0 (self->priv->controller), _tmp2_);
+ self->mpris_player = (_tmp5_ = dbus_g_proxy_new_for_name (self->priv->connection, _tmp4_ = g_strconcat ("org.mpris.", _tmp3_ = g_utf8_strdown (name, -1), NULL), "/Player", mpris_interface), _g_object_unref0 (self->mpris_player), _tmp5_);
+ _g_free0 (_tmp4_);
+ _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) {
+ 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_);
+ 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;
+}
+
+
+static void mpris_controller_onTrackChange (MprisController* self, DBusGProxy* mpris_client, GHashTable* ht) {
+ GeeHashMap* _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_object_unref0 (_tmp0_);
+}
+
+
+static void _dynamic_Play1 (DBusGProxy* self, GError** error) {
+ dbus_g_proxy_call (self, "Play", error, G_TYPE_INVALID, G_TYPE_INVALID);
+ if (*error) {
+ return;
+ }
+}
+
+
+static void _dynamic_Pause2 (DBusGProxy* self, GError** error) {
+ dbus_g_proxy_call (self, "Pause", error, G_TYPE_INVALID, G_TYPE_INVALID);
+ if (*error) {
+ return;
+ }
+}
+
+
+void mpris_controller_toggle_playback (MprisController* self, gboolean state) {
+ GError * _inner_error_;
+ 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_);
+ 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_);
+ 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;
+ }
+ }
+}
+
+
+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 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 MprisControllerstatus* mpris_controller_status_dup (const MprisControllerstatus* self) {
+ MprisControllerstatus* dup;
+ dup = g_new0 (MprisControllerstatus, 1);
+ memcpy (dup, self, sizeof (MprisControllerstatus));
+ return dup;
+}
+
+
+static void mpris_controller_status_free (MprisControllerstatus* self) {
+ g_free (self);
+}
+
+
+static GType mpris_controller_status_get_type (void) {
+ static volatile gsize mpris_controller_status_type_id__volatile = 0;
+ if (g_once_init_enter (&mpris_controller_status_type_id__volatile)) {
+ GType mpris_controller_status_type_id;
+ mpris_controller_status_type_id = g_boxed_type_register_static ("MprisControllerstatus", (GBoxedCopyFunc) mpris_controller_status_dup, (GBoxedFreeFunc) mpris_controller_status_free);
+ g_once_init_leave (&mpris_controller_status_type_id__volatile, mpris_controller_status_type_id);
+ }
+ return mpris_controller_status_type_id__volatile;
+}
+
+
+static void mpris_controller_class_init (MprisControllerClass * klass) {
+ mpris_controller_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (MprisControllerPrivate));
+ G_OBJECT_CLASS (klass)->finalize = mpris_controller_finalize;
+}
+
+
+static void mpris_controller_instance_init (MprisController * self) {
+ self->priv = MPRIS_CONTROLLER_GET_PRIVATE (self);
+}
+
+
+static void mpris_controller_finalize (GObject* obj) {
+ MprisController * self;
+ self = MPRIS_CONTROLLER (obj);
+ _dbus_g_connection_unref0 (self->priv->connection);
+ _g_object_unref0 (self->mpris_player);
+ _g_object_unref0 (self->priv->controller);
+ G_OBJECT_CLASS (mpris_controller_parent_class)->finalize (obj);
+}
+
+
+GType mpris_controller_get_type (void) {
+ static volatile gsize mpris_controller_type_id__volatile = 0;
+ if (g_once_init_enter (&mpris_controller_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (MprisControllerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) mpris_controller_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (MprisController), 0, (GInstanceInitFunc) mpris_controller_instance_init, NULL };
+ GType mpris_controller_type_id;
+ mpris_controller_type_id = g_type_register_static (G_TYPE_OBJECT, "MprisController", &g_define_type_info, 0);
+ g_once_init_leave (&mpris_controller_type_id__volatile, mpris_controller_type_id);
+ }
+ return mpris_controller_type_id__volatile;
+}
+
+
+
+static void g_cclosure_user_marshal_VOID__BOXED (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__BOXED) (gpointer data1, gpointer arg_1, gpointer data2);
+ register GMarshalFunc_VOID__BOXED callback;
+ register GCClosure * cc;
+ register gpointer data1, data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 2);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__BOXED) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, g_value_get_boxed (param_values + 1), data2);
+}
+
+
+
diff --git a/src/mpris-controller.vala b/src/mpris-controller.vala
new file mode 100644
index 0000000..7e65594
--- /dev/null
+++ b/src/mpris-controller.vala
@@ -0,0 +1,101 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+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;
+
+
+public class MprisController : GLib.Object
+{
+ private DBus.Connection connection;
+ public dynamic DBus.Object mpris_player;
+ private PlayerController controller;
+ struct status {
+ public int32 playback;
+ public int32 shuffle;
+ public int32 repeat;
+ public int32 endless;
+ }
+
+
+ public MprisController(string name, PlayerController controller, string mpris_interface="org.freedesktop.MediaPlayer"){
+ try {
+ this.connection = DBus.Bus.get (DBus.BusType.SESSION);
+ } catch (Error e) {
+ error("Problems connecting to the session bus - %s", e.message);
+ }
+ 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());
+ }
+
+ public HashMap<string, string> get_track_data()
+ {
+ return format_metadata(this.mpris_player.GetMetadata());
+ }
+
+ private void onTrackChange(dynamic DBus.Object mpris_client, HashTable<string,Value?> ht)
+ {
+ this.controller.update_playing_info(format_metadata(ht));
+ }
+
+ /**
+ * TRUE => Playing
+ * FALSE => Paused
+ **/
+ public void toggle_playback(bool state)
+ {
+ if(state == true){
+ debug("about to play");
+ this.mpris_player.Play();
+ }
+ else{
+ debug("about to pause");
+ this.mpris_player.Pause();
+ }
+ }
+
+ 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();
+ }
+
+ 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
new file mode 100644
index 0000000..c08a1e7
--- /dev/null
+++ b/src/music-player-bridge.c
@@ -0,0 +1,362 @@
+/* music-player-bridge.c generated by valac, the Vala compiler
+ * 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:
+ 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 <libindicate/./indicator-messages.h>
+#include <libindicate/./indicator.h>
+#include <libindicate/./interests.h>
+#include <libindicate/./listener.h>
+#include <libindicate/./server.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 <stdlib.h>
+#include <string.h>
+
+
+#define TYPE_MUSIC_PLAYER_BRIDGE (music_player_bridge_get_type ())
+#define MUSIC_PLAYER_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MUSIC_PLAYER_BRIDGE, MusicPlayerBridge))
+#define MUSIC_PLAYER_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MUSIC_PLAYER_BRIDGE, MusicPlayerBridgeClass))
+#define IS_MUSIC_PLAYER_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MUSIC_PLAYER_BRIDGE))
+#define IS_MUSIC_PLAYER_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MUSIC_PLAYER_BRIDGE))
+#define MUSIC_PLAYER_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MUSIC_PLAYER_BRIDGE, MusicPlayerBridgeClass))
+
+typedef struct _MusicPlayerBridge MusicPlayerBridge;
+typedef struct _MusicPlayerBridgeClass MusicPlayerBridgeClass;
+typedef struct _MusicPlayerBridgePrivate MusicPlayerBridgePrivate;
+
+#define TYPE_PLAYER_CONTROLLER (player_controller_get_type ())
+#define PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_CONTROLLER, PlayerController))
+#define PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+#define IS_PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_CONTROLLER))
+#define IS_PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_CONTROLLER))
+#define PLAYER_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+
+typedef struct _PlayerController PlayerController;
+typedef struct _PlayerControllerClass PlayerControllerClass;
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+
+struct _MusicPlayerBridge {
+ GObject parent_instance;
+ MusicPlayerBridgePrivate * priv;
+};
+
+struct _MusicPlayerBridgeClass {
+ GObjectClass parent_class;
+};
+
+struct _MusicPlayerBridgePrivate {
+ IndicateListener* listener;
+ DbusmenuMenuitem* root_menu;
+ GeeHashMap* registered_clients;
+};
+
+
+static gpointer music_player_bridge_parent_class = NULL;
+
+GType music_player_bridge_get_type (void);
+GType player_controller_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
+};
+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);
+static void _music_player_bridge_on_indicator_removed_indicate_listener_indicator_removed (IndicateListener* _sender, IndicateListenerServer* object, IndicateListenerIndicator* p0, gpointer self);
+void music_player_bridge_on_indicator_modified (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0, const char* s);
+static void _music_player_bridge_on_indicator_modified_indicate_listener_indicator_modified (IndicateListener* _sender, IndicateListenerServer* object, IndicateListenerIndicator* p0, const char* p1, gpointer self);
+void music_player_bridge_on_server_added (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type);
+static void _music_player_bridge_on_server_added_indicate_listener_server_added (IndicateListener* _sender, IndicateListenerServer* object, const char* p0, gpointer self);
+void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type);
+static void _music_player_bridge_on_server_removed_indicate_listener_server_removed (IndicateListener* _sender, IndicateListenerServer* object, const char* p0, gpointer self);
+void music_player_bridge_on_server_count_changed (MusicPlayerBridge* self, IndicateListenerServer* object, guint i);
+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);
+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);
+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);
+static gint _vala_array_length (gpointer array);
+
+
+
+static void _music_player_bridge_on_indicator_added_indicate_listener_indicator_added (IndicateListener* _sender, IndicateListenerServer* object, IndicateListenerIndicator* p0, gpointer self) {
+ music_player_bridge_on_indicator_added (self, object, p0);
+}
+
+
+static void _music_player_bridge_on_indicator_removed_indicate_listener_indicator_removed (IndicateListener* _sender, IndicateListenerServer* object, IndicateListenerIndicator* p0, gpointer self) {
+ music_player_bridge_on_indicator_removed (self, object, p0);
+}
+
+
+static void _music_player_bridge_on_indicator_modified_indicate_listener_indicator_modified (IndicateListener* _sender, IndicateListenerServer* object, IndicateListenerIndicator* p0, const char* p1, gpointer self) {
+ music_player_bridge_on_indicator_modified (self, object, p0, p1);
+}
+
+
+static void _music_player_bridge_on_server_added_indicate_listener_server_added (IndicateListener* _sender, IndicateListenerServer* object, const char* p0, gpointer self) {
+ music_player_bridge_on_server_added (self, object, p0);
+}
+
+
+static void _music_player_bridge_on_server_removed_indicate_listener_server_removed (IndicateListener* _sender, IndicateListenerServer* object, const char* p0, gpointer self) {
+ music_player_bridge_on_server_removed (self, object, p0);
+}
+
+
+static void _music_player_bridge_on_server_count_changed_indicate_listener_server_count_changed (IndicateListener* _sender, IndicateListenerServer* object, guint p0, gpointer self) {
+ music_player_bridge_on_server_count_changed (self, object, p0);
+}
+
+
+MusicPlayerBridge* music_player_bridge_construct (GType object_type) {
+ MusicPlayerBridge * self;
+ GeeHashMap* _tmp0_;
+ IndicateListener* _tmp1_;
+ 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_);
+ 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);
+ g_signal_connect_object (self->priv->listener, "server-added", (GCallback) _music_player_bridge_on_server_added_indicate_listener_server_added, self, 0);
+ g_signal_connect_object (self->priv->listener, "server-removed", (GCallback) _music_player_bridge_on_server_removed_indicate_listener_server_removed, self, 0);
+ g_signal_connect_object (self->priv->listener, "server-count-changed", (GCallback) _music_player_bridge_on_server_count_changed_indicate_listener_server_count_changed, self, 0);
+ return self;
+}
+
+
+MusicPlayerBridge* music_player_bridge_new (void) {
+ return music_player_bridge_construct (TYPE_MUSIC_PLAYER_BRIDGE);
+}
+
+
+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) {
+ 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);
+}
+
+
+void music_player_bridge_on_server_added (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type) {
+ gint _tmp1__length1;
+ char** _tmp1_;
+ char** _tmp0_;
+ char* _tmp2_;
+ char* client_name;
+ 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" \
+" value %s", type);
+ if (music_player_bridge_server_is_not_of_interest (self, type)) {
+ return;
+ }
+ client_name = (_tmp2_ = g_strdup ((_tmp1_ = _tmp0_ = g_strsplit (type, ".", 0), _tmp1__length1 = _vala_array_length (_tmp0_), _tmp1_)[1]), _tmp1_ = (_vala_array_free (_tmp1_, _tmp1__length1, (GDestroyNotify) g_free), NULL), _tmp2_);
+ if (self->priv->root_menu != NULL) {
+ _tmp3_ = client_name != NULL;
+ } else {
+ _tmp3_ = FALSE;
+ }
+ if (_tmp3_) {
+ PlayerController* ctrl;
+ 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" \
+"ered with us", client_name);
+ _g_object_unref0 (ctrl);
+ }
+ _g_free0 (client_name);
+}
+
+
+void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateListenerServer* object, const char* type) {
+ gint _tmp1__length1;
+ char** _tmp1_;
+ char** _tmp0_;
+ char* _tmp2_;
+ char* client_name;
+ 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" \
+"th value %s", type);
+ if (music_player_bridge_server_is_not_of_interest (self, type)) {
+ return;
+ }
+ client_name = (_tmp2_ = g_strdup ((_tmp1_ = _tmp0_ = g_strsplit (type, ".", 0), _tmp1__length1 = _vala_array_length (_tmp0_), _tmp1_)[1]), _tmp1_ = (_vala_array_free (_tmp1_, _tmp1__length1, (GDestroyNotify) g_free), NULL), _tmp2_);
+ if (self->priv->root_menu != NULL) {
+ _tmp3_ = client_name != NULL;
+ } else {
+ _tmp3_ = FALSE;
+ }
+ if (_tmp3_) {
+ PlayerController* _tmp4_;
+ 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" \
+" %s from registered_clients", client_name);
+ }
+ _g_free0 (client_name);
+}
+
+
+static gboolean string_contains (const char* self, const char* needle) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (needle != NULL, FALSE);
+ result = strstr (self, needle) != NULL;
+ return result;
+}
+
+
+static gboolean music_player_bridge_server_is_not_of_interest (MusicPlayerBridge* self, const char* type) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (type != NULL, FALSE);
+ if (type == NULL) {
+ result = TRUE;
+ 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");
+ result = TRUE;
+ return result;
+ }
+ result = FALSE;
+ return result;
+}
+
+
+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);
+}
+
+
+static void music_player_bridge_class_init (MusicPlayerBridgeClass * klass) {
+ music_player_bridge_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (MusicPlayerBridgePrivate));
+ G_OBJECT_CLASS (klass)->finalize = music_player_bridge_finalize;
+}
+
+
+static void music_player_bridge_instance_init (MusicPlayerBridge * self) {
+ self->priv = MUSIC_PLAYER_BRIDGE_GET_PRIVATE (self);
+}
+
+
+static void music_player_bridge_finalize (GObject* obj) {
+ MusicPlayerBridge * self;
+ self = MUSIC_PLAYER_BRIDGE (obj);
+ _g_object_unref0 (self->priv->listener);
+ _g_object_unref0 (self->priv->root_menu);
+ _g_object_unref0 (self->priv->registered_clients);
+ G_OBJECT_CLASS (music_player_bridge_parent_class)->finalize (obj);
+}
+
+
+GType music_player_bridge_get_type (void) {
+ static volatile gsize music_player_bridge_type_id__volatile = 0;
+ if (g_once_init_enter (&music_player_bridge_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (MusicPlayerBridgeClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) music_player_bridge_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (MusicPlayerBridge), 0, (GInstanceInitFunc) music_player_bridge_instance_init, NULL };
+ GType music_player_bridge_type_id;
+ music_player_bridge_type_id = g_type_register_static (G_TYPE_OBJECT, "MusicPlayerBridge", &g_define_type_info, 0);
+ g_once_init_leave (&music_player_bridge_type_id__volatile, music_player_bridge_type_id);
+ }
+ return music_player_bridge_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/music-player-bridge.h b/src/music-player-bridge.h
new file mode 100644
index 0000000..6a31b30
--- /dev/null
+++ b/src/music-player-bridge.h
@@ -0,0 +1,185 @@
+/* music-player-bridge.h generated by valac, the Vala compiler, do not modify */
+
+
+#ifndef __MUSIC_PLAYER_BRIDGE_H__
+#define __MUSIC_PLAYER_BRIDGE_H__
+
+#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>
+#include <libindicate/./listener.h>
+#include <libindicate/./server.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gee.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+
+#define TYPE_MUSIC_PLAYER_BRIDGE (music_player_bridge_get_type ())
+#define MUSIC_PLAYER_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MUSIC_PLAYER_BRIDGE, MusicPlayerBridge))
+#define MUSIC_PLAYER_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MUSIC_PLAYER_BRIDGE, MusicPlayerBridgeClass))
+#define IS_MUSIC_PLAYER_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MUSIC_PLAYER_BRIDGE))
+#define IS_MUSIC_PLAYER_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MUSIC_PLAYER_BRIDGE))
+#define MUSIC_PLAYER_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MUSIC_PLAYER_BRIDGE, MusicPlayerBridgeClass))
+
+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))
+
+typedef struct _TransportMenuitem TransportMenuitem;
+typedef struct _TransportMenuitemClass TransportMenuitemClass;
+typedef struct _TransportMenuitemPrivate TransportMenuitemPrivate;
+
+#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))
+#define IS_METADATA_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_METADATA_MENUITEM))
+#define IS_METADATA_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_METADATA_MENUITEM))
+#define METADATA_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_METADATA_MENUITEM, MetadataMenuitemClass))
+
+typedef struct _MetadataMenuitem MetadataMenuitem;
+typedef struct _MetadataMenuitemClass MetadataMenuitemClass;
+typedef struct _MetadataMenuitemPrivate MetadataMenuitemPrivate;
+
+#define TYPE_PLAYER_CONTROLLER (player_controller_get_type ())
+#define PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_CONTROLLER, PlayerController))
+#define PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+#define IS_PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_CONTROLLER))
+#define IS_PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_CONTROLLER))
+#define PLAYER_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+
+typedef struct _PlayerController PlayerController;
+typedef struct _PlayerControllerClass PlayerControllerClass;
+typedef struct _PlayerControllerPrivate PlayerControllerPrivate;
+typedef struct _MprisControllerPrivate MprisControllerPrivate;
+
+#define TYPE_MPRIS_CONTROLLER_V2 (mpris_controller_v2_get_type ())
+#define MPRIS_CONTROLLER_V2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2))
+#define MPRIS_CONTROLLER_V2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2Class))
+#define IS_MPRIS_CONTROLLER_V2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MPRIS_CONTROLLER_V2))
+#define IS_MPRIS_CONTROLLER_V2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MPRIS_CONTROLLER_V2))
+#define MPRIS_CONTROLLER_V2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2Class))
+
+typedef struct _MprisControllerV2 MprisControllerV2;
+typedef struct _MprisControllerV2Class MprisControllerV2Class;
+typedef struct _MprisControllerV2Private MprisControllerV2Private;
+
+struct _MusicPlayerBridge {
+ GObject parent_instance;
+ MusicPlayerBridgePrivate * priv;
+};
+
+struct _MusicPlayerBridgeClass {
+ GObjectClass parent_class;
+};
+
+struct _TransportMenuitem {
+ DbusmenuMenuitem parent_instance;
+ TransportMenuitemPrivate * priv;
+};
+
+struct _TransportMenuitemClass {
+ DbusmenuMenuitemClass parent_class;
+};
+
+struct _MetadataMenuitem {
+ DbusmenuMenuitem parent_instance;
+ MetadataMenuitemPrivate * priv;
+};
+
+struct _MetadataMenuitemClass {
+ DbusmenuMenuitemClass parent_class;
+};
+
+struct _PlayerController {
+ GObject parent_instance;
+ PlayerControllerPrivate * priv;
+};
+
+struct _PlayerControllerClass {
+ GObjectClass parent_class;
+};
+
+struct _MprisController {
+ GObject parent_instance;
+ MprisControllerPrivate * priv;
+ DBusGProxy* mpris_player;
+};
+
+struct _MprisControllerClass {
+ GObjectClass parent_class;
+};
+
+struct _MprisControllerV2 {
+ MprisController parent_instance;
+ MprisControllerV2Private * priv;
+};
+
+struct _MprisControllerV2Class {
+ MprisControllerClass 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_set_root_menu_item (MusicPlayerBridge* self, DbusmenuMenuitem* menu);
+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 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);
+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);
+GType player_controller_get_type (void);
+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);
+
+
+G_END_DECLS
+
+#endif
diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala
new file mode 100644
index 0000000..b03ecbd
--- /dev/null
+++ b/src/music-player-bridge.vala
@@ -0,0 +1,106 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+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 Indicate;
+using Dbusmenu;
+using Gee;
+
+public class MusicPlayerBridge : GLib.Object
+{
+
+ private Listener listener;
+ private Dbusmenu.Menuitem root_menu;
+ private HashMap<string, PlayerController> registered_clients;
+
+ public MusicPlayerBridge()
+ {
+ registered_clients = new HashMap<string, PlayerController> ();
+ listener = Listener.ref_default();
+ listener.indicator_added.connect(on_indicator_added);
+ listener.indicator_removed.connect(on_indicator_removed);
+ listener.indicator_modified.connect(on_indicator_modified);
+ listener.server_added.connect(on_server_added);
+ 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)
+ {
+ debug("MusicPlayerBridge -> on_server_added with value %s", type);
+ if(server_is_not_of_interest(type)) return;
+ string client_name = type.split(".")[1];
+ if (root_menu != null && client_name != null){
+ 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);
+ }
+ }
+
+ public void on_server_removed(Indicate.ListenerServer object, string type)
+ {
+ debug("MusicPlayerBridge -> on_server_removed with value %s", type);
+ if(server_is_not_of_interest(type)) return;
+ string client_name = type.split(".")[1];
+ if (root_menu != null && client_name != null){
+ registered_clients[client_name].vanish();
+ registered_clients.remove(client_name);
+ debug("Successively removed menu_item for client %s from registered_clients", client_name);
+ }
+ }
+
+ private bool server_is_not_of_interest(string type){
+ if (type == null) return true;
+ if (type.contains("music") == false) {
+ debug("server is of no interest, it is not an music server");
+ return true;
+ }
+ return false;
+ }
+
+ public void on_server_count_changed(Indicate.ListenerServer object, uint i)
+ {
+ debug("MusicPlayerBridge-> on_server_count_changed with value %u", i);
+ }
+
+}
+
+
+
+
diff --git a/src/player-controller.c b/src/player-controller.c
new file mode 100644
index 0000000..7c37346
--- /dev/null
+++ b/src/player-controller.c
@@ -0,0 +1,364 @@
+/* player-controller.c generated by valac, the Vala compiler
+ * generated from player-controller.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:
+ 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_CONTROLLER (player_controller_get_type ())
+#define PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_CONTROLLER, PlayerController))
+#define PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+#define IS_PLAYER_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_CONTROLLER))
+#define IS_PLAYER_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_CONTROLLER))
+#define PLAYER_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_CONTROLLER, PlayerControllerClass))
+
+typedef struct _PlayerController PlayerController;
+typedef struct _PlayerControllerClass PlayerControllerClass;
+typedef struct _PlayerControllerPrivate PlayerControllerPrivate;
+
+#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))
+
+#define TYPE_MPRIS_CONTROLLER_V2 (mpris_controller_v2_get_type ())
+#define MPRIS_CONTROLLER_V2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2))
+#define MPRIS_CONTROLLER_V2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2Class))
+#define IS_MPRIS_CONTROLLER_V2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MPRIS_CONTROLLER_V2))
+#define IS_MPRIS_CONTROLLER_V2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_MPRIS_CONTROLLER_V2))
+#define MPRIS_CONTROLLER_V2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_MPRIS_CONTROLLER_V2, MprisControllerV2Class))
+
+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))
+#define IS_METADATA_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_METADATA_MENUITEM))
+#define IS_METADATA_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_METADATA_MENUITEM))
+#define METADATA_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_METADATA_MENUITEM, MetadataMenuitemClass))
+
+typedef struct _MetadataMenuitem MetadataMenuitem;
+typedef struct _MetadataMenuitemClass MetadataMenuitemClass;
+
+struct _PlayerController {
+ GObject parent_instance;
+ PlayerControllerPrivate * priv;
+};
+
+struct _PlayerControllerClass {
+ GObjectClass parent_class;
+};
+
+struct _PlayerControllerPrivate {
+ DbusmenuMenuitem* root_menu;
+ char* name;
+ gboolean is_active;
+ GeeArrayList* custom_items;
+ MprisController* mpris_adaptor;
+};
+
+
+static gpointer player_controller_parent_class = NULL;
+
+GType player_controller_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 {
+ PLAYER_CONTROLLER_DUMMY_PROPERTY
+};
+#define PLAYER_CONTROLLER_METADATA 2
+#define PLAYER_CONTROLLER_TRANSPORT 3
+static char* player_controller_format_client_name (const char* client_name);
+static gboolean player_controller_self_construct (PlayerController* self);
+MprisControllerV2* mpris_controller_v2_new (const char* name, PlayerController* controller);
+MprisControllerV2* mpris_controller_v2_construct (GType object_type, const char* name, PlayerController* controller);
+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);
+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);
+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);
+static void player_controller_finalize (GObject* obj);
+static int _vala_strcmp0 (const char * str1, const char * str2);
+
+
+
+static gpointer _g_object_ref0 (gpointer self) {
+ return self ? g_object_ref (self) : NULL;
+}
+
+
+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;
+}
+
+
+PlayerController* player_controller_construct (GType object_type, DbusmenuMenuitem* root, const char* client_name, gboolean active) {
+ PlayerController * self;
+ DbusmenuMenuitem* _tmp0_;
+ char* _tmp2_;
+ char* _tmp1_;
+ GeeArrayList* _tmp3_;
+ TransportMenuitem* t;
+ 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);
+ self->priv->root_menu = (_tmp0_ = _g_object_ref0 (root), _g_object_unref0 (self->priv->root_menu), _tmp0_);
+ 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_);
+ player_controller_self_construct (self);
+ if (_vala_strcmp0 (self->priv->name, "Vlc") == 0) {
+ MprisController* _tmp4_;
+ self->priv->mpris_adaptor = (_tmp4_ = (MprisController*) mpris_controller_v2_new (self->priv->name, self), _g_object_unref0 (self->priv->mpris_adaptor), _tmp4_);
+ } else {
+ 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);
+ return self;
+}
+
+
+PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* client_name, gboolean active) {
+ return player_controller_construct (TYPE_PLAYER_CONTROLLER, root, client_name, active);
+}
+
+
+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);
+ while (TRUE) {
+ DbusmenuMenuitem* item;
+ if (!gee_iterator_next (_item_it)) {
+ break;
+ }
+ item = (DbusmenuMenuitem*) gee_iterator_get (_item_it);
+ dbusmenu_menuitem_child_delete (self->priv->root_menu, item);
+ _g_object_unref0 (item);
+ }
+ _g_object_unref0 (_item_it);
+ }
+}
+
+
+static gboolean player_controller_self_construct (PlayerController* self) {
+ gboolean result = FALSE;
+ DbusmenuMenuitem* separator_item;
+ DbusmenuMenuitem* title_item;
+ 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);
+ metadata_item = metadata_menuitem_new ();
+ gee_abstract_collection_add ((GeeAbstractCollection*) self->priv->custom_items, (DbusmenuMenuitem*) metadata_item);
+ transport_item = transport_menuitem_new ();
+ gee_abstract_collection_add ((GeeAbstractCollection*) self->priv->custom_items, (DbusmenuMenuitem*) transport_item);
+ offset = 2;
+ {
+ GeeIterator* _item_it;
+ _item_it = gee_abstract_collection_iterator ((GeeAbstractCollection*) self->priv->custom_items);
+ while (TRUE) {
+ DbusmenuMenuitem* 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)));
+ _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;
+ 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;
+}
+
+
+static char* player_controller_format_client_name (const char* client_name) {
+ char* result = NULL;
+ char* formatted;
+ g_return_val_if_fail (client_name != NULL, NULL);
+ formatted = g_strdup (client_name);
+ if (g_utf8_strlen (formatted, -1) > 1) {
+ char* _tmp2_;
+ char* _tmp1_;
+ char* _tmp0_;
+ 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);
+ }
+ result = formatted;
+ return result;
+}
+
+
+static void player_controller_class_init (PlayerControllerClass * klass) {
+ player_controller_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (PlayerControllerPrivate));
+ G_OBJECT_CLASS (klass)->finalize = player_controller_finalize;
+}
+
+
+static void player_controller_instance_init (PlayerController * self) {
+ self->priv = PLAYER_CONTROLLER_GET_PRIVATE (self);
+}
+
+
+static void player_controller_finalize (GObject* obj) {
+ PlayerController * self;
+ 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->priv->mpris_adaptor);
+ G_OBJECT_CLASS (player_controller_parent_class)->finalize (obj);
+}
+
+
+GType player_controller_get_type (void) {
+ static volatile gsize player_controller_type_id__volatile = 0;
+ if (g_once_init_enter (&player_controller_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (PlayerControllerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) player_controller_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PlayerController), 0, (GInstanceInitFunc) player_controller_instance_init, NULL };
+ GType player_controller_type_id;
+ player_controller_type_id = g_type_register_static (G_TYPE_OBJECT, "PlayerController", &g_define_type_info, 0);
+ g_once_init_leave (&player_controller_type_id__volatile, player_controller_type_id);
+ }
+ return player_controller_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/player-controller.vala b/src/player-controller.vala
new file mode 100644
index 0000000..aa72cac
--- /dev/null
+++ b/src/player-controller.vala
@@ -0,0 +1,110 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+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 PlayerController : GLib.Object
+{
+ private 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;
+ private MprisController mpris_adaptor;
+
+ 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>();
+ self_construct();
+
+ // Temporary scenario to handle both v1 and v2 of MPRIS.
+ if(this.name == "Vlc"){
+ this.mpris_adaptor = new MprisControllerV2(this.name, this);
+ }
+ else{
+ this.mpris_adaptor = new MprisController(this.name, this);
+ }
+
+ // 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);
+ }
+
+ public void vanish()
+ {
+ foreach(Dbusmenu.Menuitem item in this.custom_items){
+ root_menu.child_delete(item);
+ }
+ }
+
+ 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);
+
+ // 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);
+
+ // Metadata item
+ MetadataMenuitem metadata_item = new MetadataMenuitem();
+ this.custom_items.add(metadata_item);
+
+ // Transport item
+ TransportMenuitem transport_item = new TransportMenuitem();
+ this.custom_items.add(transport_item);
+
+ int offset = 2;
+ foreach(Dbusmenu.Menuitem 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;
+ if(formatted.len() > 1){
+ formatted = client_name.up(1).concat(client_name.slice(1, client_name.len()));
+ debug("PlayerController->format_client_name - : %s", formatted);
+ }
+ return formatted;
+ }
+
+} \ No newline at end of file
diff --git a/src/pulse-manager.c b/src/pulse-manager.c
index c84cfcc..7323797 100644
--- a/src/pulse-manager.c
+++ b/src/pulse-manager.c
@@ -89,14 +89,14 @@ Gracefully close our connection with the Pulse async library.
void close_pulse_activites()
{
if (pulse_context != NULL){
- g_debug("freeing the pulse context");
+/* 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");
+/* g_debug("I just closed communication with Pulse");*/
}
/**
@@ -147,7 +147,7 @@ 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 !!!");
+/* g_debug("Sink_available returning false because sinks_hash is empty !!!"); */
DEFAULT_SINK_INDEX = -1;
return FALSE;
}
@@ -166,9 +166,9 @@ static gboolean determine_sink_availability()
// 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);
+/* 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);
+/* g_debug("PA_Manager -> determine_sink_availability: %i", available);*/
return available;
}
@@ -184,7 +184,7 @@ static gboolean default_sink_is_muted()
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);
@@ -201,7 +201,7 @@ static gdouble get_default_sink_volume()
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);
+/* g_debug("software volume = %f", volume_percent);*/
return volume_percent;
}
@@ -216,13 +216,13 @@ static void mute_each_sink(gpointer key, gpointer value, gpointer user_data)
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));
+/* 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_debug("in the pulse manager: toggle global mute value %i", mute_value);*/
}
@@ -234,7 +234,7 @@ 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);
+/* g_debug("in the pulse manager:set_sink_volume with percent %f", percent);*/
if(DEFAULT_SINK_INDEX < 0)
{
@@ -287,7 +287,7 @@ static void gather_pulse_information(pa_context *c, void *userdata)
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);*/
}
/**
@@ -315,7 +315,7 @@ static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, in
}
}
else{
- g_debug("About to add an item to our hash");
+/* g_debug("About to add an item to our hash");*/
sink_info *value;
value = g_new0(sink_info, 1);
value->index = sink->index;
@@ -325,7 +325,7 @@ static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, in
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");
+/* g_debug("After adding an item to our hash");*/
}
}
@@ -339,7 +339,7 @@ static void pulse_default_sink_info_callback(pa_context *c, const pa_sink_info *
}
else{
DEFAULT_SINK_INDEX = info->index;
- g_debug("Just set the default sink index to %i", DEFAULT_SINK_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.
@@ -358,17 +358,17 @@ static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_in
if (eol > 0) {
if (pa_context_errno(c) == PA_ERR_NOENTITY)
return;
- g_warning("Sink INPUT info callback failure");
+/* 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!!!");
+/* 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);
+/* g_debug("\n SINK INPUT INFO sink index : %d \n", info->sink);*/
check_sink_input_while_muted_event(info->sink);
}
}
@@ -378,7 +378,7 @@ static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, v
if (eol > 0) {
if (pa_context_errno(c) == PA_ERR_NOENTITY)
return;
- g_warning("Sink INPUT info callback failure");
+/* g_warning("Sink INPUT info callback failure");*/
return;
}
gint position = -1;
@@ -414,19 +414,19 @@ static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, v
{
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);
+/* 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);
+/* 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);
+/* g_debug("Updating volume from PA manager with volume = %f", volume_percent);*/
sound_service_dbus_update_sink_volume(dbus_service, volume_percent);
}
}
@@ -443,7 +443,7 @@ static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, v
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");
+/* g_debug("pulse-manager:update_sink_info -> After adding a new sink to our hash");*/
sound_service_dbus_update_sink_availability(dbus_service, TRUE);
}
}
@@ -457,7 +457,7 @@ static gboolean has_volume_changed(const pa_sink_info* new_sink, sink_info* cach
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!");
+/* g_debug("has_volume_changed: volumes appear to be equal? no change triggered!"); */
return FALSE;
}
@@ -467,7 +467,7 @@ static gboolean has_volume_changed(const pa_sink_info* new_sink, sink_info* cach
static void pulse_server_info_callback(pa_context *c, const pa_server_info *info, void *userdata)
{
- g_debug("server info callback");
+/* g_debug("server info callback");*/
pa_operation *operation;
if (info == NULL)
{
@@ -507,32 +507,32 @@ static void subscribed_events_callback(pa_context *c, enum pa_subscription_event
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_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);
+/* 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);
+/* 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");
+/* 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!!");
+/* 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));
- }
+ 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 ???");
@@ -551,16 +551,16 @@ static void subscribed_events_callback(pa_context *c, enum pa_subscription_event
static void context_state_callback(pa_context *c, void *userdata) {
switch (pa_context_get_state(c)) {
case PA_CONTEXT_UNCONNECTED:
- g_debug("unconnected");
+/* g_debug("unconnected");*/
break;
case PA_CONTEXT_CONNECTING:
- g_debug("connecting - waiting for the server to become available");
+/* g_debug("connecting - waiting for the server to become available");*/
break;
case PA_CONTEXT_AUTHORIZING:
- g_debug("authorizing");
+/* g_debug("authorizing");*/
break;
case PA_CONTEXT_SETTING_NAME:
- g_debug("context setting name");
+/* g_debug("context setting name");*/
break;
case PA_CONTEXT_FAILED:
g_warning("FAILED to retrieve context - Is PulseAudio Daemon running ?");
@@ -568,10 +568,10 @@ static void context_state_callback(pa_context *c, void *userdata) {
reconnect_to_pulse();
break;
case PA_CONTEXT_TERMINATED:
- g_debug("context terminated");
+/* g_debug("context terminated");*/
break;
case PA_CONTEXT_READY:
- g_debug("PA daemon is ready");
+ g_debug("PA daemon is ready");
pa_operation *o;
pa_context_set_subscribe_callback(c, subscribed_events_callback, userdata);
diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c
index cb72524..8a21fcf 100644
--- a/src/slider-menu-item.c
+++ b/src/slider-menu-item.c
@@ -53,8 +53,8 @@ static void slider_menu_item_class_init (SliderMenuItemClass *klass)
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;
+ DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass);
+ mclass->handle_event = handle_event;
return;
}
@@ -81,10 +81,10 @@ 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");
- gdouble volume_input = 0;
- volume_input = g_value_get_double(value);
- if(value != NULL)
- set_sink_volume(volume_input);
+ gdouble volume_input = 0;
+ volume_input = g_value_get_double(value);
+ if(value != NULL)
+ set_sink_volume(volume_input);
}
@@ -92,9 +92,9 @@ handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, g
SliderMenuItem* slider_menu_item_new(gboolean sinks_available, gdouble start_volume)
{
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);
+ 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;
}
diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c
index 5c6c487..d1ddfc4 100644
--- a/src/sound-service-dbus.c
+++ b/src/sound-service-dbus.c
@@ -199,7 +199,7 @@ 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_debug("Emitting signal: SINK_INPUT_WHILE_MUTED, with block_value: %i", block_value);*/
g_signal_emit(obj,
signals[SINK_INPUT_WHILE_MUTED],
0,
@@ -211,7 +211,7 @@ void sound_service_dbus_update_sink_volume(SoundServiceDbus* obj, gdouble sink_v
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_debug("Emitting signal: SINK_VOLUME_UPDATE, with sink_volme %f", priv->volume_percent);*/
g_signal_emit(obj,
signals[SINK_VOLUME_UPDATE],
0,
@@ -220,7 +220,7 @@ 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;
@@ -233,7 +233,7 @@ 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;
diff --git a/src/sound-service.c b/src/sound-service.c
index d70971e..38e5fba 100644
--- a/src/sound-service.c
+++ b/src/sound-service.c
@@ -23,6 +23,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "sound-service.h"
#include "dbus-menu-manager.h"
#include "pulse-manager.h"
+#include "music-player-bridge.h"
static GMainLoop *mainloop = NULL;
@@ -43,9 +44,9 @@ service_shutdown (IndicatorService *service, gpointer user_data)
if (mainloop != NULL) {
g_debug("Service shutdown !");
- // TODO: uncomment for release !!
- close_pulse_activites();
- g_main_loop_quit(mainloop);
+ // TODO: uncomment for release !!
+ close_pulse_activites();
+ g_main_loop_quit(mainloop);
}
return;
}
@@ -57,7 +58,7 @@ main:
int
main (int argc, char ** argv)
{
- g_type_init();
+ g_type_init();
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
@@ -69,13 +70,15 @@ main (int argc, char ** argv)
INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
G_CALLBACK(service_shutdown), NULL);
- dbus_menu_manager_setup();
+ 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
- mainloop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(mainloop);
-
- return 0;
+ mainloop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(mainloop);
+
+ return 0;
}
diff --git a/src/transport-menu-item.c b/src/transport-menu-item.c
new file mode 100644
index 0000000..bcddc55
--- /dev/null
+++ b/src/transport-menu-item.c
@@ -0,0 +1,175 @@
+/* transport-menu-item.c generated by valac, the Vala compiler
+ * 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:
+ 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>
+
+
+#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_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 _TransportMenuitem {
+ DbusmenuMenuitem parent_instance;
+ TransportMenuitemPrivate * priv;
+};
+
+struct _TransportMenuitemClass {
+ DbusmenuMenuitemClass parent_class;
+};
+
+struct _TransportMenuitemPrivate {
+ MprisController* mpris_adaptor;
+};
+
+
+static gpointer transport_menuitem_parent_class = NULL;
+
+GType transport_menuitem_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))
+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"
+TransportMenuitem* transport_menuitem_new (void);
+TransportMenuitem* transport_menuitem_construct (GType object_type);
+void transport_menuitem_set_adaptor (TransportMenuitem* self, MprisController* adaptor);
+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);
+
+
+
+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");
+ return self;
+}
+
+
+TransportMenuitem* transport_menuitem_new (void) {
+ return transport_menuitem_construct (TYPE_TRANSPORT_MENUITEM);
+}
+
+
+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_;
+ 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_);
+}
+
+
+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 transport_menuitem_real_handle_event (DbusmenuMenuitem* base, const char* name, GValue* input_value, guint timestamp) {
+ TransportMenuitem * self;
+ 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_free0 (_tmp0_);
+ mpris_controller_toggle_playback (self->priv->mpris_adaptor, g_value_get_boolean (input_value));
+}
+
+
+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;
+}
+
+
+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);
+}
+
+
+GType transport_menuitem_get_type (void) {
+ static volatile gsize transport_menuitem_type_id__volatile = 0;
+ 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);
+ 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
new file mode 100644
index 0000000..2e1ed0b
--- /dev/null
+++ b/src/transport-menu-item.vala
@@ -0,0 +1,54 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+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 TransportMenuitem : Dbusmenu.Menuitem
+{
+ /* 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);
+ debug("transport on the vala side");
+ }
+
+ public void set_adaptor(MprisController adaptor)
+ {
+ this.mpris_adaptor = adaptor;
+ }
+
+ /**
+ 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());
+ }
+} \ No newline at end of file
diff --git a/src/transport-widget.c b/src/transport-widget.c
new file mode 100644
index 0000000..c53513d
--- /dev/null
+++ b/src/transport-widget.c
@@ -0,0 +1,230 @@
+/*
+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/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include "transport-widget.h"
+#include "common-defs.h"
+#include <gtk/gtk.h>
+
+// TODO: think about leakage: ted !
+
+static DbusmenuMenuitem* twin_item;
+
+typedef struct _TransportWidgetPrivate TransportWidgetPrivate;
+
+struct _TransportWidgetPrivate
+{
+ GtkWidget* hbox;
+ GtkWidget* play_button;
+};
+
+enum {
+ PLAY,
+ PAUSE,
+ NEXT,
+ PREVIOUS,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+#define TRANSPORT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRANSPORT_WIDGET_TYPE, TransportWidgetPrivate))
+
+/* Gobject boiler plate */
+static void transport_widget_class_init (TransportWidgetClass *klass);
+static void transport_widget_init (TransportWidget *self);
+static void transport_widget_dispose (GObject *object);
+static void transport_widget_finalize (GObject *object);
+
+/* UI and dbusmenu callbacks */
+static gboolean transport_widget_button_press_event (GtkWidget *menuitem,
+ GdkEventButton *event);
+static gboolean transport_widget_button_release_event (GtkWidget *menuitem,
+ GdkEventButton *event);
+
+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);
+
+G_DEFINE_TYPE (TransportWidget, transport_widget, GTK_TYPE_MENU_ITEM);
+
+
+
+static void
+transport_widget_class_init (TransportWidgetClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->button_press_event = transport_widget_button_press_event;
+ widget_class->button_release_event = transport_widget_button_release_event;
+
+ g_type_class_add_private (klass, sizeof (TransportWidgetPrivate));
+
+ gobject_class->dispose = transport_widget_dispose;
+ gobject_class->finalize = transport_widget_finalize;
+
+ signals[PLAY] = g_signal_new ("play",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[PAUSE] = g_signal_new ("pause",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+
+ signals[NEXT] = g_signal_new ("next",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[PREVIOUS] = g_signal_new ("previous",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+transport_widget_init (TransportWidget *self)
+{
+ g_debug("TransportWidget::transport_widget_init");
+
+ TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(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));
+ 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);
+
+ gtk_container_add (GTK_CONTAINER (self), priv->hbox);
+
+ gtk_widget_show_all (priv->hbox);
+}
+
+static void
+transport_widget_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (transport_widget_parent_class)->dispose (object);
+}
+
+static void
+transport_widget_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (transport_widget_parent_class)->finalize (object);
+}
+
+/* keyevents */
+static gboolean
+transport_widget_button_press_event (GtkWidget *menuitem,
+ GdkEventButton *event)
+{
+ g_debug("TransportWidget::menu_press_event");
+ TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem));
+
+ 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))));
+ GValue value = {0};
+ g_value_init(&value, G_TYPE_BOOLEAN);
+ g_debug("TransportWidget::menu_press_event - going to send value %i", state);
+
+ g_value_set_boolean(&value, state);
+ dbusmenu_menuitem_handle_event (twin_item, "Transport state change", &value, 0);
+
+ return TRUE;
+}
+
+static gboolean
+transport_widget_button_release_event (GtkWidget *menuitem,
+ GdkEventButton *event)
+{
+ g_debug("TransportWidget::menu_release_event");
+ return TRUE;
+}
+
+/**
+* transport_widget_update_state()
+* Callback for updates from the other side of dbus
+**/
+static void
+transport_widget_property_update(DbusmenuMenuitem* item, gchar* property,
+ 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);
+
+ 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)));
+}
+
+// will be needed for image swapping
+static gchar* transport_widget_toggle_play_label(const gchar* state)
+{
+ gchar* label = ">";
+ if(g_strcmp0(state, ">") == 0){
+ label = "||";
+ }
+ return label;
+}
+
+ /**
+ * transport_new:
+ * @returns: a new #TransportWidget.
+ **/
+GtkWidget*
+transport_widget_new(DbusmenuMenuitem *item)
+{
+ twin_item = item;
+ return g_object_new(TRANSPORT_WIDGET_TYPE, NULL);
+}
+
diff --git a/src/transport-widget.h b/src/transport-widget.h
new file mode 100644
index 0000000..1d1aa6e
--- /dev/null
+++ b/src/transport-widget.h
@@ -0,0 +1,51 @@
+/*
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Conor Curran <conor.curran@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __TRANSPORT_WIDGET_H__
+#define __TRANSPORT_WIDGET_H__
+
+#include <gtk/gtkmenuitem.h>
+#include <libdbusmenu-gtk/menu.h>
+
+G_BEGIN_DECLS
+
+#define TRANSPORT_WIDGET_TYPE (transport_widget_get_type ())
+#define TRANSPORT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRANSPORT_WIDGET_TYPE, TransportWidget))
+#define TRANSPORT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRANSPORT_WIDGET_TYPE, TransportWidgetClass))
+#define IS_TRANSPORT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRANSPORT_WIDGET_TYPE))
+#define IS_TRANSPORT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRANSPORT_WIDGET_TYPE))
+#define TRANSPORT_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRANSPORT_WIDGET_TYPE, TransportWidgetClass))
+
+typedef struct _TransportWidget TransportWidget;
+typedef struct _TransportWidgetClass TransportWidgetClass;
+
+struct _TransportWidgetClass {
+ GtkMenuItemClass parent_class;
+};
+
+struct _TransportWidget {
+ GtkMenuItem parent;
+};
+
+GType transport_widget_get_type (void);
+GtkWidget* transport_widget_new(DbusmenuMenuitem *twin_item);
+
+G_END_DECLS
+
+#endif
+