diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 111 | ||||
-rw-r--r-- | src/Makefile.in | 247 | ||||
-rw-r--r-- | src/common-defs.h | 13 | ||||
-rw-r--r-- | src/dbus-menu-manager.c | 4 | ||||
-rw-r--r-- | src/dbus-menu-manager.h | 4 | ||||
-rwxr-xr-x | src/indicator-sound.c | 339 | ||||
-rw-r--r-- | src/metadata-menu-item.c | 186 | ||||
-rw-r--r-- | src/metadata-menu-item.vala | 40 | ||||
-rw-r--r-- | src/metadata-widget.c | 214 | ||||
-rw-r--r-- | src/metadata-widget.h | 51 | ||||
-rw-r--r-- | src/mpris-controller-v2.c | 135 | ||||
-rw-r--r-- | src/mpris-controller-v2.vala | 28 | ||||
-rw-r--r-- | src/mpris-controller.c | 380 | ||||
-rw-r--r-- | src/mpris-controller.vala | 101 | ||||
-rw-r--r-- | src/music-player-bridge.c | 362 | ||||
-rw-r--r-- | src/music-player-bridge.h | 185 | ||||
-rw-r--r-- | src/music-player-bridge.vala | 106 | ||||
-rw-r--r-- | src/player-controller.c | 364 | ||||
-rw-r--r-- | src/player-controller.vala | 110 | ||||
-rw-r--r-- | src/pulse-manager.c | 74 | ||||
-rw-r--r-- | src/slider-menu-item.c | 18 | ||||
-rw-r--r-- | src/sound-service-dbus.c | 8 | ||||
-rw-r--r-- | src/sound-service.c | 21 | ||||
-rw-r--r-- | src/transport-menu-item.c | 175 | ||||
-rw-r--r-- | src/transport-menu-item.vala | 54 | ||||
-rw-r--r-- | src/transport-widget.c | 230 | ||||
-rw-r--r-- | src/transport-widget.h | 51 |
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 + |