diff options
author | Sebastien Bacher <seb128@ubuntu.com> | 2010-07-22 21:04:26 +0200 |
---|---|---|
committer | Sebastien Bacher <seb128@ubuntu.com> | 2010-07-22 21:04:26 +0200 |
commit | 1777ee4291dc792ca3d4df087c8af23cd8458961 (patch) | |
tree | 101cc9ea1b424973a7c43cd7ce7bb9c4f9ac66aa | |
parent | f6ffb190261dfdbbf55e90b63c1cd06f03037e35 (diff) | |
parent | c7316aef6047ef29ab71fbcd34d6932fb0e521ad (diff) | |
download | ayatana-indicator-sound-1777ee4291dc792ca3d4df087c8af23cd8458961.tar.gz ayatana-indicator-sound-1777ee4291dc792ca3d4df087c8af23cd8458961.tar.bz2 ayatana-indicator-sound-1777ee4291dc792ca3d4df087c8af23cd8458961.zip |
Import upstream version 0.3.8
35 files changed, 1712 insertions, 447 deletions
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for indicator-sound 0.3.6. +# Generated by GNU Autoconf 2.65 for indicator-sound 0.3.8. # # Report bugs to <conor.curran@canonical.com>. # @@ -761,8 +761,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='indicator-sound' PACKAGE_TARNAME='indicator-sound' -PACKAGE_VERSION='0.3.6' -PACKAGE_STRING='indicator-sound 0.3.6' +PACKAGE_VERSION='0.3.8' +PACKAGE_STRING='indicator-sound 0.3.8' PACKAGE_BUGREPORT='conor.curran@canonical.com' PACKAGE_URL='' @@ -1555,7 +1555,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures indicator-sound 0.3.6 to adapt to many kinds of systems. +\`configure' configures indicator-sound 0.3.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1625,7 +1625,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of indicator-sound 0.3.6:";; + short | recursive ) echo "Configuration of indicator-sound 0.3.8:";; esac cat <<\_ACEOF @@ -1752,7 +1752,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -indicator-sound configure 0.3.6 +indicator-sound configure 0.3.8 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. @@ -2123,7 +2123,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by indicator-sound $as_me 0.3.6, which was +It was created by indicator-sound $as_me 0.3.8, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -2936,7 +2936,7 @@ fi # Define the identity of the package. PACKAGE=indicator-sound - VERSION=0.3.6 + VERSION=0.3.8 cat >>confdefs.h <<_ACEOF @@ -12111,7 +12111,7 @@ INDICATOR_REQUIRED_VERSION=0.3.6 DBUSMENUGTK_REQUIRED_VERSION=0.2.2 POLKIT_REQUIRED_VERSION=0.92 PULSE_AUDIO_REQUIRED_VERSION=0.9.19 -INDICATOR_DISPLAY_OBJECTS=0.1.4 +INDICATOR_DISPLAY_OBJECTS=0.1.10 INDICATE_REQUIRED_VERSION=0.4.1 DBUSMENUGLIB_REQUIRED_VERSION=0.3.1 @@ -14069,7 +14069,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by indicator-sound $as_me 0.3.6, which was +This file was extended by indicator-sound $as_me 0.3.8, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14135,7 +14135,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -indicator-sound config.status 0.3.6 +indicator-sound config.status 0.3.8 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 0a41bc5..8dcaaea 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,10 @@ -AC_INIT(indicator-sound, 0.3.6, conor.curran@canonical.com) +AC_INIT(indicator-sound, 0.3.8, conor.curran@canonical.com) AC_PREREQ(2.53) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(indicator-sound, 0.3.6) +AM_INIT_AUTOMAKE(indicator-sound, 0.3.8) AM_MAINTAINER_MODE @@ -33,7 +33,7 @@ INDICATOR_REQUIRED_VERSION=0.3.6 DBUSMENUGTK_REQUIRED_VERSION=0.2.2 POLKIT_REQUIRED_VERSION=0.92 PULSE_AUDIO_REQUIRED_VERSION=0.9.19 -INDICATOR_DISPLAY_OBJECTS=0.1.4 +INDICATOR_DISPLAY_OBJECTS=0.1.10 INDICATE_REQUIRED_VERSION=0.4.1 DBUSMENUGLIB_REQUIRED_VERSION=0.3.1 diff --git a/src/Makefile.am b/src/Makefile.am index 79ba7d2..ed3e394 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,6 +18,8 @@ libsoundmenu_la_SOURCES = \ indicator-sound.c \ title-widget.c \ title-widget.h \ + scrub-widget.c \ + scrub-widget.h \ dbus-shared-names.h \ sound-service-client.h @@ -58,6 +60,7 @@ music_bridge_VALASOURCES = \ music-player-bridge.vala \ transport-menu-item.vala \ metadata-menu-item.vala \ + scrub-menu-item.vala \ title-menu-item.vala \ player-controller.vala \ mpris-controller-v2.vala \ diff --git a/src/Makefile.in b/src/Makefile.in index 6f0fd0c..b60a421 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -76,7 +76,8 @@ am_libsoundmenu_la_OBJECTS = libsoundmenu_la-transport-widget.lo \ libsoundmenu_la-metadata-widget.lo \ libsoundmenu_la-play-button.lo \ libsoundmenu_la-indicator-sound.lo \ - libsoundmenu_la-title-widget.lo + libsoundmenu_la-title-widget.lo \ + libsoundmenu_la-scrub-widget.lo libsoundmenu_la_OBJECTS = $(am_libsoundmenu_la_OBJECTS) AM_V_lt = $(am__v_lt_$(V)) am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) @@ -89,6 +90,7 @@ 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-scrub-menu-item.$(OBJEXT) \ indicator_sound_service-title-menu-item.$(OBJEXT) \ indicator_sound_service-player-controller.$(OBJEXT) \ indicator_sound_service-mpris-controller-v2.$(OBJEXT) \ @@ -315,6 +317,8 @@ libsoundmenu_la_SOURCES = \ indicator-sound.c \ title-widget.c \ title-widget.h \ + scrub-widget.c \ + scrub-widget.h \ dbus-shared-names.h \ sound-service-client.h @@ -329,6 +333,7 @@ music_bridge_VALASOURCES = \ music-player-bridge.vala \ transport-menu-item.vala \ metadata-menu-item.vala \ + scrub-menu-item.vala \ title-menu-item.vala \ player-controller.vala \ mpris-controller-v2.vala \ @@ -527,6 +532,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-player-controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-player-item.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-pulse-manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_sound_service-scrub-menu-item.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@ @@ -535,6 +541,7 @@ distclean-compile: @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-play-button.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoundmenu_la-scrub-widget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoundmenu_la-title-widget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsoundmenu_la-transport-widget.Plo@am__quote@ @@ -602,6 +609,14 @@ libsoundmenu_la-title-widget.lo: title-widget.c @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-title-widget.lo `test -f 'title-widget.c' || echo '$(srcdir)/'`title-widget.c +libsoundmenu_la-scrub-widget.lo: scrub-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-scrub-widget.lo -MD -MP -MF $(DEPDIR)/libsoundmenu_la-scrub-widget.Tpo -c -o libsoundmenu_la-scrub-widget.lo `test -f 'scrub-widget.c' || echo '$(srcdir)/'`scrub-widget.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsoundmenu_la-scrub-widget.Tpo $(DEPDIR)/libsoundmenu_la-scrub-widget.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scrub-widget.c' object='libsoundmenu_la-scrub-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-scrub-widget.lo `test -f 'scrub-widget.c' || echo '$(srcdir)/'`scrub-widget.c + indicator_sound_service-sound-service.o: sound-service.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_sound_service_CFLAGS) $(CFLAGS) -MT indicator_sound_service-sound-service.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-sound-service.Tpo -c -o indicator_sound_service-sound-service.o `test -f 'sound-service.c' || echo '$(srcdir)/'`sound-service.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-sound-service.Tpo $(DEPDIR)/indicator_sound_service-sound-service.Po @@ -730,6 +745,22 @@ indicator_sound_service-metadata-menu-item.obj: metadata-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-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-scrub-menu-item.o: scrub-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-scrub-menu-item.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-scrub-menu-item.Tpo -c -o indicator_sound_service-scrub-menu-item.o `test -f 'scrub-menu-item.c' || echo '$(srcdir)/'`scrub-menu-item.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-scrub-menu-item.Tpo $(DEPDIR)/indicator_sound_service-scrub-menu-item.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scrub-menu-item.c' object='indicator_sound_service-scrub-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-scrub-menu-item.o `test -f 'scrub-menu-item.c' || echo '$(srcdir)/'`scrub-menu-item.c + +indicator_sound_service-scrub-menu-item.obj: scrub-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-scrub-menu-item.obj -MD -MP -MF $(DEPDIR)/indicator_sound_service-scrub-menu-item.Tpo -c -o indicator_sound_service-scrub-menu-item.obj `if test -f 'scrub-menu-item.c'; then $(CYGPATH_W) 'scrub-menu-item.c'; else $(CYGPATH_W) '$(srcdir)/scrub-menu-item.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-scrub-menu-item.Tpo $(DEPDIR)/indicator_sound_service-scrub-menu-item.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scrub-menu-item.c' object='indicator_sound_service-scrub-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-scrub-menu-item.obj `if test -f 'scrub-menu-item.c'; then $(CYGPATH_W) 'scrub-menu-item.c'; else $(CYGPATH_W) '$(srcdir)/scrub-menu-item.c'; fi` + indicator_sound_service-title-menu-item.o: title-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-title-menu-item.o -MD -MP -MF $(DEPDIR)/indicator_sound_service-title-menu-item.Tpo -c -o indicator_sound_service-title-menu-item.o `test -f 'title-menu-item.c' || echo '$(srcdir)/'`title-menu-item.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_sound_service-title-menu-item.Tpo $(DEPDIR)/indicator_sound_service-title-menu-item.Po diff --git a/src/common-defs.h b/src/common-defs.h index 9c1fbab..208c8cb 100644 --- a/src/common-defs.h +++ b/src/common-defs.h @@ -29,11 +29,17 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #define DBUSMENU_TRANSPORT_MENUITEM_TYPE "x-canonical-transport-bar" #define DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE "x-canonical-transport-play-state" -#define DBUSMENU_METADATA_MENUITEM_TYPE "x-canonical-metadata-menu-item" -#define DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST "x-canonical-metadata-text-artist" -#define DBUSMENU_METADATA_MENUITEM_TEXT_TITLE "x-canonical-metadata-text-title" -#define DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM "x-canonical-metadata-text-album" -#define DBUSMENU_METADATA_MENUITEM_ARTURL "x-canonical-metadata-arturl" +#define DBUSMENU_METADATA_MENUITEM_TYPE "x-canonical-sound-menu-player-metadata-menu-item" +#define DBUSMENU_METADATA_MENUITEM_ARTIST "x-canonical-sound-menu-player-metadata-artist" +#define DBUSMENU_METADATA_MENUITEM_TITLE "x-canonical-sound-menu-player-metadata-title" +#define DBUSMENU_METADATA_MENUITEM_ALBUM "x-canonical-sound-menu-player-metadata-album" +#define DBUSMENU_METADATA_MENUITEM_ARTURL "x-canonical-sound-menu-player-metadata-arturl" #define DBUSMENU_TITLE_MENUITEM_TYPE "x-canonical-sound-menu-player-title-menu-item" -#define DBUSMENU_TITLE_MENUITEM_TEXT_NAME "x-canonical-sound-menu-player-title-name" +#define DBUSMENU_TITLE_MENUITEM_NAME "x-canonical-sound-menu-player-title-name" + +#define DBUSMENU_SCRUB_MENUITEM_TYPE "x-canonical-sound-menu-player-scrub-menu-item" +#define DBUSMENU_SCRUB_MENUITEM_DURATION "x-canonical-sound-menu-player-scrub-time" +#define DBUSMENU_SCRUB_MENUITEM_POSITION "x-canonical-sound-menu-player-scrub-position" +#define DBUSMENU_SCRUB_MENUITEM_PLAY_STATE "x-canonical-sound-menu-player-scrub-play-state" + diff --git a/src/familiar-players-db.c b/src/familiar-players-db.c index 9933d4d..059bf5a 100644 --- a/src/familiar-players-db.c +++ b/src/familiar-players-db.c @@ -129,8 +129,10 @@ FamiliarPlayersDB* familiar_players_db_new (void) { static gboolean familiar_players_db_create_key_file (FamiliarPlayersDB* self) { gboolean result = FALSE; GError * _inner_error_; + gboolean _result_; g_return_val_if_fail (self != NULL, FALSE); _inner_error_ = NULL; + _result_ = FALSE; if (g_file_test (self->priv->file_name, G_FILE_TEST_EXISTS)) { GKeyFile* _tmp0_; self->priv->key_file = (_tmp0_ = g_key_file_new (), _g_key_file_free0 (self->priv->key_file), _tmp0_); @@ -138,14 +140,28 @@ static gboolean familiar_players_db_create_key_file (FamiliarPlayersDB* self) { gboolean _tmp1_; _tmp1_ = g_key_file_load_from_file (self->priv->key_file, self->priv->file_name, G_KEY_FILE_NONE, &_inner_error_); if (_inner_error_ != NULL) { + if (_inner_error_->domain == G_KEY_FILE_ERROR) { + goto __catch3_g_key_file_error; + } if (_inner_error_->domain == G_FILE_ERROR) { goto __catch3_g_file_error; } - goto __finally3; + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; } - if (_tmp1_ == TRUE) { - result = TRUE; - return result; + _result_ = _tmp1_; + } + goto __finally3; + __catch3_g_key_file_error: + { + GError * e; + e = _inner_error_; + _inner_error_ = NULL; + { + g_warning ("familiar-players-db.vala:61: FamiliarPlayersDB::create_key_file() - Ke" \ +"yFileError"); + _g_error_free0 (e); } } goto __finally3; @@ -155,8 +171,8 @@ static gboolean familiar_players_db_create_key_file (FamiliarPlayersDB* self) { e = _inner_error_; _inner_error_ = NULL; { - g_warning ("familiar-players-db.vala:62: FamiliarPlayersDB - error trying to load " \ -"KeyFile"); + g_warning ("familiar-players-db.vala:64: FamiliarPlayersDB::create_key_file() - Fi" \ +"leError"); _g_error_free0 (e); } } @@ -167,7 +183,7 @@ static gboolean familiar_players_db_create_key_file (FamiliarPlayersDB* self) { return FALSE; } } - result = FALSE; + result = _result_; return result; } @@ -211,7 +227,7 @@ static gboolean familiar_players_db_check_for_keys (FamiliarPlayersDB* self) { g_clear_error (&_inner_error_); return FALSE; } - g_warning ("familiar-players-db.vala:77: Seen DB '%s' does not have key '%s' in gr" \ + g_warning ("familiar-players-db.vala:79: Seen DB '%s' does not have key '%s' in gr" \ "oup '%s'", self->priv->file_name, FAMILIAR_PLAYERS_DB_KEY_NAME, FAMILIAR_PLAYERS_DB_GROUP_NAME); result = FALSE; return result; @@ -231,10 +247,12 @@ static gboolean familiar_players_db_load_data_from_key_file (FamiliarPlayersDB* char** desktops; desktops = (_tmp1_ = g_key_file_get_string_list (self->priv->key_file, FAMILIAR_PLAYERS_DB_GROUP_NAME, FAMILIAR_PLAYERS_DB_KEY_NAME, &_tmp0_, &_inner_error_), desktops_length1 = _tmp0_, _desktops_size_ = desktops_length1, _tmp1_); if (_inner_error_ != NULL) { - if (_inner_error_->domain == G_FILE_ERROR) { - goto __catch5_g_file_error; + if (_inner_error_->domain == G_KEY_FILE_ERROR) { + goto __catch5_g_key_file_error; } - goto __finally5; + g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); + g_clear_error (&_inner_error_); + return FALSE; } { char** s_collection; @@ -256,13 +274,13 @@ static gboolean familiar_players_db_load_data_from_key_file (FamiliarPlayersDB* return result; } goto __finally5; - __catch5_g_file_error: + __catch5_g_key_file_error: { GError * _error_; _error_ = _inner_error_; _inner_error_ = NULL; { - g_warning ("familiar-players-db.vala:91: Error loading the Desktop string list"); + g_warning ("familiar-players-db.vala:93: Error loading the Desktop string list"); result = FALSE; _g_error_free0 (_error_); return result; @@ -325,13 +343,13 @@ static gboolean familiar_players_db_write_db (FamiliarPlayersDB* self) { data = (_tmp4_ = g_key_file_to_data (keyfile, &data_length, NULL), _g_free0 (data), _tmp4_); } goto __finally6; - __catch6_g_error: + __catch6_g_key_file_error: { GError * e; e = _inner_error_; _inner_error_ = NULL; { - g_warning ("familiar-players-db.vala:112: Problems dumping keyfile to a string"); + g_warning ("familiar-players-db.vala:114: Problems dumping keyfile to a string"); result = FALSE; _g_error_free0 (e); _g_key_file_free0 (keyfile); @@ -350,7 +368,7 @@ static gboolean familiar_players_db_write_db (FamiliarPlayersDB* self) { return FALSE; } if (g_mkdir_with_parents (self->priv->dir_name, 0700) != 0) { - g_warning ("familiar-players-db.vala:117: Unable to make directory: %s", self->priv->dir_name); + g_warning ("familiar-players-db.vala:119: Unable to make directory: %s", self->priv->dir_name); result = FALSE; _g_key_file_free0 (keyfile); desktops = (_vala_array_free (desktops, desktops_length1, (GDestroyNotify) g_free), NULL); @@ -372,7 +390,7 @@ static gboolean familiar_players_db_write_db (FamiliarPlayersDB* self) { return FALSE; } if (_tmp5_ == FALSE) { - g_warning ("familiar-players-db.vala:123: Unable to write out file '%s'", self->priv->file_name); + g_warning ("familiar-players-db.vala:125: Unable to write out file '%s'", self->priv->file_name); } } goto __finally7; @@ -382,7 +400,7 @@ static gboolean familiar_players_db_write_db (FamiliarPlayersDB* self) { err = _inner_error_; _inner_error_ = NULL; { - g_warning ("familiar-players-db.vala:127: Unable to write out file '%s'", self->priv->file_name); + g_warning ("familiar-players-db.vala:129: Unable to write out file '%s'", self->priv->file_name); _g_error_free0 (err); } } @@ -446,7 +464,7 @@ gboolean familiar_players_db_already_familiar (FamiliarPlayersDB* self, const ch gboolean _tmp3_; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (desktop != NULL, FALSE); - g_debug ("familiar-players-db.vala:146: playerDB->already_familiar - result %s", _tmp1_ = bool_to_string (gee_collection_contains ((GeeCollection*) (_tmp0_ = gee_map_get_keys ((GeeMap*) self->priv->players_DB)), desktop))); + g_debug ("familiar-players-db.vala:148: playerDB->already_familiar - result %s", _tmp1_ = bool_to_string (gee_collection_contains ((GeeCollection*) (_tmp0_ = gee_map_get_keys ((GeeMap*) self->priv->players_DB)), desktop))); _g_free0 (_tmp1_); _g_object_unref0 (_tmp0_); result = (_tmp3_ = gee_collection_contains ((GeeCollection*) (_tmp2_ = gee_map_get_keys ((GeeMap*) self->priv->players_DB)), desktop), _g_object_unref0 (_tmp2_), _tmp3_); diff --git a/src/familiar-players-db.vala b/src/familiar-players-db.vala index b83caa3..2bc0a3c 100644 --- a/src/familiar-players-db.vala +++ b/src/familiar-players-db.vala @@ -51,18 +51,20 @@ public class FamiliarPlayersDB : GLib.Object } private bool create_key_file(){ + bool result = false; if (test(this.file_name, GLib.FileTest.EXISTS)) { this.key_file = new KeyFile(); try{ - if (this.key_file.load_from_file(this.file_name, KeyFileFlags.NONE) == true) { - return true; - } + result = this.key_file.load_from_file(this.file_name, KeyFileFlags.NONE); } - catch(FileError e){ - warning("FamiliarPlayersDB - error trying to load KeyFile"); + catch(GLib.KeyFileError e){ + warning("FamiliarPlayersDB::create_key_file() - KeyFileError"); } + catch(GLib.FileError e){ + warning("FamiliarPlayersDB::create_key_file() - FileError"); + } } - return false; + return result; } private bool check_for_keys(){ @@ -87,7 +89,7 @@ public class FamiliarPlayersDB : GLib.Object } return true; } - catch(FileError error){ + catch(GLib.KeyFileError error){ warning("Error loading the Desktop string list"); return false; } @@ -108,7 +110,7 @@ public class FamiliarPlayersDB : GLib.Object try{ data = keyfile.to_data(out data_length); } - catch(Error e){ + catch(GLib.KeyFileError e){ warning("Problems dumping keyfile to a string"); return false; } diff --git a/src/indicator-sound.c b/src/indicator-sound.c index a2d9762..1c6041b 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -41,6 +41,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include "transport-widget.h" #include "metadata-widget.h" #include "title-widget.h" +#include "scrub-widget.h" #include "dbus-shared-names.h" #include "sound-service-client.h" #include "common-defs.h" @@ -94,10 +95,11 @@ 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 +//player widget realisation methods static gboolean new_transport_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); static gboolean new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); static gboolean new_title_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); +static gboolean new_scrub_bar_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); // DBUS communication static DBusGProxy *sound_dbus_proxy = NULL; @@ -246,7 +248,9 @@ get_menu (IndicatorObject * io) dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TRANSPORT_MENUITEM_TYPE, new_transport_widget); dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_METADATA_MENUITEM_TYPE, new_metadata_widget); dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TITLE_MENUITEM_TYPE, new_title_widget); - // register Key-press listening on the menu widget as the slider does not allow this. + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_SCRUB_MENUITEM_TYPE, new_scrub_bar_widget); + + // register Key-press listening on the menu widget as the slider does not allow this. g_signal_connect(menu, "key-press-event", G_CALLBACK(key_press_cb), NULL); return GTK_MENU(menu); } @@ -273,7 +277,8 @@ new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuC io = g_object_get_data (G_OBJECT (client), "indicator"); - volume_slider = ido_scale_menu_item_new_with_range ("Volume", initial_volume_percent, 0, 100, 1); + volume_slider = ido_scale_menu_item_new_with_range ("Volume", IDO_RANGE_STYLE_DEFAULT, initial_volume_percent, 0, 100, 1); + ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (volume_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE); g_object_set(volume_slider, "reverse-scroll-events", TRUE, NULL); g_signal_connect (volume_slider, @@ -373,6 +378,26 @@ new_title_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusmenu return TRUE; } +static gboolean +new_scrub_bar_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) +{ + g_debug("indicator-sound: new_scrub_bar_widget"); + + GtkWidget* scrub_bar = NULL; + + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); + + scrub_bar = scrub_widget_new (newitem); + GtkMenuItem *menu_scrub_widget = GTK_MENU_ITEM(scrub_widget_get_ido_bar(SCRUB_WIDGET(scrub_bar))); + + gtk_widget_show_all(scrub_widget_get_ido_bar(SCRUB_WIDGET(scrub_bar))); + + dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_scrub_widget, parent); + + return TRUE; +} + static void connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer userdata) diff --git a/src/metadata-menu-item.c b/src/metadata-menu-item.c index 518bad8..792b638 100644 --- a/src/metadata-menu-item.c +++ b/src/metadata-menu-item.c @@ -84,7 +84,7 @@ enum { MetadataMenuitem* metadata_menuitem_new (void); MetadataMenuitem* metadata_menuitem_construct (GType object_type); GeeHashSet* metadata_menuitem_attributes_format (void); -gboolean metadata_menuitem_populated (MetadataMenuitem* self); +gboolean metadata_menuitem_not_populated (MetadataMenuitem* self); static int _vala_strcmp0 (const char * str1, const char * str2); @@ -105,21 +105,21 @@ GeeHashSet* metadata_menuitem_attributes_format (void) { GeeHashSet* result = NULL; GeeHashSet* attrs; attrs = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, NULL, NULL); - gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_TEXT_TITLE); - gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST); - gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_TITLE); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_ARTIST); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_ALBUM); gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_METADATA_MENUITEM_ARTURL); result = attrs; return result; } -gboolean metadata_menuitem_populated (MetadataMenuitem* self) { +gboolean metadata_menuitem_not_populated (MetadataMenuitem* self) { gboolean result = FALSE; gboolean _tmp0_ = FALSE; g_return_val_if_fail (self != NULL, FALSE); - if (dbusmenu_menuitem_property_get ((DbusmenuMenuitem*) self, DBUSMENU_METADATA_MENUITEM_TEXT_TITLE) != NULL) { - _tmp0_ = _vala_strcmp0 (dbusmenu_menuitem_property_get ((DbusmenuMenuitem*) self, DBUSMENU_METADATA_MENUITEM_TEXT_TITLE), "") != 0; + if (dbusmenu_menuitem_property_get ((DbusmenuMenuitem*) self, DBUSMENU_METADATA_MENUITEM_TITLE) == NULL) { + _tmp0_ = _vala_strcmp0 (dbusmenu_menuitem_property_get ((DbusmenuMenuitem*) self, DBUSMENU_METADATA_MENUITEM_TITLE), "") == 0; } else { _tmp0_ = FALSE; } diff --git a/src/metadata-menu-item.vala b/src/metadata-menu-item.vala index cfcb3bc..388ef81 100644 --- a/src/metadata-menu-item.vala +++ b/src/metadata-menu-item.vala @@ -31,17 +31,17 @@ public class MetadataMenuitem : PlayerItem public static HashSet<string> attributes_format() { HashSet<string> attrs = new HashSet<string>(); - attrs.add(MENUITEM_TEXT_TITLE); - attrs.add(MENUITEM_TEXT_ARTIST); - attrs.add(MENUITEM_TEXT_ALBUM); + attrs.add(MENUITEM_TITLE); + attrs.add(MENUITEM_ARTIST); + attrs.add(MENUITEM_ALBUM); attrs.add(MENUITEM_ARTURL); return attrs; } - public bool populated() + public bool not_populated() { - return (this.property_get(MENUITEM_TEXT_TITLE) != null && - this.property_get(MENUITEM_TEXT_TITLE) != ""); + return (this.property_get(MENUITEM_TITLE) == null && + this.property_get(MENUITEM_TITLE) == ""); } }
\ No newline at end of file diff --git a/src/metadata-widget.c b/src/metadata-widget.c index 8235725..dce9226 100644 --- a/src/metadata-widget.c +++ b/src/metadata-widget.c @@ -109,7 +109,7 @@ metadata_widget_init (MetadataWidget *self) // artist GtkWidget* artist; artist = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, - DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST)); + DBUSMENU_METADATA_MENUITEM_ARTIST)); gtk_misc_set_alignment(GTK_MISC(artist), (gfloat)0, (gfloat)0); gtk_label_set_width_chars(GTK_LABEL(artist), 15); @@ -121,7 +121,7 @@ metadata_widget_init (MetadataWidget *self) // piece GtkWidget* piece; piece = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, - DBUSMENU_METADATA_MENUITEM_TEXT_TITLE)); + DBUSMENU_METADATA_MENUITEM_TITLE)); gtk_misc_set_alignment(GTK_MISC(piece), (gfloat)0, (gfloat)0); gtk_label_set_width_chars(GTK_LABEL(piece), 12); gtk_label_set_ellipsize(GTK_LABEL(piece), PANGO_ELLIPSIZE_MIDDLE); @@ -132,7 +132,7 @@ metadata_widget_init (MetadataWidget *self) // container GtkWidget* container; container = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, - DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM)); + DBUSMENU_METADATA_MENUITEM_ALBUM)); gtk_misc_set_alignment(GTK_MISC(container), (gfloat)0, (gfloat)0); gtk_label_set_width_chars(GTK_LABEL(container), 15); gtk_label_set_ellipsize(GTK_LABEL(container), PANGO_ELLIPSIZE_MIDDLE); @@ -202,15 +202,15 @@ metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property, MetadataWidget* mitem = METADATA_WIDGET(userdata); MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(mitem); - if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST, property) == 0){ + if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ARTIST, property) == 0){ gtk_label_set_text(GTK_LABEL(priv->artist_label), g_value_get_string(value)); style_artist_text(mitem); } - else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_TITLE, property) == 0){ + else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TITLE, property) == 0){ gtk_label_set_text(GTK_LABEL(priv->piece_label), g_value_get_string(value)); style_title_text(mitem); } - else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_ALBUM, property) == 0){ + else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ALBUM, property) == 0){ gtk_label_set_text(GTK_LABEL(priv->container_label), g_value_get_string(value)); style_album_text(mitem); } diff --git a/src/mpris-controller.c b/src/mpris-controller.c index 041177c..4131b5f 100644 --- a/src/mpris-controller.c +++ b/src/mpris-controller.c @@ -32,6 +32,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/menuitem-proxy.h> #include <libdbusmenu-glib/menuitem.h> #include <libdbusmenu-glib/server.h> +#include <float.h> +#include <math.h> #define TYPE_MPRIS_CONTROLLER (mpris_controller_get_type ()) @@ -57,6 +59,9 @@ 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_free0(var) (var = (g_free (var), NULL)) + +#define MPRIS_CONTROLLER_TYPE_STATUS (mpris_controller_status_get_type ()) +typedef struct _MprisControllerstatus MprisControllerstatus; typedef struct _PlayerControllerPrivate PlayerControllerPrivate; #define TYPE_PLAYER_ITEM (player_item_get_type ()) @@ -69,12 +74,7 @@ typedef struct _PlayerControllerPrivate PlayerControllerPrivate; typedef struct _PlayerItem PlayerItem; typedef struct _PlayerItemClass PlayerItemClass; -#define TRANSPORT_MENUITEM_TYPE_ACTION (transport_menuitem_action_get_type ()) - -#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))) -#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +#define PLAYER_CONTROLLER_TYPE_WIDGET_ORDER (player_controller_widget_order_get_type ()) #define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) #define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) @@ -85,6 +85,20 @@ typedef struct _MprisControllerstatus MprisControllerstatus; typedef struct _TransportMenuitem TransportMenuitem; typedef struct _TransportMenuitemClass TransportMenuitemClass; +#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL))) + +#define TYPE_SCRUB_MENUITEM (scrub_menuitem_get_type ()) +#define SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitem)) +#define SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) +#define IS_SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCRUB_MENUITEM)) +#define IS_SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCRUB_MENUITEM)) +#define SCRUB_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) + +typedef struct _ScrubMenuitem ScrubMenuitem; +typedef struct _ScrubMenuitemClass ScrubMenuitemClass; + +#define TRANSPORT_MENUITEM_TYPE_ACTION (transport_menuitem_action_get_type ()) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) struct _MprisController { GObject parent_instance; @@ -100,7 +114,13 @@ struct _MprisControllerPrivate { DBusGProxy* _mpris_player; PlayerController* _owner; char* _mpris_interface; - char* name; +}; + +struct _MprisControllerstatus { + gint32 playback; + gint32 shuffle; + gint32 repeat; + gint32 endless; }; struct _PlayerController { @@ -116,15 +136,19 @@ struct _PlayerControllerClass { }; typedef enum { + PLAYER_CONTROLLER_WIDGET_ORDER_SEPARATOR, + PLAYER_CONTROLLER_WIDGET_ORDER_TITLE, + PLAYER_CONTROLLER_WIDGET_ORDER_METADATA, + PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB, + PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT +} PlayerControllerwidget_order; + +typedef enum { TRANSPORT_MENUITEM_ACTION_PREVIOUS, TRANSPORT_MENUITEM_ACTION_PLAY_PAUSE, TRANSPORT_MENUITEM_ACTION_NEXT } TransportMenuitemaction; -struct _MprisControllerstatus { - gint32 playback; -}; - static gpointer mpris_controller_parent_class = NULL; @@ -139,29 +163,42 @@ enum { }; MprisController* mpris_controller_new (PlayerController* ctrl, const char* inter); MprisController* mpris_controller_construct (GType object_type, PlayerController* ctrl, const char* inter); -PlayerController* mpris_controller_get_owner (MprisController* self); -GType player_item_get_type (void); -#define PLAYER_CONTROLLER_METADATA 2 -void player_item_reset (PlayerItem* self, GeeHashSet* attrs); -GeeHashSet* metadata_menuitem_attributes_format (void); -void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes); -static void mpris_controller_onTrackChange (MprisController* self, DBusGProxy* mpris_client, GHashTable* ht); -GType transport_menuitem_action_get_type (void); DBusGProxy* mpris_controller_get_mpris_player (MprisController* self); 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 _dynamic_GetStatus0 (DBusGProxy* self, MprisControllerstatus* result, GError** error); -static void _dynamic_Play1 (DBusGProxy* self, GError** error); -static void _dynamic_Pause2 (DBusGProxy* self, GError** error); -static void _dynamic_Prev3 (DBusGProxy* self, GError** error); -static void _dynamic_Next4 (DBusGProxy* self, GError** error); +PlayerController* mpris_controller_get_owner (MprisController* self); +GType player_item_get_type (void); +GType player_controller_widget_order_get_type (void); +GType transport_menuitem_get_type (void); +void transport_menuitem_change_play_state (TransportMenuitem* self, gint state); +static GHashTable* _dynamic_GetMetadata1 (DBusGProxy* self, GError** error); +void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attributes); +GeeHashSet* metadata_menuitem_attributes_format (void); +static GHashTable* _dynamic_GetMetadata2 (DBusGProxy* self, GError** error); +GeeHashSet* scrub_menuitem_attributes_format (void); +GType scrub_menuitem_get_type (void); +static gint32 _dynamic_PositionGet3 (DBusGProxy* self, GError** error); +void scrub_menuitem_update_position (ScrubMenuitem* self, gint32 new_position); +static void mpris_controller_initial_update (MprisController* self); +GType transport_menuitem_action_get_type (void); +static void _dynamic_Pause4 (DBusGProxy* self, GError** error); +static void _dynamic_Prev5 (DBusGProxy* self, GError** error); +static void _dynamic_Next6 (DBusGProxy* self, GError** error); void mpris_controller_transport_event (MprisController* self, TransportMenuitemaction command); -gboolean mpris_controller_connected (MprisController* self); +static GHashTable* _dynamic_GetMetadata7 (DBusGProxy* self, GError** error); static GValue* _g_value_dup (GValue* self); -#define PLAYER_CONTROLLER_TRANSPORT 3 +static void _dynamic_PositionSet8 (DBusGProxy* self, gint32 param1, GError** error); +static gint32 _dynamic_PositionGet9 (DBusGProxy* self, GError** error); +void mpris_controller_set_position (MprisController* self, double position); +gboolean mpris_controller_connected (MprisController* self); GeeHashSet* transport_menuitem_attributes_format (void); static void mpris_controller_onStatusChange (MprisController* self, DBusGProxy* mpris_client, MprisControllerstatus* st); +void player_item_reset (PlayerItem* self, GeeHashSet* attrs); +static GHashTable* _dynamic_GetMetadata10 (DBusGProxy* self, GError** error); +static gint32 _dynamic_PositionGet11 (DBusGProxy* self, GError** error); +static void mpris_controller_onTrackChange (MprisController* self, DBusGProxy* mpris_client, GHashTable* ht); static void mpris_controller_set_mpris_player (MprisController* self, DBusGProxy* value); static void mpris_controller_set_owner (MprisController* self, PlayerController* value); const char* mpris_controller_get_mpris_interface (MprisController* self); @@ -171,10 +208,6 @@ static void _mpris_controller_onTrackChange_dynamic_TrackChange0_ (DBusGProxy* _ void _dynamic_TrackChange1_connect (gpointer obj, const char * signal_name, GCallback handler, gpointer data); 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); -static void _dynamic_GetStatus5 (DBusGProxy* self, MprisControllerstatus* result, GError** error); -GType transport_menuitem_get_type (void); -void transport_menuitem_change_play_state (TransportMenuitem* self, gint state); -static GHashTable* _dynamic_GetMetadata6 (DBusGProxy* self, GError** error); static GObject * mpris_controller_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties); static void mpris_controller_finalize (GObject* obj); static void mpris_controller_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); @@ -197,43 +230,113 @@ MprisController* mpris_controller_new (PlayerController* ctrl, const char* inter } -static void mpris_controller_onTrackChange (MprisController* self, DBusGProxy* mpris_client, GHashTable* ht) { - GeeHashSet* _tmp1_; - PlayerItem* _tmp0_; - GeeHashSet* _tmp3_; - PlayerItem* _tmp2_; - g_return_if_fail (self != NULL); - g_return_if_fail (mpris_client != NULL); - g_return_if_fail (ht != NULL); - g_debug ("mpris-controller.vala:68: onTrackChange"); - player_item_reset (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, PLAYER_CONTROLLER_METADATA), _tmp1_ = metadata_menuitem_attributes_format ()); - _g_object_unref0 (_tmp1_); - _g_object_unref0 (_tmp0_); - player_item_update (_tmp2_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, PLAYER_CONTROLLER_METADATA), ht, _tmp3_ = metadata_menuitem_attributes_format ()); - _g_object_unref0 (_tmp3_); - _g_object_unref0 (_tmp2_); -} - - static void _dynamic_GetStatus0 (DBusGProxy* self, MprisControllerstatus* result, GError** error) { GValueArray* dbus_result; - dbus_g_proxy_call (self, "GetStatus", error, G_TYPE_INVALID, dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INVALID), &dbus_result, G_TYPE_INVALID); + dbus_g_proxy_call (self, "GetStatus", error, G_TYPE_INVALID, dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INVALID), &dbus_result, G_TYPE_INVALID); if (*error) { return; } result->playback = g_value_get_int (&dbus_result->values[0]); + result->shuffle = g_value_get_int (&dbus_result->values[1]); + result->repeat = g_value_get_int (&dbus_result->values[2]); + result->endless = g_value_get_int (&dbus_result->values[3]); } -static void _dynamic_Play1 (DBusGProxy* self, GError** error) { - dbus_g_proxy_call (self, "Play", error, G_TYPE_INVALID, G_TYPE_INVALID); +static GHashTable* _dynamic_GetMetadata1 (DBusGProxy* self, GError** error) { + GHashTable* result; + dbus_g_proxy_call (self, "GetMetadata", error, G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &result, G_TYPE_INVALID); if (*error) { + return NULL; + } + return result; +} + + +static GHashTable* _dynamic_GetMetadata2 (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; +} + + +static gint32 _dynamic_PositionGet3 (DBusGProxy* self, GError** error) { + gint32 result; + dbus_g_proxy_call (self, "PositionGet", error, G_TYPE_INVALID, G_TYPE_INT, &result, G_TYPE_INVALID); + if (*error) { + return 0; + } + return result; +} + + +static void mpris_controller_initial_update (MprisController* self) { + GError * _inner_error_; + MprisControllerstatus _tmp0_ = {0}; + MprisControllerstatus st; + gint play_state; + TransportMenuitem* _tmp2_; + PlayerItem* _tmp1_; + GHashTable* _tmp3_; + GeeHashSet* _tmp6_; + GHashTable* _tmp5_; + PlayerItem* _tmp4_; + GHashTable* _tmp7_; + GeeHashSet* _tmp10_; + GHashTable* _tmp9_; + PlayerItem* _tmp8_; + PlayerItem* _tmp11_; + ScrubMenuitem* scrub; + gint32 _tmp12_; + g_return_if_fail (self != NULL); + _inner_error_ = NULL; + st = (_dynamic_GetStatus0 (self->priv->_mpris_player, &_tmp0_, &_inner_error_), _tmp0_); + 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; + } + play_state = (gint) st.playback; + g_debug ("mpris-controller.vala:60: GetStatusChange - play state %i", play_state); + transport_menuitem_change_play_state (_tmp2_ = (_tmp1_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT), IS_TRANSPORT_MENUITEM (_tmp1_) ? ((TransportMenuitem*) _tmp1_) : NULL), play_state); + _g_object_unref0 (_tmp2_); + _tmp3_ = _dynamic_GetMetadata1 (self->priv->_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; + } + player_item_update (_tmp4_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA), _tmp5_ = _tmp3_, _tmp6_ = metadata_menuitem_attributes_format ()); + _g_object_unref0 (_tmp6_); + _g_hash_table_unref0 (_tmp5_); + _g_object_unref0 (_tmp4_); + _tmp7_ = _dynamic_GetMetadata2 (self->priv->_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; } + player_item_update (_tmp8_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB), _tmp9_ = _tmp7_, _tmp10_ = scrub_menuitem_attributes_format ()); + _g_object_unref0 (_tmp10_); + _g_hash_table_unref0 (_tmp9_); + _g_object_unref0 (_tmp8_); + scrub = (_tmp11_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB), IS_SCRUB_MENUITEM (_tmp11_) ? ((ScrubMenuitem*) _tmp11_) : NULL); + _tmp12_ = _dynamic_PositionGet3 (self->priv->_mpris_player, &_inner_error_); + if (_inner_error_ != NULL) { + _g_object_unref0 (scrub); + 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; + } + scrub_menuitem_update_position (scrub, _tmp12_); + _g_object_unref0 (scrub); } -static void _dynamic_Pause2 (DBusGProxy* self, GError** error) { +static void _dynamic_Pause4 (DBusGProxy* self, GError** error) { dbus_g_proxy_call (self, "Pause", error, G_TYPE_INVALID, G_TYPE_INVALID); if (*error) { return; @@ -241,7 +344,7 @@ static void _dynamic_Pause2 (DBusGProxy* self, GError** error) { } -static void _dynamic_Prev3 (DBusGProxy* self, GError** error) { +static void _dynamic_Prev5 (DBusGProxy* self, GError** error) { dbus_g_proxy_call (self, "Prev", error, G_TYPE_INVALID, G_TYPE_INVALID); if (*error) { return; @@ -249,7 +352,7 @@ static void _dynamic_Prev3 (DBusGProxy* self, GError** error) { } -static void _dynamic_Next4 (DBusGProxy* self, GError** error) { +static void _dynamic_Next6 (DBusGProxy* self, GError** error) { dbus_g_proxy_call (self, "Next", error, G_TYPE_INVALID, G_TYPE_INVALID); if (*error) { return; @@ -261,42 +364,18 @@ void mpris_controller_transport_event (MprisController* self, TransportMenuitema GError * _inner_error_; g_return_if_fail (self != NULL); _inner_error_ = NULL; - g_debug ("mpris-controller.vala:80: transport_event input = %i", (gint) command); + g_debug ("mpris-controller.vala:73: transport_event input = %i", (gint) command); if (command == TRANSPORT_MENUITEM_ACTION_PLAY_PAUSE) { - MprisControllerstatus _tmp0_ = {0}; - MprisControllerstatus st; - gboolean play_state; - gboolean new_play_state; - st = (_dynamic_GetStatus0 (self->priv->_mpris_player, &_tmp0_, &_inner_error_), _tmp0_); + g_debug ("mpris-controller.vala:75: transport_event PLAY_PAUSE"); + _dynamic_Pause4 (self->priv->_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; } - play_state = st.playback == 1; - g_debug ("mpris-controller.vala:84: toggle_playback - initial play state %i", (gint) play_state); - new_play_state = !play_state; - g_debug ("mpris-controller.vala:86: toggle_playback - new play state %i", (gint) new_play_state); - if (new_play_state == TRUE) { - g_debug ("mpris-controller.vala:88: about to play"); - _dynamic_Play1 (self->priv->_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:92: about to pause"); - _dynamic_Pause2 (self->priv->_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 { if (command == TRANSPORT_MENUITEM_ACTION_PREVIOUS) { - _dynamic_Prev3 (self->priv->_mpris_player, &_inner_error_); + _dynamic_Prev5 (self->priv->_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_); @@ -304,7 +383,7 @@ void mpris_controller_transport_event (MprisController* self, TransportMenuitema } } else { if (command == TRANSPORT_MENUITEM_ACTION_NEXT) { - _dynamic_Next4 (self->priv->_mpris_player, &_inner_error_); + _dynamic_Next6 (self->priv->_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_); @@ -316,10 +395,12 @@ void mpris_controller_transport_event (MprisController* self, TransportMenuitema } -gboolean mpris_controller_connected (MprisController* self) { - gboolean result = FALSE; - g_return_val_if_fail (self != NULL, FALSE); - result = self->priv->_mpris_player != NULL; +static GHashTable* _dynamic_GetMetadata7 (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; } @@ -334,6 +415,87 @@ static gpointer __g_value_dup0 (gpointer self) { } +static void _dynamic_PositionSet8 (DBusGProxy* self, gint32 param1, GError** error) { + dbus_g_proxy_call (self, "PositionSet", error, G_TYPE_INT, param1, G_TYPE_INVALID, G_TYPE_INVALID); + if (*error) { + return; + } +} + + +static gint32 _dynamic_PositionGet9 (DBusGProxy* self, GError** error) { + gint32 result; + dbus_g_proxy_call (self, "PositionGet", error, G_TYPE_INVALID, G_TYPE_INT, &result, G_TYPE_INVALID); + if (*error) { + return 0; + } + return result; +} + + +void mpris_controller_set_position (MprisController* self, double position) { + GError * _inner_error_; + GHashTable* data; + GValue* time_value; + guint32 total_time; + double new_time_position; + PlayerItem* _tmp0_; + ScrubMenuitem* scrub; + gint32 _tmp1_; + g_return_if_fail (self != NULL); + _inner_error_ = NULL; + g_debug ("mpris-controller.vala:88: Set position with pos (0-100) %f", position); + data = _dynamic_GetMetadata7 (self->priv->_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; + } + time_value = __g_value_dup0 ((GValue*) g_hash_table_lookup (data, "time")); + if (time_value == NULL) { + g_warning ("mpris-controller.vala:92: Can't fetch the duration of the track theref" \ +"ore cant set the position"); + _g_hash_table_unref0 (data); + _g_free0 (time_value); + return; + } + total_time = (guint32) g_value_get_uint (time_value); + g_debug ("mpris-controller.vala:96: total time of track = %i", (gint) total_time); + new_time_position = (total_time * position) / 100.0; + g_debug ("mpris-controller.vala:98: new position = %f", new_time_position * 1000); + _dynamic_PositionSet8 (self->priv->_mpris_player, (gint32) new_time_position, &_inner_error_); + if (_inner_error_ != NULL) { + _g_hash_table_unref0 (data); + _g_free0 (time_value); + 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; + } + scrub = (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB), IS_SCRUB_MENUITEM (_tmp0_) ? ((ScrubMenuitem*) _tmp0_) : NULL); + _tmp1_ = _dynamic_PositionGet9 (self->priv->_mpris_player, &_inner_error_); + if (_inner_error_ != NULL) { + _g_hash_table_unref0 (data); + _g_free0 (time_value); + _g_object_unref0 (scrub); + 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; + } + scrub_menuitem_update_position (scrub, _tmp1_); + _g_hash_table_unref0 (data); + _g_free0 (time_value); + _g_object_unref0 (scrub); +} + + +gboolean mpris_controller_connected (MprisController* self) { + gboolean result = FALSE; + g_return_val_if_fail (self != NULL, FALSE); + result = self->priv->_mpris_player != NULL; + return result; +} + + static void mpris_controller_onStatusChange (MprisController* self, DBusGProxy* mpris_client, MprisControllerstatus* st) { MprisControllerstatus* status; GValueArray* ar; @@ -342,6 +504,8 @@ static void mpris_controller_onStatusChange (MprisController* self, DBusGProxy* GValue v = {0}; GeeHashSet* _tmp1_; PlayerItem* _tmp0_; + GeeHashSet* _tmp3_; + PlayerItem* _tmp2_; g_return_if_fail (self != NULL); g_return_if_fail (mpris_client != NULL); g_debug ("mpris-controller.vala:111: onStatusChange - signal received"); @@ -353,14 +517,91 @@ static void mpris_controller_onStatusChange (MprisController* self, DBusGProxy* g_value_init (&v, G_TYPE_INT); g_value_set_int (&v, play_state); g_hash_table_insert (ht, g_strdup ("state"), __g_value_dup0 (&v)); - player_item_update (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, PLAYER_CONTROLLER_TRANSPORT), ht, _tmp1_ = transport_menuitem_attributes_format ()); + player_item_update (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT), ht, _tmp1_ = transport_menuitem_attributes_format ()); _g_object_unref0 (_tmp1_); _g_object_unref0 (_tmp0_); + player_item_update (_tmp2_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB), ht, _tmp3_ = scrub_menuitem_attributes_format ()); + _g_object_unref0 (_tmp3_); + _g_object_unref0 (_tmp2_); _g_hash_table_unref0 (ht); G_IS_VALUE (&v) ? (g_value_unset (&v), NULL) : NULL; } +static GHashTable* _dynamic_GetMetadata10 (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; +} + + +static gint32 _dynamic_PositionGet11 (DBusGProxy* self, GError** error) { + gint32 result; + dbus_g_proxy_call (self, "PositionGet", error, G_TYPE_INVALID, G_TYPE_INT, &result, G_TYPE_INVALID); + if (*error) { + return 0; + } + return result; +} + + +static void mpris_controller_onTrackChange (MprisController* self, DBusGProxy* mpris_client, GHashTable* ht) { + GError * _inner_error_; + GeeHashSet* _tmp1_; + PlayerItem* _tmp0_; + GeeHashSet* _tmp3_; + PlayerItem* _tmp2_; + GeeHashSet* _tmp5_; + PlayerItem* _tmp4_; + GHashTable* _tmp6_; + GeeHashSet* _tmp9_; + GHashTable* _tmp8_; + PlayerItem* _tmp7_; + PlayerItem* _tmp10_; + ScrubMenuitem* scrub; + gint32 _tmp11_; + g_return_if_fail (self != NULL); + g_return_if_fail (mpris_client != NULL); + g_return_if_fail (ht != NULL); + _inner_error_ = NULL; + g_debug ("mpris-controller.vala:126: onTrackChange"); + player_item_reset (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA), _tmp1_ = metadata_menuitem_attributes_format ()); + _g_object_unref0 (_tmp1_); + _g_object_unref0 (_tmp0_); + player_item_reset (_tmp2_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB), _tmp3_ = scrub_menuitem_attributes_format ()); + _g_object_unref0 (_tmp3_); + _g_object_unref0 (_tmp2_); + player_item_update (_tmp4_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA), ht, _tmp5_ = metadata_menuitem_attributes_format ()); + _g_object_unref0 (_tmp5_); + _g_object_unref0 (_tmp4_); + g_debug ("mpris-controller.vala:131: about to update the duration on the scrub b" \ +"ar"); + _tmp6_ = _dynamic_GetMetadata10 (self->priv->_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; + } + player_item_update (_tmp7_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB), _tmp8_ = _tmp6_, _tmp9_ = scrub_menuitem_attributes_format ()); + _g_object_unref0 (_tmp9_); + _g_hash_table_unref0 (_tmp8_); + _g_object_unref0 (_tmp7_); + scrub = (_tmp10_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB), IS_SCRUB_MENUITEM (_tmp10_) ? ((ScrubMenuitem*) _tmp10_) : NULL); + _tmp11_ = _dynamic_PositionGet11 (self->priv->_mpris_player, &_inner_error_); + if (_inner_error_ != NULL) { + _g_object_unref0 (scrub); + 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; + } + scrub_menuitem_update_position (scrub, _tmp11_); + _g_object_unref0 (scrub); +} + + DBusGProxy* mpris_controller_get_mpris_player (MprisController* self) { DBusGProxy* result; g_return_val_if_fail (self != NULL, NULL); @@ -432,32 +673,12 @@ static void _mpris_controller_onStatusChange_dynamic_StatusChange2_ (DBusGProxy* 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_INVALID), G_TYPE_INVALID); - dbus_g_proxy_add_signal (obj, "StatusChange", dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INVALID), G_TYPE_INVALID); + 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); } -static void _dynamic_GetStatus5 (DBusGProxy* self, MprisControllerstatus* result, GError** error) { - GValueArray* dbus_result; - dbus_g_proxy_call (self, "GetStatus", error, G_TYPE_INVALID, dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_INVALID), &dbus_result, G_TYPE_INVALID); - if (*error) { - return; - } - result->playback = g_value_get_int (&dbus_result->values[0]); -} - - -static GHashTable* _dynamic_GetMetadata6 (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; -} - - static GObject * mpris_controller_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) { GObject * obj; GObjectClass * parent_class; @@ -473,15 +694,6 @@ static GObject * mpris_controller_constructor (GType type, guint n_construct_pro char* _tmp2_; char* _tmp6_; char* _tmp5_; - MprisControllerstatus _tmp7_ = {0}; - MprisControllerstatus st; - gint play_state; - TransportMenuitem* _tmp9_; - PlayerItem* _tmp8_; - GHashTable* _tmp10_; - GeeHashSet* _tmp13_; - GHashTable* _tmp12_; - PlayerItem* _tmp11_; { DBusGConnection* _tmp0_; DBusGConnection* _tmp1_; @@ -498,7 +710,7 @@ static GObject * mpris_controller_constructor (GType type, guint n_construct_pro e = _inner_error_; _inner_error_ = NULL; { - g_error ("mpris-controller.vala:47: Problems connecting to the session bus - %s", e->message); + g_error ("mpris-controller.vala:45: Problems connecting to the session bus - %s", e->message); _g_error_free0 (e); } } @@ -511,30 +723,13 @@ static GObject * mpris_controller_constructor (GType type, guint n_construct_pro _g_object_unref0 (_tmp4_); _g_free0 (_tmp3_); _g_free0 (_tmp2_); - g_debug ("mpris-controller.vala:51: just attempting to establish an mpris connec" \ -"tion to %s, %s, %s", _tmp6_ = g_strconcat ("org.mpris.", _tmp5_ = g_utf8_strdown (player_controller_get_name (self->priv->_owner), -1), NULL), "/Player", self->priv->_mpris_interface); + g_debug ("mpris-controller.vala:49: Attempting to establish an mpris connection " \ +"to %s, %s, %s", _tmp6_ = g_strconcat ("org.mpris.", _tmp5_ = g_utf8_strdown (player_controller_get_name (self->priv->_owner), -1), NULL), "/Player", self->priv->_mpris_interface); _g_free0 (_tmp6_); _g_free0 (_tmp5_); _dynamic_TrackChange1_connect (self->priv->_mpris_player, "TrackChange", (GCallback) _mpris_controller_onTrackChange_dynamic_TrackChange0_, self); _dynamic_StatusChange3_connect (self->priv->_mpris_player, "StatusChange", (GCallback) _mpris_controller_onStatusChange_dynamic_StatusChange2_, self); - st = (_dynamic_GetStatus5 (self->priv->_mpris_player, &_tmp7_, &_inner_error_), _tmp7_); - 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_); - } - play_state = (gint) st.playback; - g_debug ("mpris-controller.vala:58: GetStatusChange - play state %i", play_state); - transport_menuitem_change_play_state (_tmp9_ = (_tmp8_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, PLAYER_CONTROLLER_TRANSPORT), IS_TRANSPORT_MENUITEM (_tmp8_) ? ((TransportMenuitem*) _tmp8_) : NULL), play_state); - _g_object_unref0 (_tmp9_); - _tmp10_ = _dynamic_GetMetadata6 (self->priv->_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_); - } - player_item_update (_tmp11_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->priv->_owner->custom_items, PLAYER_CONTROLLER_METADATA), _tmp12_ = _tmp10_, _tmp13_ = metadata_menuitem_attributes_format ()); - _g_object_unref0 (_tmp13_); - _g_hash_table_unref0 (_tmp12_); - _g_object_unref0 (_tmp11_); + mpris_controller_initial_update (self); } return obj; } @@ -589,7 +784,6 @@ static void mpris_controller_finalize (GObject* obj) { _g_object_unref0 (self->priv->_mpris_player); _g_object_unref0 (self->priv->_owner); _g_free0 (self->priv->_mpris_interface); - _g_free0 (self->priv->name); G_OBJECT_CLASS (mpris_controller_parent_class)->finalize (obj); } diff --git a/src/mpris-controller.vala b/src/mpris-controller.vala index 8dd0cc9..8ecd20a 100644 --- a/src/mpris-controller.vala +++ b/src/mpris-controller.vala @@ -26,14 +26,12 @@ public class MprisController : GLib.Object public dynamic DBus.Object mpris_player{get; construct;} public PlayerController owner {get; construct;} public string mpris_interface {get; construct;} - private string name; - struct status { public int32 playback; - //public int32 shuffle; // Not used just yet - //public int32 repeat; - //public int32 endless; + public int32 shuffle; + public int32 repeat; + public int32 endless; } public MprisController(PlayerController ctrl, string inter="org.freedesktop.MediaPlayer"){ @@ -48,50 +46,34 @@ public class MprisController : GLib.Object } this.mpris_player = this.connection.get_object ("org.mpris.".concat(this.owner.name.down()) , "/Player", this.mpris_interface); - debug("just attempting to establish an mpris connection to %s, %s, %s", "org.mpris.".concat(this.owner.name.down()) , "/Player", this.mpris_interface); + debug("Attempting to establish an mpris connection to %s, %s, %s", "org.mpris.".concat(this.owner.name.down()) , "/Player", this.mpris_interface); this.mpris_player.TrackChange += onTrackChange; this.mpris_player.StatusChange += onStatusChange; + initial_update(); + } + private void initial_update() + { status st = this.mpris_player.GetStatus(); int play_state = st.playback; debug("GetStatusChange - play state %i", play_state); - (this.owner.custom_items[this.owner.TRANSPORT] as TransportMenuitem).change_play_state(play_state); - this.owner.custom_items[this.owner.METADATA].update(this.mpris_player.GetMetadata(), - MetadataMenuitem.attributes_format()); - - } - - - private void onTrackChange(dynamic DBus.Object mpris_client, HashTable<string,Value?> ht) - { - debug("onTrackChange"); - this.owner.custom_items[this.owner.METADATA].reset(MetadataMenuitem.attributes_format()); - this.owner.custom_items[this.owner.METADATA].update(ht, + (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(play_state); + this.owner.custom_items[PlayerController.widget_order.METADATA].update(this.mpris_player.GetMetadata(), MetadataMenuitem.attributes_format()); + this.owner.custom_items[PlayerController.widget_order.SCRUB].update(this.mpris_player.GetMetadata(), + ScrubMenuitem.attributes_format()); + // temporary fix + ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem; + scrub.update_position(this.mpris_player.PositionGet()); } - /** - * TRUE => Playing - * FALSE => Paused - **/ public void transport_event(TransportMenuitem.action command) { debug("transport_event input = %i", (int)command); if(command == TransportMenuitem.action.PLAY_PAUSE){ - status st = this.mpris_player.GetStatus(); - bool play_state = st.playback == 1; - debug("toggle_playback - initial play state %i", (int)play_state); - bool new_play_state = !play_state; - debug("toggle_playback - new play state %i", (int)new_play_state); - if(new_play_state == true){ - debug("about to play"); - this.mpris_player.Play(); - } - else{ - debug("about to pause"); - this.mpris_player.Pause(); - } + debug("transport_event PLAY_PAUSE"); + this.mpris_player.Pause(); } else if(command == TransportMenuitem.action.PREVIOUS){ this.mpris_player.Prev(); @@ -101,6 +83,24 @@ public class MprisController : GLib.Object } } + public void set_position(double position) + { + debug("Set position with pos (0-100) %f", position); + HashTable<string, Value?> data = this.mpris_player.GetMetadata(); + Value? time_value = data.lookup("time"); + if(time_value == null){ + warning("Can't fetch the duration of the track therefore cant set the position"); + return; + } + uint32 total_time = time_value.get_uint(); + debug("total time of track = %i", (int)total_time); + double new_time_position = total_time * position/100.0; + debug("new position = %f", (new_time_position * 1000)); + this.mpris_player.PositionSet((int32)(new_time_position)); + ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem; + scrub.update_position(this.mpris_player.PositionGet()); + } + public bool connected() { return (this.mpris_player != null); @@ -108,7 +108,7 @@ public class MprisController : GLib.Object private void onStatusChange(dynamic DBus.Object mpris_client, status st) { - debug("onStatusChange - signal received"); + debug("onStatusChange - signal received"); status* status = &st; unowned ValueArray ar = (ValueArray)status; int play_state = ar.get_nth(0).get_int(); @@ -117,8 +117,24 @@ public class MprisController : GLib.Object Value v = Value(typeof(int)); v.set_int(play_state); ht.insert("state", v); - this.owner.custom_items[this.owner.TRANSPORT].update(ht, TransportMenuitem.attributes_format()); + this.owner.custom_items[PlayerController.widget_order.TRANSPORT].update(ht, TransportMenuitem.attributes_format()); + this.owner.custom_items[PlayerController.widget_order.SCRUB].update(ht, ScrubMenuitem.attributes_format()); } - + + private void onTrackChange(dynamic DBus.Object mpris_client, HashTable<string,Value?> ht) + { + debug("onTrackChange"); + this.owner.custom_items[PlayerController.widget_order.METADATA].reset(MetadataMenuitem.attributes_format()); + this.owner.custom_items[PlayerController.widget_order.SCRUB].reset(ScrubMenuitem.attributes_format()); + this.owner.custom_items[PlayerController.widget_order.METADATA].update(ht, + MetadataMenuitem.attributes_format()); + debug("about to update the duration on the scrub bar"); + this.owner.custom_items[PlayerController.widget_order.SCRUB].update(this.mpris_player.GetMetadata(), + ScrubMenuitem.attributes_format()); + // temporary fix + ScrubMenuitem scrub = this.owner.custom_items[PlayerController.widget_order.SCRUB] as ScrubMenuitem; + scrub.update_position(this.mpris_player.PositionGet()); + } + } diff --git a/src/music-player-bridge.c b/src/music-player-bridge.c index 2dfc99c..aa4e5dd 100644 --- a/src/music-player-bridge.c +++ b/src/music-player-bridge.c @@ -129,6 +129,7 @@ GType player_controller_state_get_type (void); PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* client_name, gint offset, PlayerControllerstate initial_state); PlayerController* player_controller_construct (GType object_type, DbusmenuMenuitem* root, const char* client_name, gint offset, PlayerControllerstate initial_state); static void music_player_bridge_try_to_add_inactive_familiar_clients (MusicPlayerBridge* self); +#define PLAYER_CONTROLLER_WIDGET_QUANTITY 5 static gboolean music_player_bridge_server_is_not_of_interest (MusicPlayerBridge* self, const char* type); void player_controller_update_state (PlayerController* self, PlayerControllerstate new_state); void player_controller_activate (PlayerController* self); @@ -284,7 +285,7 @@ static gint music_player_bridge_calculate_menu_position (MusicPlayerBridge* self result = 2; return result; } else { - result = 2 + (gee_map_get_size ((GeeMap*) self->priv->registered_clients) * 4); + result = 2 + (gee_map_get_size ((GeeMap*) self->priv->registered_clients) * PLAYER_CONTROLLER_WIDGET_QUANTITY); return result; } } @@ -328,7 +329,7 @@ void music_player_bridge_on_server_added (MusicPlayerBridge* self, IndicateListe PlayerController* ctrl; ctrl = player_controller_new (self->priv->root_menu, client_name, music_player_bridge_calculate_menu_position (self), PLAYER_CONTROLLER_STATE_READY); gee_abstract_map_set ((GeeAbstractMap*) self->priv->registered_clients, client_name, ctrl); - g_debug ("music-player-bridge.vala:105: New Client of name %s has successfully r" \ + g_debug ("music-player-bridge.vala:103: New Client of name %s has successfully r" \ "egistered with us", client_name); _g_object_unref0 (ctrl); } @@ -351,7 +352,7 @@ void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateLis gboolean _tmp3_ = FALSE; g_return_if_fail (self != NULL); g_return_if_fail (type != NULL); - g_debug ("music-player-bridge.vala:117: MusicPlayerBridge -> on_server_removed w" \ + g_debug ("music-player-bridge.vala:115: MusicPlayerBridge -> on_server_removed w" \ "ith value %s", type); if (music_player_bridge_server_is_not_of_interest (self, type)) { return; @@ -367,7 +368,7 @@ void music_player_bridge_on_server_removed (MusicPlayerBridge* self, IndicateLis player_controller_vanish (_tmp4_ = (PlayerController*) gee_abstract_map_get ((GeeAbstractMap*) self->priv->registered_clients, client_name)); _g_object_unref0 (_tmp4_); gee_map_remove ((GeeMap*) self->priv->registered_clients, client_name, NULL); - g_debug ("music-player-bridge.vala:123: Successively removed menu_item for clien" \ + g_debug ("music-player-bridge.vala:121: Successively removed menu_item for clien" \ "t %s from registered_clients", client_name); } _g_free0 (client_name); @@ -392,7 +393,7 @@ static gboolean music_player_bridge_server_is_not_of_interest (MusicPlayerBridge return result; } if (string_contains (type, "music") == FALSE) { - g_debug ("music-player-bridge.vala:131: server is of no interest, it is not an " \ + g_debug ("music-player-bridge.vala:129: server is of no interest, it is not an " \ "music server"); result = TRUE; return result; @@ -416,7 +417,7 @@ static void music_player_bridge_desktop_info_callback (MusicPlayerBridge* self, } if (_tmp1_) { GAppInfo* app_info; - g_debug ("music-player-bridge.vala:142: About to store desktop file path: %s", path); + g_debug ("music-player-bridge.vala:140: About to store desktop file path: %s", path); familiar_players_db_insert (bridge->priv->playersDB, path); app_info = music_player_bridge_create_app_info (path); if (app_info != NULL) { @@ -426,13 +427,13 @@ static void music_player_bridge_desktop_info_callback (MusicPlayerBridge* self, PlayerController* ctrl; ctrl = (_tmp4_ = (PlayerController*) gee_abstract_map_get ((GeeAbstractMap*) bridge->priv->registered_clients, _tmp3_ = string_strip (_tmp2_ = g_utf8_strdown (g_app_info_get_name (app_info), -1))), _g_free0 (_tmp3_), _g_free0 (_tmp2_), _tmp4_); g_object_set ((GObject*) ctrl, "app_info", app_info, NULL); - g_debug ("music-player-bridge.vala:148: successfully created appinfo from path a" \ + g_debug ("music-player-bridge.vala:146: successfully created appinfo from path a" \ "nd set it on the respective instance"); _g_object_unref0 (ctrl); } _g_object_unref0 (app_info); } else { - g_debug ("music-player-bridge.vala:152: Ignoring desktop file path because its e" \ + g_debug ("music-player-bridge.vala:150: Ignoring desktop file path because its e" \ "ither invalid of the db cache file has it already: %s", path); } _g_object_unref0 (bridge); @@ -451,20 +452,20 @@ void music_player_bridge_set_root_menu_item (MusicPlayerBridge* self, DbusmenuMe 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:164: MusicPlayerBridge-> on_server_count_chan" \ + g_debug ("music-player-bridge.vala:162: MusicPlayerBridge-> on_server_count_chan" \ "ged with value %u", i); } void music_player_bridge_on_indicator_added (MusicPlayerBridge* self, IndicateListenerServer* object, IndicateListenerIndicator* p0) { g_return_if_fail (self != NULL); - g_debug ("music-player-bridge.vala:168: MusicPlayerBridge-> on_indicator_added"); + g_debug ("music-player-bridge.vala:166: 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:173: MusicPlayerBridge -> on_indicator_remove" \ + g_debug ("music-player-bridge.vala:171: MusicPlayerBridge -> on_indicator_remove" \ "d"); } @@ -472,7 +473,7 @@ void music_player_bridge_on_indicator_removed (MusicPlayerBridge* self, Indicate 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:178: MusicPlayerBridge -> indicator_modified " \ + g_debug ("music-player-bridge.vala:176: MusicPlayerBridge -> indicator_modified " \ "with vale %s", s); } @@ -485,7 +486,7 @@ GAppInfo* music_player_bridge_create_app_info (const char* path) { g_return_val_if_fail (path != NULL, NULL); info = g_desktop_app_info_new_from_filename (path); if (path == NULL) { - g_warning ("music-player-bridge.vala:185: Could not create a desktopappinfo instan" \ + g_warning ("music-player-bridge.vala:183: Could not create a desktopappinfo instan" \ "ce from app: %s", path); result = NULL; _g_object_unref0 (info); diff --git a/src/music-player-bridge.h b/src/music-player-bridge.h index baeb597..03c8831 100644 --- a/src/music-player-bridge.h +++ b/src/music-player-bridge.h @@ -19,6 +19,8 @@ #include <libdbusmenu-glib/server.h> #include <gio/gio.h> #include <gee.h> +#include <float.h> +#include <math.h> #include <dbus/dbus-glib-lowlevel.h> #include <dbus/dbus-glib.h> @@ -81,6 +83,17 @@ typedef struct _MetadataMenuitem MetadataMenuitem; typedef struct _MetadataMenuitemClass MetadataMenuitemClass; typedef struct _MetadataMenuitemPrivate MetadataMenuitemPrivate; +#define TYPE_SCRUB_MENUITEM (scrub_menuitem_get_type ()) +#define SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitem)) +#define SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) +#define IS_SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCRUB_MENUITEM)) +#define IS_SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCRUB_MENUITEM)) +#define SCRUB_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) + +typedef struct _ScrubMenuitem ScrubMenuitem; +typedef struct _ScrubMenuitemClass ScrubMenuitemClass; +typedef struct _ScrubMenuitemPrivate ScrubMenuitemPrivate; + #define TYPE_TITLE_MENUITEM (title_menuitem_get_type ()) #define TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TITLE_MENUITEM, TitleMenuitem)) #define TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) @@ -103,6 +116,8 @@ typedef struct _PlayerControllerPrivate PlayerControllerPrivate; typedef struct _MprisController MprisController; typedef struct _MprisControllerClass MprisControllerClass; +#define PLAYER_CONTROLLER_TYPE_WIDGET_ORDER (player_controller_widget_order_get_type ()) + #define PLAYER_CONTROLLER_TYPE_STATE (player_controller_state_get_type ()) typedef struct _MprisControllerPrivate MprisControllerPrivate; @@ -170,6 +185,15 @@ struct _MetadataMenuitemClass { PlayerItemClass parent_class; }; +struct _ScrubMenuitem { + PlayerItem parent_instance; + ScrubMenuitemPrivate * priv; +}; + +struct _ScrubMenuitemClass { + PlayerItemClass parent_class; +}; + struct _TitleMenuitem { PlayerItem parent_instance; TitleMenuitemPrivate * priv; @@ -192,6 +216,14 @@ struct _PlayerControllerClass { }; typedef enum { + PLAYER_CONTROLLER_WIDGET_ORDER_SEPARATOR, + PLAYER_CONTROLLER_WIDGET_ORDER_TITLE, + PLAYER_CONTROLLER_WIDGET_ORDER_METADATA, + PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB, + PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT +} PlayerControllerwidget_order; + +typedef enum { PLAYER_CONTROLLER_STATE_OFFLINE, PLAYER_CONTROLLER_STATE_INSTANTIATING, PLAYER_CONTROLLER_STATE_READY, @@ -250,20 +282,27 @@ GType metadata_menuitem_get_type (void); MetadataMenuitem* metadata_menuitem_new (void); MetadataMenuitem* metadata_menuitem_construct (GType object_type); GeeHashSet* metadata_menuitem_attributes_format (void); -gboolean metadata_menuitem_populated (MetadataMenuitem* self); +gboolean metadata_menuitem_not_populated (MetadataMenuitem* self); +GType scrub_menuitem_get_type (void); +ScrubMenuitem* scrub_menuitem_new (PlayerController* parent); +ScrubMenuitem* scrub_menuitem_construct (GType object_type, PlayerController* parent); +void scrub_menuitem_update_position (ScrubMenuitem* self, gint32 new_position); +GeeHashSet* scrub_menuitem_attributes_format (void); GType title_menuitem_get_type (void); TitleMenuitem* title_menuitem_new (PlayerController* parent); TitleMenuitem* title_menuitem_construct (GType object_type, PlayerController* parent); GeeHashSet* title_menuitem_attributes_format (void); GType mpris_controller_get_type (void); +GType player_controller_widget_order_get_type (void); GType player_controller_state_get_type (void); -#define PLAYER_CONTROLLER_METADATA 2 +#define PLAYER_CONTROLLER_WIDGET_QUANTITY 5 PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* client_name, gint offset, PlayerControllerstate initial_state); PlayerController* player_controller_construct (GType object_type, DbusmenuMenuitem* root, const char* client_name, gint offset, PlayerControllerstate initial_state); void player_controller_update_state (PlayerController* self, PlayerControllerstate new_state); void player_controller_activate (PlayerController* self); void player_controller_instantiate (PlayerController* self); void player_controller_vanish (PlayerController* self); +void player_controller_update_layout (PlayerController* self); const char* player_controller_get_name (PlayerController* self); void player_controller_set_name (PlayerController* self, const char* value); GAppInfo* player_controller_get_app_info (PlayerController* self); @@ -276,6 +315,7 @@ MprisControllerV2* mpris_controller_v2_construct (GType object_type, PlayerContr MprisController* mpris_controller_new (PlayerController* ctrl, const char* inter); MprisController* mpris_controller_construct (GType object_type, PlayerController* ctrl, const char* inter); void mpris_controller_transport_event (MprisController* self, TransportMenuitemaction command); +void mpris_controller_set_position (MprisController* self, double position); gboolean mpris_controller_connected (MprisController* self); DBusGProxy* mpris_controller_get_mpris_player (MprisController* self); PlayerController* mpris_controller_get_owner (MprisController* self); diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala index 2f87b2d..352ea7f 100644 --- a/src/music-player-bridge.vala +++ b/src/music-player-bridge.vala @@ -35,7 +35,7 @@ public class MusicPlayerBridge : GLib.Object playersDB = new FamiliarPlayersDB(); registered_clients = new HashMap<string, PlayerController> (); listener = Listener.ref_default(); - listener.indicator_added.connect(on_indicator_added); + listener.indicator_added += on_indicator_added; listener.indicator_removed.connect(on_indicator_removed); listener.indicator_modified.connect(on_indicator_modified); listener.server_added.connect(on_server_added); @@ -77,7 +77,7 @@ public class MusicPlayerBridge : GLib.Object return 2; } else{ - return (2 + (this.registered_clients.size * 4)); + return (2 + (this.registered_clients.size * PlayerController.WIDGET_QUANTITY)); } } @@ -93,15 +93,13 @@ public class MusicPlayerBridge : GLib.Object this.registered_clients[client_name].update_state(PlayerController.state.READY); this.registered_clients[client_name].activate(); } - //else init a new one else{ - + //else init a new one PlayerController ctrl = new PlayerController(root_menu, client_name, calculate_menu_position(), PlayerController.state.READY); - registered_clients.set(client_name, ctrl); - + registered_clients.set(client_name, ctrl); debug("New Client of name %s has successfully registered with us", client_name); } // irregardless check that it has a desktop file if not kick off a request for it @@ -163,7 +161,7 @@ public class MusicPlayerBridge : GLib.Object { debug("MusicPlayerBridge-> on_server_count_changed with value %u", i); } - public void on_indicator_added(Indicate.ListenerServer object, Indicate.ListenerIndicator p0) + public void on_indicator_added(ListenerServer object, ListenerIndicator p0) { debug("MusicPlayerBridge-> on_indicator_added"); } diff --git a/src/play-button.c b/src/play-button.c index d6d243c..1aeff12 100644 --- a/src/play-button.c +++ b/src/play-button.c @@ -52,23 +52,22 @@ Uses code from ctk #define BAR_OFFSET 10.0f #define PAUSE_X 77.0f #define PAUSE_Y 15.0f - -// Transport events -enum { - PREVIOUS, - PLAY_PAUSE, - NEXT -}; +#define PLAY_WIDTH 28.0f +#define PLAY_HEIGHT 29.0f +#define PLAY_PADDING 5.0f typedef struct _PlayButtonPrivate PlayButtonPrivate; struct _PlayButtonPrivate { - GdkColor background_colour_fg; - GdkColor background_colour_bg_dark; - GdkColor background_colour_bg_light; - GdkColor foreground_colour_fg; - GdkColor foreground_colour_bg; + GdkColor background_colour_fg; + GdkColor background_colour_bg_dark; + GdkColor background_colour_bg_light; + GdkColor foreground_colour_fg; + GdkColor foreground_colour_bg; + PlayButtonEvent current_command; + PlayButtonState current_state; + GHashTable* command_coordinates; }; #define PLAY_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PLAY_BUTTON_TYPE, PlayButtonPrivate)) @@ -86,7 +85,7 @@ G_DEFINE_TYPE (PlayButton, play_button, GTK_TYPE_DRAWING_AREA); /// internal helper functions ////////////////////////////////////////////////// -static double +/*static double _align (double val) { double fract = val - (int) val; @@ -95,7 +94,7 @@ _align (double val) return (double) ((int) val + 0.5f); else return val; -} +}*/ static inline void _blurinner (guchar* pixel, @@ -308,8 +307,7 @@ _surface_blur (cairo_surface_t* surface, static void play_button_class_init (PlayButtonClass *klass) -{ - +{ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass); @@ -324,6 +322,43 @@ play_button_class_init (PlayButtonClass *klass) static void play_button_init (PlayButton *self) { + PlayButtonPrivate* priv = PLAY_BUTTON_GET_PRIVATE(self); + priv->current_command = TRANSPORT_NADA; + priv->current_state = PAUSE; + priv->command_coordinates = g_hash_table_new_full(g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify)g_list_free); + GList* previous_list = NULL; + previous_list = g_list_insert(previous_list, GINT_TO_POINTER(15), 0); + previous_list = g_list_insert(previous_list, GINT_TO_POINTER(10), 1); + previous_list = g_list_insert(previous_list, GINT_TO_POINTER(60), 2); + previous_list = g_list_insert(previous_list, GINT_TO_POINTER(34), 3); + + g_hash_table_insert(priv->command_coordinates, + GINT_TO_POINTER(TRANSPORT_PREVIOUS), + previous_list); + + GList* play_list = NULL; + play_list = g_list_insert(play_list, GINT_TO_POINTER(60), 0); + play_list = g_list_insert(play_list, GINT_TO_POINTER(10), 1); + play_list = g_list_insert(play_list, GINT_TO_POINTER(45), 2); + play_list = g_list_insert(play_list, GINT_TO_POINTER(40), 3); + + g_hash_table_insert(priv->command_coordinates, + GINT_TO_POINTER(TRANSPORT_PLAY_PAUSE), + play_list); + + GList* next_list = NULL; + next_list = g_list_insert(next_list, GINT_TO_POINTER(100), 0); + next_list = g_list_insert(next_list, GINT_TO_POINTER(10), 1); + next_list = g_list_insert(next_list, GINT_TO_POINTER(60), 2); + next_list = g_list_insert(next_list, GINT_TO_POINTER(34), 3); + + g_hash_table_insert(priv->command_coordinates, + GINT_TO_POINTER(TRANSPORT_NEXT), + next_list); + gtk_widget_set_size_request(GTK_WIDGET(self), 200, 80); } @@ -356,29 +391,84 @@ play_button_expose (GtkWidget *button, GdkEventExpose *event) } -gint +PlayButtonEvent determine_button_event(GtkWidget* button, GdkEventButton* event) { g_debug("event x coordinate = %f", event->x); g_debug("event y coordinate = %f", event->y); - gint result = 0; + PlayButtonEvent button_event = TRANSPORT_NADA; // For now very simple rectangular collision detection if(event->x > 55 && event->x < 95 && event->y > 22 && event->y < 46){ - result = PREVIOUS; + button_event = TRANSPORT_PREVIOUS; } else if(event->x > 101 && event->x < 133 && event->y > 20 && event->y < 47){ - result = PLAY_PAUSE; + button_event = TRANSPORT_PLAY_PAUSE; } else if(event->x > 137 && event->x < 179 && event->y > 22 && event->y < 46){ - result = NEXT; - } + button_event = TRANSPORT_NEXT; + } + return button_event; +} + +void +play_button_react_to_button_press(GtkWidget* button, PlayButtonEvent command) +{ + g_return_if_fail(IS_PLAY_BUTTON(button)); + PlayButtonPrivate* priv = PLAY_BUTTON_GET_PRIVATE(button); + priv->current_command = command; + + cairo_t *cr; + cr = gdk_cairo_create (button->window); + + GList* list = g_hash_table_lookup(priv->command_coordinates, GINT_TO_POINTER(command)); + cairo_rectangle(cr, + GPOINTER_TO_INT(g_list_nth_data(list, 0)), + GPOINTER_TO_INT(g_list_nth_data(list, 1)), + GPOINTER_TO_INT(g_list_nth_data(list, 2)), + GPOINTER_TO_INT(g_list_nth_data(list, 3))); + cairo_clip(cr); + draw (button, cr); + cairo_destroy (cr); +} + + +void +play_button_react_to_button_release(GtkWidget* button) +{ + g_return_if_fail(IS_PLAY_BUTTON(button)); + PlayButtonPrivate* priv = PLAY_BUTTON_GET_PRIVATE(button); + cairo_t *cr; + + cr = gdk_cairo_create (button->window); + GList* list = g_hash_table_lookup(priv->command_coordinates, + GINT_TO_POINTER(priv->current_command)); + + priv->current_command = TRANSPORT_NADA; + + cairo_rectangle(cr, + GPOINTER_TO_INT(g_list_nth_data(list, 0)), + GPOINTER_TO_INT(g_list_nth_data(list, 1)), + GPOINTER_TO_INT(g_list_nth_data(list, 2)), + GPOINTER_TO_INT(g_list_nth_data(list, 3))); + + cairo_clip(cr); + draw (button, cr); + cairo_destroy (cr); - return result; +} + +void +play_button_toggle_play_pause(GtkWidget* button, PlayButtonState update) +{ + PlayButtonPrivate* priv = PLAY_BUTTON_GET_PRIVATE(button); + priv->current_state = update; + g_debug("PlayButton::toggle play state : %i", priv->current_state); } + void play_button_set_style(GtkWidget* button, GtkStyle* style) { @@ -561,6 +651,24 @@ _mask_pause (cairo_t* cr, } static void +_mask_play (cairo_t* cr, + double x, + double y, + double tri_width, + double tri_height + /*double tri_offset*/) +{ + if (!cr) + return; + + cairo_move_to (cr, x, y); + cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f); + cairo_line_to (cr, x, y + tri_height); + cairo_close_path (cr); + +} + +static void _fill (cairo_t* cr, double x_start, double y_start, @@ -615,6 +723,9 @@ _finalize (cairo_t* cr, static void draw (GtkWidget* button, cairo_t *cr) { + g_return_if_fail(IS_PLAY_BUTTON(button)); + PlayButtonPrivate* priv = PLAY_BUTTON_GET_PRIVATE(button); + cairo_surface_t* surf = NULL; cairo_t* cr_surf = NULL; @@ -627,7 +738,8 @@ draw (GtkWidget* button, cairo_t *cr) double BUTTON_START[] = {252.0f / 255.0f, 251.0f / 255.0f, 251.0f / 255.0f,1.0f}; double BUTTON_END[] = {186.0f / 255.0f,180.0f / 255.0f, 170.0f / 255.0f, 1.0f}; double BUTTON_SHADOW[] = {0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 0.75f}; - + double INNER_COMPRESSED_END[] = {61.0f / 255.0f, 60.0f / 255.0f, 57.0f / 255.0f, 1.0f}; + double INNER_COMPRESSED_START[] = {36.0f / 255.0f, 35.0f / 255.0f, 33.0f / 255.0f, 1.0f}; // prev/next-background draw_gradient (cr, @@ -644,13 +756,32 @@ draw (GtkWidget* button, cairo_t *cr) MIDDLE_RADIUS, MIDDLE_START, MIDDLE_END); - draw_gradient (cr, - X, - Y + 2, - RECT_WIDTH - 4, - INNER_RADIUS, - INNER_START, - INNER_END); + draw_gradient (cr, + X, + Y + 2, + RECT_WIDTH - 4, + INNER_RADIUS, + INNER_START, + INNER_END); + + if(priv->current_command == TRANSPORT_PREVIOUS){ + draw_gradient (cr, + X, + Y + 2, + RECT_WIDTH/2, + INNER_RADIUS, + INNER_COMPRESSED_START, + INNER_COMPRESSED_END); + } + else if(priv->current_command == TRANSPORT_NEXT){ + draw_gradient (cr, + RECT_WIDTH / 2 + X, + Y + 2, + (RECT_WIDTH - 7)/2, + INNER_RADIUS, + INNER_COMPRESSED_START, + INNER_COMPRESSED_END); + } // play/pause-background draw_circle (cr, @@ -670,7 +801,16 @@ draw (GtkWidget* button, cairo_t *cr) Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 2.0f, CIRCLE_RADIUS - 2.0f, INNER_START, - INNER_END); + INNER_END); + if(priv->current_command == TRANSPORT_PLAY_PAUSE){ + draw_circle (cr, + X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 4.5f + 2.0f, + Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 2.0f, + CIRCLE_RADIUS - 2.0f, + INNER_COMPRESSED_START, + INNER_COMPRESSED_END); + } + // draw previous-button drop-shadow _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT); @@ -700,13 +840,13 @@ draw (GtkWidget* button, cairo_t *cr) TRI_HEIGHT, TRI_OFFSET); _fill (cr_surf, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (double) TRI_HEIGHT, - BUTTON_START, - BUTTON_END, - FALSE); + (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, + (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, + (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, + (double) TRI_HEIGHT, + BUTTON_START, + BUTTON_END, + FALSE); _finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y); // draw next-button drop-shadow @@ -747,41 +887,81 @@ draw (GtkWidget* button, cairo_t *cr) _finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y); // draw pause-button drop-shadow - _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); - _mask_pause (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - BAR_WIDTH, - BAR_HEIGHT - 2.0f * BAR_WIDTH, - BAR_OFFSET); - _fill (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (double) BAR_HEIGHT, - BUTTON_SHADOW, - BUTTON_SHADOW, - TRUE); - _surface_blur (surf, 1); - _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y + 1.0f); - - // draw pause-button - _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); - _mask_pause (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - BAR_WIDTH, - BAR_HEIGHT - 2.0f * BAR_WIDTH, - BAR_OFFSET); - _fill (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (double) BAR_HEIGHT, - BUTTON_START, - BUTTON_END, - TRUE); - _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y); + if(priv->current_state == PLAY){ + _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); + _mask_pause (cr_surf, + (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, + (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, + BAR_WIDTH, + BAR_HEIGHT - 2.0f * BAR_WIDTH, + BAR_OFFSET); + _fill (cr_surf, + (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, + (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, + (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, + (double) BAR_HEIGHT, + BUTTON_SHADOW, + BUTTON_SHADOW, + TRUE); + _surface_blur (surf, 1); + _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y + 1.0f); + + // draw pause-button + _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); + _mask_pause (cr_surf, + (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, + (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, + BAR_WIDTH, + BAR_HEIGHT - 2.0f * BAR_WIDTH, + BAR_OFFSET); + _fill (cr_surf, + (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, + (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, + (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, + (double) BAR_HEIGHT, + BUTTON_START, + BUTTON_END, + TRUE); + _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y); + } + else if(priv->current_state == PAUSE){ + _setup (&cr_surf, &surf, PLAY_WIDTH, PLAY_HEIGHT); + _mask_play (cr_surf, + PLAY_PADDING, + PLAY_PADDING, + PLAY_WIDTH - (2*PLAY_PADDING), + PLAY_HEIGHT - (2*PLAY_PADDING)); + _fill (cr_surf, + PLAY_PADDING, + PLAY_PADDING, + PLAY_WIDTH - (2*PLAY_PADDING), + PLAY_HEIGHT - (2*PLAY_PADDING), + BUTTON_SHADOW, + BUTTON_SHADOW, + FALSE); + _surface_blur (surf, 1); + _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y + 1.0f); + // draw play-button + _setup (&cr_surf, &surf, PLAY_WIDTH, PLAY_HEIGHT); + cairo_set_line_width (cr, 10.5); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); + _mask_play (cr_surf, + PLAY_PADDING, + PLAY_PADDING, + PLAY_WIDTH - (2*PLAY_PADDING), + PLAY_HEIGHT - (2*PLAY_PADDING)); + _fill (cr_surf, + PLAY_PADDING, + PLAY_PADDING, + PLAY_WIDTH - (2*PLAY_PADDING), + PLAY_HEIGHT - (2*PLAY_PADDING), + BUTTON_START, + BUTTON_END, + FALSE); + _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y); + } + } @@ -791,8 +971,7 @@ draw (GtkWidget* button, cairo_t *cr) **/ GtkWidget* play_button_new() -{ - +{ GtkWidget* widget = g_object_new(PLAY_BUTTON_TYPE, NULL); gtk_widget_set_app_paintable (widget, TRUE); return widget; diff --git a/src/play-button.h b/src/play-button.h index 3eaabcc..727a489 100644 --- a/src/play-button.h +++ b/src/play-button.h @@ -33,6 +33,18 @@ G_BEGIN_DECLS typedef struct _PlayButton PlayButton; typedef struct _PlayButtonClass PlayButtonClass; +typedef enum { + TRANSPORT_PREVIOUS, + TRANSPORT_PLAY_PAUSE, + TRANSPORT_NEXT, + TRANSPORT_NADA +}PlayButtonEvent; + +typedef enum { + PLAY, + PAUSE +}PlayButtonState; + struct _PlayButtonClass { GtkDrawingAreaClass parent_class; }; @@ -43,7 +55,10 @@ struct _PlayButton { GType play_button_get_type (void); void play_button_set_style(GtkWidget* button, GtkStyle* style); -gint determine_button_event(GtkWidget* button, GdkEventButton* event); +PlayButtonEvent determine_button_event(GtkWidget* button, GdkEventButton* event); +void play_button_react_to_button_press(GtkWidget* button, PlayButtonEvent command); +void play_button_react_to_button_release(GtkWidget* button); +void play_button_toggle_play_pause(GtkWidget* button, PlayButtonState update); GtkWidget* play_button_new(); diff --git a/src/player-controller.c b/src/player-controller.c index ca1485e..acb2da2 100644 --- a/src/player-controller.c +++ b/src/player-controller.c @@ -64,11 +64,23 @@ typedef struct _PlayerItemClass PlayerItemClass; typedef struct _MprisController MprisController; typedef struct _MprisControllerClass MprisControllerClass; +#define PLAYER_CONTROLLER_TYPE_WIDGET_ORDER (player_controller_widget_order_get_type ()) + #define PLAYER_CONTROLLER_TYPE_STATE (player_controller_state_get_type ()) #define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) #define _g_free0(var) (var = (g_free (var), NULL)) #define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) +#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; + #define TYPE_TITLE_MENUITEM (title_menuitem_get_type ()) #define TITLE_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TITLE_MENUITEM, TitleMenuitem)) #define TITLE_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TITLE_MENUITEM, TitleMenuitemClass)) @@ -79,15 +91,15 @@ typedef struct _MprisControllerClass MprisControllerClass; typedef struct _TitleMenuitem TitleMenuitem; typedef struct _TitleMenuitemClass TitleMenuitemClass; -#define TYPE_METADATA_MENUITEM (metadata_menuitem_get_type ()) -#define METADATA_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_METADATA_MENUITEM, MetadataMenuitem)) -#define METADATA_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_METADATA_MENUITEM, MetadataMenuitemClass)) -#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)) +#define TYPE_SCRUB_MENUITEM (scrub_menuitem_get_type ()) +#define SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitem)) +#define SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) +#define IS_SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCRUB_MENUITEM)) +#define IS_SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCRUB_MENUITEM)) +#define SCRUB_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) -typedef struct _MetadataMenuitem MetadataMenuitem; -typedef struct _MetadataMenuitemClass MetadataMenuitemClass; +typedef struct _ScrubMenuitem ScrubMenuitem; +typedef struct _ScrubMenuitemClass ScrubMenuitemClass; #define TYPE_TRANSPORT_MENUITEM (transport_menuitem_get_type ()) #define TRANSPORT_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TRANSPORT_MENUITEM, TransportMenuitem)) @@ -119,6 +131,14 @@ struct _PlayerControllerPrivate { }; typedef enum { + PLAYER_CONTROLLER_WIDGET_ORDER_SEPARATOR, + PLAYER_CONTROLLER_WIDGET_ORDER_TITLE, + PLAYER_CONTROLLER_WIDGET_ORDER_METADATA, + PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB, + PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT +} PlayerControllerwidget_order; + +typedef enum { PLAYER_CONTROLLER_STATE_OFFLINE, PLAYER_CONTROLLER_STATE_INSTANTIATING, PLAYER_CONTROLLER_STATE_READY, @@ -139,16 +159,16 @@ enum { PLAYER_CONTROLLER_APP_INFO, PLAYER_CONTROLLER_MENU_OFFSET }; +GType player_controller_widget_order_get_type (void); GType player_controller_state_get_type (void); -#define PLAYER_CONTROLLER_METADATA 2 -#define PLAYER_CONTROLLER_TRANSPORT 3 +#define PLAYER_CONTROLLER_WIDGET_QUANTITY 5 static char* player_controller_format_client_name (const char* client_name); void player_controller_set_name (PlayerController* self, const char* value); void player_controller_update_state (PlayerController* self, PlayerControllerstate new_state); void player_controller_set_menu_offset (PlayerController* self, gint value); static void player_controller_construct_widgets (PlayerController* self); static void player_controller_establish_mpris_connection (PlayerController* self); -static void player_controller_update_layout (PlayerController* self); +void player_controller_update_layout (PlayerController* self); PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* client_name, gint offset, PlayerControllerstate initial_state); PlayerController* player_controller_construct (GType object_type, DbusmenuMenuitem* root, const char* client_name, gint offset, PlayerControllerstate initial_state); const char* player_controller_get_name (PlayerController* self); @@ -159,6 +179,7 @@ MprisController* mpris_controller_new (PlayerController* ctrl, const char* inter MprisController* mpris_controller_construct (GType object_type, PlayerController* ctrl, const char* inter); gboolean mpris_controller_connected (MprisController* self); void player_controller_vanish (PlayerController* self); +GType metadata_menuitem_get_type (void); PlayerItem* player_item_new (const char* type); PlayerItem* player_item_construct (GType object_type, const char* type); TitleMenuitem* title_menuitem_new (PlayerController* parent); @@ -166,7 +187,9 @@ TitleMenuitem* title_menuitem_construct (GType object_type, PlayerController* pa GType title_menuitem_get_type (void); MetadataMenuitem* metadata_menuitem_new (void); MetadataMenuitem* metadata_menuitem_construct (GType object_type); -GType metadata_menuitem_get_type (void); +ScrubMenuitem* scrub_menuitem_new (PlayerController* parent); +ScrubMenuitem* scrub_menuitem_construct (GType object_type, PlayerController* parent); +GType scrub_menuitem_get_type (void); TransportMenuitem* transport_menuitem_new (PlayerController* parent); TransportMenuitem* transport_menuitem_construct (GType object_type, PlayerController* parent); GType transport_menuitem_get_type (void); @@ -179,6 +202,18 @@ static int _vala_strcmp0 (const char * str1, const char * str2); +GType player_controller_widget_order_get_type (void) { + static volatile gsize player_controller_widget_order_type_id__volatile = 0; + if (g_once_init_enter (&player_controller_widget_order_type_id__volatile)) { + static const GEnumValue values[] = {{PLAYER_CONTROLLER_WIDGET_ORDER_SEPARATOR, "PLAYER_CONTROLLER_WIDGET_ORDER_SEPARATOR", "separator"}, {PLAYER_CONTROLLER_WIDGET_ORDER_TITLE, "PLAYER_CONTROLLER_WIDGET_ORDER_TITLE", "title"}, {PLAYER_CONTROLLER_WIDGET_ORDER_METADATA, "PLAYER_CONTROLLER_WIDGET_ORDER_METADATA", "metadata"}, {PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB, "PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB", "scrub"}, {PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT, "PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT", "transport"}, {0, NULL, NULL}}; + GType player_controller_widget_order_type_id; + player_controller_widget_order_type_id = g_enum_register_static ("PlayerControllerwidget_order", values); + g_once_init_leave (&player_controller_widget_order_type_id__volatile, player_controller_widget_order_type_id); + } + return player_controller_widget_order_type_id__volatile; +} + + GType player_controller_state_get_type (void) { static volatile gsize player_controller_state_type_id__volatile = 0; if (g_once_init_enter (&player_controller_state_type_id__volatile)) { @@ -223,7 +258,6 @@ PlayerController* player_controller_construct (GType object_type, DbusmenuMenuit self->custom_items = (_tmp3_ = gee_array_list_new (TYPE_PLAYER_ITEM, (GBoxedCopyFunc) g_object_ref, g_object_unref, NULL), _g_object_unref0 (self->custom_items), _tmp3_); player_controller_update_state (self, initial_state); player_controller_set_menu_offset (self, offset); - g_debug ("player-controller.vala:54: offset = %i", offset); player_controller_construct_widgets (self); player_controller_establish_mpris_connection (self); player_controller_update_layout (self); @@ -238,7 +272,7 @@ PlayerController* player_controller_new (DbusmenuMenuitem* root, const char* cli void player_controller_update_state (PlayerController* self, PlayerControllerstate new_state) { g_return_if_fail (self != NULL); - g_debug ("player-controller.vala:62: update_state - player controller %s : new s" \ + g_debug ("player-controller.vala:68: update_state - player controller %s : new s" \ "tate %i", self->priv->_name, (gint) new_state); self->current_state = (gint) new_state; } @@ -248,7 +282,7 @@ void player_controller_activate (PlayerController* self) { PlayerItem* _tmp0_; g_return_if_fail (self != NULL); player_controller_establish_mpris_connection (self); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, PLAYER_CONTROLLER_METADATA)), DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA)), DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); _g_object_unref0 (_tmp0_); } @@ -257,7 +291,7 @@ void player_controller_instantiate (PlayerController* self) { GError * _inner_error_; g_return_if_fail (self != NULL); _inner_error_ = NULL; - g_debug ("player-controller.vala:80: instantiate in player controller for %s", self->priv->_name); + g_debug ("player-controller.vala:87: instantiate in player controller for %s", self->priv->_name); { g_app_info_launch (self->priv->_app_info, NULL, NULL, &_inner_error_); if (_inner_error_ != NULL) { @@ -272,7 +306,7 @@ void player_controller_instantiate (PlayerController* self) { _error_ = _inner_error_; _inner_error_ = NULL; { - g_warning ("player-controller.vala:86: Failed to launch app %s with error message:" \ + g_warning ("player-controller.vala:93: Failed to launch app %s with error message:" \ " %s", self->priv->_name, _error_->message); _g_error_free0 (_error_); } @@ -289,20 +323,20 @@ void player_controller_instantiate (PlayerController* self) { static void player_controller_establish_mpris_connection (PlayerController* self) { g_return_if_fail (self != NULL); if (self->current_state != PLAYER_CONTROLLER_STATE_READY) { - g_debug ("player-controller.vala:93: establish_mpris_connection - Not ready to c" \ -"onnect"); + g_debug ("player-controller.vala:100: establish_mpris_connection - Not ready to " \ +"connect"); return; } if (_vala_strcmp0 (self->priv->_name, "Vlc") == 0) { MprisController* _tmp0_; - g_debug ("player-controller.vala:98: establishing a vlc mpris controller"); + g_debug ("player-controller.vala:105: establishing a vlc mpris controller"); self->mpris_adaptor = (_tmp0_ = mpris_controller_new (self, "org.mpris.MediaPlayer.Player"), _g_object_unref0 (self->mpris_adaptor), _tmp0_); } else { MprisController* _tmp1_; self->mpris_adaptor = (_tmp1_ = mpris_controller_new (self, "org.freedesktop.MediaPlayer"), _g_object_unref0 (self->mpris_adaptor), _tmp1_); } if (mpris_controller_connected (self->mpris_adaptor) == TRUE) { - g_debug ("player-controller.vala:106: yup I'm connected"); + g_debug ("player-controller.vala:113: yup I'm connected"); player_controller_update_state (self, PLAYER_CONTROLLER_STATE_CONNECTED); } else { player_controller_update_state (self, PLAYER_CONTROLLER_STATE_DISCONNECTED); @@ -342,26 +376,34 @@ static char* bool_to_string (gboolean self) { } -static void player_controller_update_layout (PlayerController* self) { +void player_controller_update_layout (PlayerController* self) { gboolean visibility; - char* _tmp0_; - PlayerItem* _tmp1_; + PlayerItem* _tmp0_; + MetadataMenuitem* meta_item; + char* _tmp1_; PlayerItem* _tmp2_; + PlayerItem* _tmp3_; + PlayerItem* _tmp4_; g_return_if_fail (self != NULL); visibility = TRUE; + meta_item = (_tmp0_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA), IS_METADATA_MENUITEM (_tmp0_) ? ((MetadataMenuitem*) _tmp0_) : NULL); if (self->current_state != PLAYER_CONTROLLER_STATE_CONNECTED) { visibility = FALSE; } - g_debug ("player-controller.vala:128: about the set the visibility on both the t" \ -"ransport and metadata widget to %s", _tmp0_ = bool_to_string (visibility)); - _g_free0 (_tmp0_); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) (_tmp1_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, PLAYER_CONTROLLER_TRANSPORT)), DBUSMENU_MENUITEM_PROP_VISIBLE, visibility); - _g_object_unref0 (_tmp1_); - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) (_tmp2_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, PLAYER_CONTROLLER_METADATA)), DBUSMENU_MENUITEM_PROP_VISIBLE, visibility); + g_debug ("player-controller.vala:137: about the set the visibility on both the t" \ +"ransport and metadata widget to %s", _tmp1_ = bool_to_string (visibility)); + _g_free0 (_tmp1_); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) (_tmp2_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_TRANSPORT)), DBUSMENU_MENUITEM_PROP_VISIBLE, visibility); _g_object_unref0 (_tmp2_); - if (self->mpris_adaptor == NULL) { - g_warning ("player-controller.vala:133: Why is the mpris object null"); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) (_tmp3_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_SCRUB)), DBUSMENU_MENUITEM_PROP_VISIBLE, visibility); + _g_object_unref0 (_tmp3_); + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) (_tmp4_ = (PlayerItem*) gee_abstract_list_get ((GeeAbstractList*) self->custom_items, (gint) PLAYER_CONTROLLER_WIDGET_ORDER_METADATA)), DBUSMENU_MENUITEM_PROP_VISIBLE, visibility); + _g_object_unref0 (_tmp4_); + if (visibility == FALSE) { + g_warning ("player-controller.vala:143: Update layout of client %s is setting widg" \ +"ets to invisibile!", self->priv->_name); } + _g_object_unref0 (meta_item); } @@ -369,6 +411,7 @@ static void player_controller_construct_widgets (PlayerController* self) { PlayerItem* _tmp0_; TitleMenuitem* title_menu_item; MetadataMenuitem* metadata_item; + ScrubMenuitem* scrub_item; TransportMenuitem* transport_item; g_return_if_fail (self != NULL); gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, _tmp0_ = player_item_new (DBUSMENU_CLIENT_TYPES_SEPARATOR)); @@ -377,6 +420,8 @@ static void player_controller_construct_widgets (PlayerController* self) { gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, (PlayerItem*) title_menu_item); metadata_item = metadata_menuitem_new (); gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, (PlayerItem*) metadata_item); + scrub_item = scrub_menuitem_new (self); + gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, (PlayerItem*) scrub_item); transport_item = transport_menuitem_new (self); gee_abstract_collection_add ((GeeAbstractCollection*) self->custom_items, (PlayerItem*) transport_item); { @@ -395,6 +440,7 @@ static void player_controller_construct_widgets (PlayerController* self) { } _g_object_unref0 (title_menu_item); _g_object_unref0 (metadata_item); + _g_object_unref0 (scrub_item); _g_object_unref0 (transport_item); } @@ -444,7 +490,7 @@ static char* player_controller_format_client_name (const char* client_name) { formatted = (_tmp2_ = g_strconcat (_tmp0_ = g_utf8_strup (client_name, (gssize) 1), _tmp1_ = string_slice (client_name, (glong) 1, g_utf8_strlen (client_name, -1)), NULL), _g_free0 (formatted), _tmp2_); _g_free0 (_tmp1_); _g_free0 (_tmp0_); - g_debug ("player-controller.vala:165: PlayerController->format_client_name - : %" \ + g_debug ("player-controller.vala:179: PlayerController->format_client_name - : %" \ "s", formatted); } result = formatted; diff --git a/src/player-controller.vala b/src/player-controller.vala index d272d14..f824d6f 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -23,8 +23,15 @@ using Gee; public class PlayerController : GLib.Object { - public const int METADATA = 2; - private const int TRANSPORT = 3; + public const int WIDGET_QUANTITY = 5; + + public static enum widget_order{ + SEPARATOR, + TITLE, + METADATA, + SCRUB, + TRANSPORT + } public enum state{ OFFLINE, @@ -51,22 +58,22 @@ public class PlayerController : GLib.Object this.custom_items = new ArrayList<PlayerItem>(); this.update_state(initial_state); this.menu_offset = offset; - debug("offset = %i", offset); construct_widgets(); establish_mpris_connection(); - update_layout(); + this.update_layout(); } public void update_state(state new_state) { debug("update_state - player controller %s : new state %i", this.name, new_state); this.current_state = new_state; + //this.update_layout(); } public void activate() { this.establish_mpris_connection(); - this.custom_items[METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, true); + this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, true); } /* @@ -119,22 +126,24 @@ public class PlayerController : GLib.Object } } - private void update_layout() + public void update_layout() { bool visibility = true; - if(this.current_state != state.CONNECTED){ + MetadataMenuitem meta_item = this.custom_items[widget_order.METADATA] as MetadataMenuitem; + if(this.current_state != state.CONNECTED /*|| + meta_item.not_populated()*/){ visibility = false; } debug("about the set the visibility on both the transport and metadata widget to %s", visibility.to_string()); - this.custom_items[TRANSPORT].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); - this.custom_items[METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); + this.custom_items[widget_order.TRANSPORT].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); + this.custom_items[widget_order.SCRUB].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); + this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); // DEBUG - if(this.mpris_adaptor == null){ - warning("Why is the mpris object null"); + if(visibility == false){ + warning("Update layout of client %s is setting widgets to invisibile!", this.name); } } - - + private void construct_widgets() { // Separator item @@ -147,11 +156,16 @@ public class PlayerController : GLib.Object // Metadata item MetadataMenuitem metadata_item = new MetadataMenuitem(); this.custom_items.add(metadata_item); - + + // Scrub item + ScrubMenuitem scrub_item = new ScrubMenuitem(this); + this.custom_items.add(scrub_item); + // Transport item TransportMenuitem transport_item = new TransportMenuitem(this); this.custom_items.add(transport_item); + foreach(PlayerItem item in this.custom_items){ root_menu.child_add_position(item, this.menu_offset + this.custom_items.index_of(item)); } diff --git a/src/player-item.c b/src/player-item.c index 2ef44a8..7546ca2 100644 --- a/src/player-item.c +++ b/src/player-item.c @@ -127,6 +127,7 @@ void player_item_reset (PlayerItem* self, GeeHashSet* attrs) { s = (char*) gee_iterator_get (_s_it); g_debug ("player-item.vala:39: attempting to set prop %s to null", s); dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, s, NULL); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, s, 0); _g_free0 (s); } _g_object_unref0 (_s_it); @@ -170,9 +171,9 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu g_return_if_fail (data != NULL); g_return_if_fail (attributes != NULL); _inner_error_ = NULL; - g_debug ("player-item.vala:46: PlayerItem::update()"); + g_debug ("player-item.vala:47: PlayerItem::update()"); if (player_item_ensure_valid_updates (data, attributes) == FALSE) { - g_debug ("player-item.vala:48: PlayerItem::Update -> The hashtable update does n" \ + g_debug ("player-item.vala:49: PlayerItem::Update -> The hashtable update does n" \ "ot contain what we were expecting - just leave it!"); return; } @@ -196,12 +197,12 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu property = (char*) gee_iterator_get (_property_it); input_keys = (_tmp1_ = _tmp0_ = g_strsplit (property, "-", 0), input_keys_length1 = _vala_array_length (_tmp0_), _input_keys_size_ = input_keys_length1, _tmp1_); search_key = g_strdup ((_tmp3_ = input_keys + (input_keys_length1 - 1), _tmp2_ = input_keys_length1 - (input_keys_length1 - 1), _tmp3_)[0]); - g_debug ("player-item.vala:54: search key = %s", search_key); + g_debug ("player-item.vala:56: search key = %s", search_key); v = __g_value_dup0 ((GValue*) g_hash_table_lookup (data, search_key)); if (G_VALUE_HOLDS (v, G_TYPE_STRING)) { char* update; update = string_strip (g_value_get_string (v)); - g_debug ("player-item.vala:59: with value : %s", update); + g_debug ("player-item.vala:61: with value : %s", update); if (string_contains (property, "arturl")) { { char* _tmp4_; @@ -232,7 +233,7 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu e = _inner_error_; _inner_error_ = NULL; { - g_warning ("player-item.vala:65: Problem converting URI %s to file path", update); + g_warning ("player-item.vala:68: Problem converting URI %s to file path", update); _g_error_free0 (e); } } @@ -253,11 +254,16 @@ void player_item_update (PlayerItem* self, GHashTable* data, GeeHashSet* attribu _g_free0 (update); } else { if (G_VALUE_HOLDS (v, G_TYPE_INT)) { - g_debug ("player-item.vala:71: with value : %i", g_value_get_int (v)); + g_debug ("player-item.vala:74: with value : %i", g_value_get_int (v)); dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, property, g_value_get_int (v)); } else { - if (G_VALUE_HOLDS (v, G_TYPE_BOOLEAN)) { - dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, property, g_value_get_boolean (v)); + if (G_VALUE_HOLDS (v, G_TYPE_UINT)) { + g_debug ("player-item.vala:78: with value : %i", (gint) g_value_get_uint (v)); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, property, (gint) g_value_get_uint (v)); + } else { + if (G_VALUE_HOLDS (v, G_TYPE_BOOLEAN)) { + dbusmenu_menuitem_property_set_bool ((DbusmenuMenuitem*) self, property, g_value_get_boolean (v)); + } } } } @@ -279,11 +285,6 @@ static gboolean player_item_ensure_valid_updates (GHashTable* data, GeeHashSet* result = FALSE; return result; } - if (g_hash_table_size (data) < gee_collection_get_size ((GeeCollection*) attributes)) { - g_warning ("player-item.vala:86: update hash was too small for the target"); - result = FALSE; - return result; - } result = TRUE; return result; } diff --git a/src/player-item.vala b/src/player-item.vala index 3e10b7b..2952f71 100644 --- a/src/player-item.vala +++ b/src/player-item.vala @@ -38,6 +38,7 @@ public class PlayerItem : Dbusmenu.Menuitem foreach(string s in attrs){ debug("attempting to set prop %s to null", s); this.property_set(s, null); + this.property_set_int(s, 0); } } @@ -47,7 +48,8 @@ public class PlayerItem : Dbusmenu.Menuitem if(ensure_valid_updates(data, attributes) == false){ debug("PlayerItem::Update -> The hashtable update does not contain what we were expecting - just leave it!"); return; - } + } + foreach(string property in attributes){ string[] input_keys = property.split("-"); string search_key = input_keys[input_keys.length-1 : input_keys.length][0]; @@ -57,6 +59,7 @@ public class PlayerItem : Dbusmenu.Menuitem if (v.holds (typeof (string))){ string update = v.get_string().strip(); debug("with value : %s", update); + // Special case for the arturl URI's. if(property.contains("arturl")){ try{ update = Filename.from_uri(update.strip()); @@ -71,6 +74,10 @@ public class PlayerItem : Dbusmenu.Menuitem debug("with value : %i", v.get_int()); this.property_set_int(property, v.get_int()); } + else if (v.holds (typeof (uint))){ + debug("with value : %i", (int)v.get_uint()); + this.property_set_int(property, (int)v.get_uint()); + } else if(v.holds (typeof (bool))){ this.property_set_bool(property, v.get_boolean()); } @@ -82,10 +89,10 @@ public class PlayerItem : Dbusmenu.Menuitem if(data == null){ return false; } - if(data.size() < attributes.size){ + /*if(data.size() < attributes.size){ warning("update hash was too small for the target"); return false; - } + }*/ return true; } diff --git a/src/scrub-menu-item.c b/src/scrub-menu-item.c new file mode 100644 index 0000000..24b10e3 --- /dev/null +++ b/src/scrub-menu-item.c @@ -0,0 +1,195 @@ +/* scrub-menu-item.c generated by valac, the Vala compiler + * generated from scrub-menu-item.vala, do not modify */ + +/* +Copyright 2010 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> +#include <glib-object.h> +#include <libdbusmenu-glib/client.h> +#include <libdbusmenu-glib/menuitem-proxy.h> +#include <libdbusmenu-glib/menuitem.h> +#include <libdbusmenu-glib/server.h> +#include <common-defs.h> +#include <stdlib.h> +#include <string.h> +#include <gee.h> +#include <float.h> +#include <math.h> + + +#define TYPE_PLAYER_ITEM (player_item_get_type ()) +#define PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER_ITEM, PlayerItem)) +#define PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER_ITEM, PlayerItemClass)) +#define IS_PLAYER_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER_ITEM)) +#define IS_PLAYER_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER_ITEM)) +#define PLAYER_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER_ITEM, PlayerItemClass)) + +typedef struct _PlayerItem PlayerItem; +typedef struct _PlayerItemClass PlayerItemClass; +typedef struct _PlayerItemPrivate PlayerItemPrivate; + +#define TYPE_SCRUB_MENUITEM (scrub_menuitem_get_type ()) +#define SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitem)) +#define SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) +#define IS_SCRUB_MENUITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCRUB_MENUITEM)) +#define IS_SCRUB_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCRUB_MENUITEM)) +#define SCRUB_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCRUB_MENUITEM, ScrubMenuitemClass)) + +typedef struct _ScrubMenuitem ScrubMenuitem; +typedef struct _ScrubMenuitemClass ScrubMenuitemClass; +typedef struct _ScrubMenuitemPrivate ScrubMenuitemPrivate; + +#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))) + +struct _PlayerItem { + DbusmenuMenuitem parent_instance; + PlayerItemPrivate * priv; +}; + +struct _PlayerItemClass { + DbusmenuMenuitemClass parent_class; +}; + +struct _ScrubMenuitem { + PlayerItem parent_instance; + ScrubMenuitemPrivate * priv; +}; + +struct _ScrubMenuitemClass { + PlayerItemClass parent_class; +}; + +struct _PlayerController { + GObject parent_instance; + PlayerControllerPrivate * priv; + gint current_state; + GeeArrayList* custom_items; + MprisController* mpris_adaptor; +}; + +struct _PlayerControllerClass { + GObjectClass parent_class; +}; + + +static gpointer scrub_menuitem_parent_class = NULL; + +GType player_item_get_type (void); +GType scrub_menuitem_get_type (void); +enum { + SCRUB_MENUITEM_DUMMY_PROPERTY +}; +GType player_controller_get_type (void); +ScrubMenuitem* scrub_menuitem_new (PlayerController* parent); +ScrubMenuitem* scrub_menuitem_construct (GType object_type, PlayerController* parent); +PlayerController* player_item_get_owner (PlayerItem* self); +const char* player_controller_get_name (PlayerController* self); +GType mpris_controller_get_type (void); +void mpris_controller_set_position (MprisController* self, double position); +static void scrub_menuitem_real_handle_event (DbusmenuMenuitem* base, const char* name, GValue* input_value, guint timestamp); +void scrub_menuitem_update_position (ScrubMenuitem* self, gint32 new_position); +GeeHashSet* scrub_menuitem_attributes_format (void); + + + +ScrubMenuitem* scrub_menuitem_construct (GType object_type, PlayerController* parent) { + ScrubMenuitem * self; + g_return_val_if_fail (parent != NULL, NULL); + self = (ScrubMenuitem*) g_object_new (object_type, "item-type", DBUSMENU_SCRUB_MENUITEM_TYPE, "owner", parent, NULL); + return self; +} + + +ScrubMenuitem* scrub_menuitem_new (PlayerController* parent) { + return scrub_menuitem_construct (TYPE_SCRUB_MENUITEM, parent); +} + + +static void scrub_menuitem_real_handle_event (DbusmenuMenuitem* base, const char* name, GValue* input_value, guint timestamp) { + ScrubMenuitem * self; + self = (ScrubMenuitem*) base; + g_return_if_fail (name != NULL); + g_debug ("scrub-menu-item.vala:33: handle_event for owner %s with value: %f", player_controller_get_name (player_item_get_owner ((PlayerItem*) self)), g_value_get_double (input_value)); + mpris_controller_set_position (player_item_get_owner ((PlayerItem*) self)->mpris_adaptor, g_value_get_double (input_value)); +} + + +void scrub_menuitem_update_position (ScrubMenuitem* self, gint32 new_position) { + g_return_if_fail (self != NULL); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, DBUSMENU_SCRUB_MENUITEM_POSITION, (gint) new_position); +} + + +GeeHashSet* scrub_menuitem_attributes_format (void) { + GeeHashSet* result = NULL; + GeeHashSet* attrs; + attrs = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, NULL, NULL); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_SCRUB_MENUITEM_DURATION); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_SCRUB_MENUITEM_POSITION); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_SCRUB_MENUITEM_PLAY_STATE); + result = attrs; + return result; +} + + +static void scrub_menuitem_class_init (ScrubMenuitemClass * klass) { + scrub_menuitem_parent_class = g_type_class_peek_parent (klass); + DBUSMENU_MENUITEM_CLASS (klass)->handle_event = scrub_menuitem_real_handle_event; +} + + +static void scrub_menuitem_instance_init (ScrubMenuitem * self) { +} + + +GType scrub_menuitem_get_type (void) { + static volatile gsize scrub_menuitem_type_id__volatile = 0; + if (g_once_init_enter (&scrub_menuitem_type_id__volatile)) { + static const GTypeInfo g_define_type_info = { sizeof (ScrubMenuitemClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scrub_menuitem_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScrubMenuitem), 0, (GInstanceInitFunc) scrub_menuitem_instance_init, NULL }; + GType scrub_menuitem_type_id; + scrub_menuitem_type_id = g_type_register_static (TYPE_PLAYER_ITEM, "ScrubMenuitem", &g_define_type_info, 0); + g_once_init_leave (&scrub_menuitem_type_id__volatile, scrub_menuitem_type_id); + } + return scrub_menuitem_type_id__volatile; +} + + + + diff --git a/src/scrub-menu-item.vala b/src/scrub-menu-item.vala new file mode 100644 index 0000000..29fa903 --- /dev/null +++ b/src/scrub-menu-item.vala @@ -0,0 +1,50 @@ +/* +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 DbusmenuScrub; +using Gee; + +public class ScrubMenuitem : PlayerItem +{ + public ScrubMenuitem(PlayerController parent) + { + Object(item_type: MENUITEM_TYPE, owner: parent); + } + + public override void handle_event(string name, GLib.Value input_value, uint timestamp) + { + debug("handle_event for owner %s with value: %f", this.owner.name, input_value.get_double()); + this.owner.mpris_adaptor.set_position(input_value.get_double()); + } + + public void update_position(int32 new_position) + { + this.property_set_int(MENUITEM_POSITION, new_position); + } + + public static HashSet<string> attributes_format() + { + HashSet<string> attrs = new HashSet<string>(); + attrs.add(MENUITEM_DURATION); + attrs.add(MENUITEM_POSITION); + attrs.add(MENUITEM_PLAY_STATE); + return attrs; + } +}
\ No newline at end of file diff --git a/src/scrub-widget.c b/src/scrub-widget.c new file mode 100644 index 0000000..fa290e0 --- /dev/null +++ b/src/scrub-widget.c @@ -0,0 +1,366 @@ +/* +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 "scrub-widget.h" +#include "common-defs.h" +#include <libido/idoscalemenuitem.h> +#include <libido/idotimeline.h> + +typedef struct _ScrubWidgetPrivate ScrubWidgetPrivate; + +struct _ScrubWidgetPrivate +{ + DbusmenuMenuitem* twin_item; + GtkWidget* ido_scrub_bar; + IdoTimeline* time_line; + gboolean scrubbing; +}; + +#define SCRUB_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SCRUB_WIDGET_TYPE, ScrubWidgetPrivate)) + +/* Prototypes */ +static void scrub_widget_class_init (ScrubWidgetClass *klass); +static void scrub_widget_init (ScrubWidget *self); +static void scrub_widget_dispose (GObject *object); +static void scrub_widget_finalize (GObject *object); +static void scrub_widget_property_update( DbusmenuMenuitem* item, gchar* property, + GValue* value, gpointer userdata); +static void scrub_widget_set_twin_item( ScrubWidget* self, + DbusmenuMenuitem* twin_item); +static gchar* scrub_widget_format_time(gint time); +static void scrub_widget_set_ido_position(ScrubWidget* self, + gint position, + gint duration); +static gboolean scrub_widget_change_value_cb (GtkRange *range, + GtkScrollType scroll, + gdouble value, + gpointer user_data); + +static void scrub_widget_timeline_frame_cb(IdoTimeline *timeline, + gdouble progress, + gpointer userdata); +static void scrub_widget_timeline_started_cb(IdoTimeline *timeline, + gpointer userdata); +static void scrub_widget_timeline_finished_cb(IdoTimeline *timeline, + gpointer userdata); +static gdouble scrub_widget_calculate_progress(ScrubWidget* widget); +static void scrub_widget_check_play_state(ScrubWidget* self); +static void scrub_widget_slider_grabbed(GtkWidget *widget, gpointer user_data); +static void scrub_widget_slider_released(GtkWidget *widget, gpointer user_data); + + + +G_DEFINE_TYPE (ScrubWidget, scrub_widget, G_TYPE_OBJECT); + +static void +scrub_widget_class_init (ScrubWidgetClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (ScrubWidgetPrivate)); + + gobject_class->dispose = scrub_widget_dispose; + gobject_class->finalize = scrub_widget_finalize; +} + +static void +scrub_widget_init (ScrubWidget *self) +{ + g_debug("ScrubWidget::scrub_widget_init"); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + + priv->ido_scrub_bar = ido_scale_menu_item_new_with_range ("Scrub", IDO_RANGE_STYLE_SMALL, 0, 0, 100, 1); + priv->time_line = ido_timeline_new(0); + + ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), IDO_SCALE_MENU_ITEM_STYLE_LABEL); + g_object_set(priv->ido_scrub_bar, "reverse-scroll-events", TRUE, NULL); + priv->scrubbing = FALSE; + + // register slider changes listening on the range + GtkWidget* scrub_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_scrub_bar); + g_signal_connect(scrub_widget, "change-value", G_CALLBACK(scrub_widget_change_value_cb), self); + g_signal_connect(priv->time_line, "frame", G_CALLBACK(scrub_widget_timeline_frame_cb), self); + g_signal_connect(priv->time_line, "started", G_CALLBACK(scrub_widget_timeline_started_cb), self); + g_signal_connect(priv->time_line, "finished", G_CALLBACK(scrub_widget_timeline_finished_cb), self); + g_signal_connect(priv->ido_scrub_bar, "slider-grabbed", G_CALLBACK(scrub_widget_slider_grabbed), self); + g_signal_connect(priv->ido_scrub_bar, "slider-released", G_CALLBACK(scrub_widget_slider_released), self); +} + +static void +scrub_widget_dispose (GObject *object) +{ + G_OBJECT_CLASS (scrub_widget_parent_class)->dispose (object); +} + +static void +scrub_widget_finalize (GObject *object) +{ + G_OBJECT_CLASS (scrub_widget_parent_class)->finalize (object); +} + +static void +scrub_widget_property_update(DbusmenuMenuitem* item, gchar* property, + GValue* value, gpointer userdata) +{ + g_debug("scrub-widget::property_update"); + + g_return_if_fail (IS_SCRUB_WIDGET (userdata)); + ScrubWidget* mitem = SCRUB_WIDGET(userdata); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + + if(g_ascii_strcasecmp(DBUSMENU_SCRUB_MENUITEM_DURATION, property) == 0){ + g_debug("scrub-widget::update length = %i", g_value_get_int(value)); + ido_scale_menu_item_set_secondary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), + scrub_widget_format_time(g_value_get_int(value))); + + ido_timeline_set_duration(priv->time_line, g_value_get_int(value) * 1000); + ido_timeline_rewind(priv->time_line); + scrub_widget_check_play_state(mitem); + g_debug("timeline is running: %i", (gint)ido_timeline_is_running(priv->time_line)); + g_debug("timeline duration = %i", ido_timeline_get_duration(priv->time_line)); + + scrub_widget_set_ido_position(mitem, + dbusmenu_menuitem_property_get_int(priv->twin_item, DBUSMENU_SCRUB_MENUITEM_POSITION)/1000, + dbusmenu_menuitem_property_get_int(priv->twin_item, DBUSMENU_SCRUB_MENUITEM_DURATION)); + } + else if(g_ascii_strcasecmp(DBUSMENU_SCRUB_MENUITEM_POSITION, property) == 0){ + g_debug("scrub-widget::update position = %i", g_value_get_int(value)); + ido_timeline_pause(priv->time_line); + ido_scale_menu_item_set_primary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), + scrub_widget_format_time(g_value_get_int(value)/1000)); + + ido_timeline_set_progress(priv->time_line, scrub_widget_calculate_progress(mitem)*1000); + scrub_widget_set_ido_position(mitem, g_value_get_int(value)/1000, + dbusmenu_menuitem_property_get_int(priv->twin_item, DBUSMENU_SCRUB_MENUITEM_DURATION)); + ido_timeline_start(priv->time_line); + + } + else if(g_ascii_strcasecmp(DBUSMENU_SCRUB_MENUITEM_PLAY_STATE, property) == 0){ + scrub_widget_check_play_state(mitem); + } +} + +static void +scrub_widget_check_play_state(ScrubWidget* self) +{ + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + gint play_state = dbusmenu_menuitem_property_get_int(priv->twin_item, + DBUSMENU_SCRUB_MENUITEM_PLAY_STATE); + + if(play_state == 0){ + g_debug("START TIMELINE"); + ido_timeline_start(priv->time_line); + } + else{ + g_debug("PAUSE TIMELINE"); + ido_timeline_pause(priv->time_line); + } +} + +static void +scrub_widget_set_twin_item(ScrubWidget* self, + DbusmenuMenuitem* twin_item) +{ + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + priv->twin_item = twin_item; + + g_signal_connect(G_OBJECT(twin_item), "property-changed", + G_CALLBACK(scrub_widget_property_update), self); + + gchar* left_text = scrub_widget_format_time(dbusmenu_menuitem_property_get_int(priv->twin_item, DBUSMENU_SCRUB_MENUITEM_POSITION)/1000); + gchar* right_text = scrub_widget_format_time(dbusmenu_menuitem_property_get_int(priv->twin_item, + DBUSMENU_SCRUB_MENUITEM_DURATION)); + scrub_widget_set_ido_position(self, + dbusmenu_menuitem_property_get_int(priv->twin_item, DBUSMENU_SCRUB_MENUITEM_POSITION)/1000, + dbusmenu_menuitem_property_get_int(priv->twin_item, DBUSMENU_SCRUB_MENUITEM_DURATION)); + + ido_scale_menu_item_set_primary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), left_text); + ido_scale_menu_item_set_secondary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), right_text); + g_free(left_text); + g_free(right_text); +} + +static gboolean +scrub_widget_change_value_cb (GtkRange *range, + GtkScrollType scroll, + gdouble new_value, + gpointer user_data) +{ + /*g_return_val_if_fail (IS_SCRUB_WIDGET (user_data), FALSE); + ScrubWidget* mitem = SCRUB_WIDGET(user_data); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + + GValue value = {0}; + g_value_init(&value, G_TYPE_DOUBLE); + gdouble clamped = CLAMP(new_value, 0, 100); + g_value_set_double(&value, clamped); + //g_debug("scrub-widget-change-value callback - = %f", clamped); + if(priv->scrubbing == FALSE){ + dbusmenu_menuitem_handle_event (priv->twin_item, "scrubbing", &value, 0); + } + else{ + g_debug("blocking scrubbing because the slider is still grabbed" + }*/ + return FALSE; +} + +GtkWidget* +scrub_widget_get_ido_bar(ScrubWidget* self) +{ + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + return priv->ido_scrub_bar; +} + +static gchar* +scrub_widget_format_time(gint time) +{ + // Assuming its in seconds for now ... + gint minutes = time/60; + gint seconds = time % 60; + gchar* prefix="0"; + gchar* seconds_prefix="0"; + if(minutes > 9) + prefix=""; + if(seconds > 9) + seconds_prefix=""; + return g_strdup_printf("%s%i:%s%i", prefix, minutes, seconds_prefix, seconds); +} + +static void +scrub_widget_set_ido_position(ScrubWidget* self, + gint position, + gint duration) +{ + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + gdouble ido_position = position/(gdouble)duration * 100.0; + g_debug("scrub_widget_set_ido_position - pos: %i, duration: %i, ido_pos: %f", position, duration, ido_position); + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_scrub_bar); + GtkRange *range = (GtkRange*)slider; + if(duration == 0) + ido_position = 0.0; + gtk_range_set_value(range, ido_position); +} + +static gdouble +scrub_widget_calculate_progress(ScrubWidget* widget) +{ + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(widget); + gint position = dbusmenu_menuitem_property_get_int(priv->twin_item, + DBUSMENU_SCRUB_MENUITEM_POSITION)/1000; + gint duration = dbusmenu_menuitem_property_get_int(priv->twin_item, + DBUSMENU_SCRUB_MENUITEM_DURATION); + gdouble ido_position = position/(gdouble)duration; + g_debug("scrub_widget_calculate_progress %f", ido_position); + + return ido_position; +} + + +static void +scrub_widget_timeline_frame_cb( IdoTimeline *timeline, + gdouble progress, + gpointer user_data) +{ + + //g_debug("Timeline CB : %f", progress); + g_return_if_fail (IS_SCRUB_WIDGET (user_data)); + ScrubWidget* mitem = SCRUB_WIDGET(user_data); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + if(priv->scrubbing == TRUE) + { + //g_debug("don't update the slider or timeline, slider is being scrubbed"); + return; + } + gint position = progress * dbusmenu_menuitem_property_get_int(priv->twin_item, + DBUSMENU_SCRUB_MENUITEM_DURATION); + gchar* left_text = scrub_widget_format_time(position); + ido_scale_menu_item_set_primary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), left_text); + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_scrub_bar); + GtkRange *range = (GtkRange*)slider; + gtk_range_set_value(range, progress * 100); + + /*g_debug("position in seconds %i and in words %s", position, left_text); + g_debug("timeline is running: %i", (gint)ido_timeline_is_running(priv->time_line)); + g_debug("timeline duration = %i", ido_timeline_get_duration(priv->time_line)); + */ + g_free(left_text); +} + + +static void +scrub_widget_slider_released(GtkWidget *widget, gpointer user_data) +{ + ScrubWidget* mitem = SCRUB_WIDGET(user_data); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + priv->scrubbing = FALSE; + GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_scrub_bar); + gdouble new_value = gtk_range_get_value(GTK_RANGE(slider)); + g_debug("okay set the scrub position with %f", new_value); + GValue value = {0}; + g_value_init(&value, G_TYPE_DOUBLE); + gdouble clamped = CLAMP(new_value, 0, 100); + g_value_set_double(&value, clamped); + dbusmenu_menuitem_handle_event (priv->twin_item, "scrubbing", &value, 0); +} + +static void +scrub_widget_slider_grabbed(GtkWidget *widget, gpointer user_data) +{ + ScrubWidget* mitem = SCRUB_WIDGET(user_data); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + priv->scrubbing = TRUE; + +} + +static void +scrub_widget_timeline_started_cb( IdoTimeline *timeline, + gpointer user_data) +{ + g_debug("Timeline Started!"); +} + +static void +scrub_widget_timeline_finished_cb(IdoTimeline *timeline, + gpointer user_data) +{ + g_debug("Timeline Finished!"); + /*g_return_if_fail (IS_SCRUB_WIDGET (user_data)); + ScrubWidget* mitem = SCRUB_WIDGET(user_data); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + ido_timeline_rewind(priv->time_line);*/ +} + +/** + * scrub_widget_new: + * @returns: a new #ScrubWidget. + **/ +GtkWidget* +scrub_widget_new(DbusmenuMenuitem *item) +{ + GtkWidget* widget = g_object_new(SCRUB_WIDGET_TYPE, NULL); + scrub_widget_set_twin_item((ScrubWidget*)widget, item); + return widget; +} + + diff --git a/src/scrub-widget.h b/src/scrub-widget.h new file mode 100644 index 0000000..cebe890 --- /dev/null +++ b/src/scrub-widget.h @@ -0,0 +1,53 @@ +/* +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 __SCRUB_WIDGET_H__ +#define __SCRUB_WIDGET_H__ + +#include <glib.h> +#include <glib-object.h> +#include <libdbusmenu-gtk/menu.h> + +G_BEGIN_DECLS + +#define SCRUB_WIDGET_TYPE (scrub_widget_get_type ()) +#define SCRUB_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SCRUB_WIDGET_TYPE, ScrubWidget)) +#define SCRUB_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SCRUB_WIDGET_TYPE, ScrubWidgetClass)) +#define IS_SCRUB_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SCRUB_WIDGET_TYPE)) +#define IS_SCRUB_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SCRUB_WIDGET_TYPE)) +#define SCRUB_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SCRUB_WIDGET_TYPE, ScrubWidgetClass)) + +typedef struct _ScrubWidget ScrubWidget; +typedef struct _ScrubWidgetClass ScrubWidgetClass; + +struct _ScrubWidgetClass { + GObjectClass parent_class; +}; + +struct _ScrubWidget { + GObject parent; +}; + +GType scrub_widget_get_type (void) G_GNUC_CONST; +GtkWidget* scrub_widget_new(DbusmenuMenuitem* twin_item); +GtkWidget* scrub_widget_get_ido_bar(ScrubWidget* self); + +G_END_DECLS + +#endif + diff --git a/src/sound-service-dbus.h b/src/sound-service-dbus.h index 258b610..72556ad 100644 --- a/src/sound-service-dbus.h +++ b/src/sound-service-dbus.h @@ -33,7 +33,6 @@ G_BEGIN_DECLS #define IS_SOUND_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SOUND_SERVICE_DBUS_TYPE)) #define SOUND_SERVICE_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SOUND_SERVICE_DBUS_TYPE, SoundServiceDbusClass)) - typedef struct _SoundServiceDbus SoundServiceDbus; typedef struct _SoundServiceDbusClass SoundServiceDbusClass; typedef struct _SoundData SoundData; diff --git a/src/sound-service.c b/src/sound-service.c index 8f4e941..8768cd3 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -39,7 +39,6 @@ should follow it. void service_shutdown (IndicatorService *service, gpointer user_data) { - if (mainloop != NULL) { g_debug("Service shutdown !"); // TODO: uncomment for release !! diff --git a/src/title-menu-item.c b/src/title-menu-item.c index 20d0aa4..9dab15f 100644 --- a/src/title-menu-item.c +++ b/src/title-menu-item.c @@ -141,7 +141,7 @@ TitleMenuitem* title_menuitem_construct (GType object_type, PlayerController* pa TitleMenuitem * self; g_return_val_if_fail (parent != NULL, NULL); self = (TitleMenuitem*) g_object_new (object_type, "item-type", DBUSMENU_TITLE_MENUITEM_TYPE, "owner", parent, NULL); - dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_TEXT_NAME, player_controller_get_name (parent)); + dbusmenu_menuitem_property_set ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_NAME, player_controller_get_name (parent)); return self; } @@ -155,8 +155,6 @@ static void title_menuitem_real_handle_event (DbusmenuMenuitem* base, const char TitleMenuitem * self; self = (TitleMenuitem*) base; g_return_if_fail (name != NULL); - g_debug ("title-menu-item.vala:34: handle_event for owner %s with owner state = " \ -"%i and title menu name %s", player_controller_get_name (player_item_get_owner ((PlayerItem*) self)), player_item_get_owner ((PlayerItem*) self)->current_state, dbusmenu_menuitem_property_get ((DbusmenuMenuitem*) self, DBUSMENU_TITLE_MENUITEM_TEXT_NAME)); if (player_item_get_owner ((PlayerItem*) self)->current_state == PLAYER_CONTROLLER_STATE_OFFLINE) { player_controller_instantiate (player_item_get_owner ((PlayerItem*) self)); } @@ -167,7 +165,7 @@ GeeHashSet* title_menuitem_attributes_format (void) { GeeHashSet* result = NULL; GeeHashSet* attrs; attrs = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, NULL, NULL); - gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_TITLE_MENUITEM_TEXT_NAME); + gee_abstract_collection_add ((GeeAbstractCollection*) attrs, DBUSMENU_TITLE_MENUITEM_NAME); result = attrs; return result; } diff --git a/src/title-menu-item.vala b/src/title-menu-item.vala index 8183821..d7e16df 100644 --- a/src/title-menu-item.vala +++ b/src/title-menu-item.vala @@ -26,13 +26,11 @@ public class TitleMenuitem : PlayerItem public TitleMenuitem(PlayerController parent) { Object(item_type: MENUITEM_TYPE, owner: parent); - this.property_set(MENUITEM_TEXT_NAME, parent.name); + this.property_set(MENUITEM_NAME, parent.name); } public override void handle_event(string name, GLib.Value input_value, uint timestamp) - { - debug("handle_event for owner %s with owner state = %i and title menu name %s", this.owner.name, this.owner.current_state, property_get(MENUITEM_TEXT_NAME)); - + { if(this.owner.current_state == PlayerController.state.OFFLINE) { this.owner.instantiate(); @@ -43,7 +41,7 @@ public class TitleMenuitem : PlayerItem public static HashSet<string> attributes_format() { HashSet<string> attrs = new HashSet<string>(); - attrs.add(MENUITEM_TEXT_NAME); + attrs.add(MENUITEM_NAME); return attrs; } }
\ No newline at end of file diff --git a/src/title-widget.c b/src/title-widget.c index 7e48940..8037eb7 100644 --- a/src/title-widget.c +++ b/src/title-widget.c @@ -152,7 +152,7 @@ title_widget_property_update(DbusmenuMenuitem* item, gchar* property, TitleWidget* mitem = TITLE_WIDGET(userdata); TitleWidgetPrivate * priv = TITLE_WIDGET_GET_PRIVATE(mitem); - if(g_ascii_strcasecmp(DBUSMENU_TITLE_MENUITEM_TEXT_NAME, property) == 0){ + if(g_ascii_strcasecmp(DBUSMENU_TITLE_MENUITEM_NAME, property) == 0){ gtk_label_set_text(GTK_LABEL(priv->name), g_value_get_string(value)); title_widget_style_name_text(mitem); } @@ -167,7 +167,7 @@ title_widget_set_twin_item(TitleWidget* self, g_signal_connect(G_OBJECT(twin_item), "property-changed", G_CALLBACK(title_widget_property_update), self); priv->name = gtk_label_new(dbusmenu_menuitem_property_get(priv->twin_item, - DBUSMENU_TITLE_MENUITEM_TEXT_NAME)); + DBUSMENU_TITLE_MENUITEM_NAME)); gtk_misc_set_padding(GTK_MISC(priv->name), 10, 0); gtk_box_pack_start (GTK_BOX (priv->hbox), priv->name, FALSE, FALSE, 0); diff --git a/src/transport-menu-item.c b/src/transport-menu-item.c index 0734a97..bbe5a4d 100644 --- a/src/transport-menu-item.c +++ b/src/transport-menu-item.c @@ -153,6 +153,7 @@ TransportMenuitem* transport_menuitem_construct (GType object_type, PlayerContro TransportMenuitem * self; g_return_val_if_fail (parent != NULL, NULL); self = (TransportMenuitem*) g_object_new (object_type, "item-type", DBUSMENU_TRANSPORT_MENUITEM_TYPE, "owner", parent, NULL); + dbusmenu_menuitem_property_set_int ((DbusmenuMenuitem*) self, DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE, 1); return self; } @@ -175,9 +176,9 @@ static void transport_menuitem_real_handle_event (DbusmenuMenuitem* base, const self = (TransportMenuitem*) base; g_return_if_fail (name != NULL); input = g_value_get_int (input_value); - g_debug ("transport-menu-item.vala:45: handle_event with value %s", _tmp0_ = g_strdup_printf ("%i", input)); + g_debug ("transport-menu-item.vala:46: handle_event with value %s", _tmp0_ = g_strdup_printf ("%i", input)); _g_free0 (_tmp0_); - g_debug ("transport-menu-item.vala:46: transport owner name = %s", player_controller_get_name (player_item_get_owner ((PlayerItem*) self))); + g_debug ("transport-menu-item.vala:47: transport owner name = %s", player_controller_get_name (player_item_get_owner ((PlayerItem*) self))); mpris_controller_transport_event (player_item_get_owner ((PlayerItem*) self)->mpris_adaptor, (TransportMenuitemaction) input); } diff --git a/src/transport-menu-item.vala b/src/transport-menu-item.vala index 8e837c2..3d6dcdd 100644 --- a/src/transport-menu-item.vala +++ b/src/transport-menu-item.vala @@ -32,6 +32,7 @@ public class TransportMenuitem : PlayerItem public TransportMenuitem(PlayerController parent) { Object(item_type: MENUITEM_TYPE, owner: parent); + this.property_set_int(MENUITEM_PLAY_STATE, 1); } public void change_play_state(int state) diff --git a/src/transport-widget.c b/src/transport-widget.c index f02200e..c616fff 100644 --- a/src/transport-widget.c +++ b/src/transport-widget.c @@ -137,9 +137,7 @@ static gboolean transport_widget_button_press_event (GtkWidget *menuitem, GdkEventButton *event) { - if(IS_TRANSPORT_WIDGET(menuitem) == FALSE){ - return FALSE; - } + g_return_val_if_fail(IS_TRANSPORT_WIDGET(menuitem), FALSE); TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem)); @@ -147,14 +145,16 @@ transport_widget_button_press_event (GtkWidget *menuitem, parent = gtk_widget_get_parent (GTK_WIDGET (menuitem)); - gint result = determine_button_event(priv->play_button, event); + PlayButtonEvent result = determine_button_event(priv->play_button, event); - GValue value = {0}; - g_value_init(&value, G_TYPE_INT); - g_debug("TransportWidget::menu_press_event - going to send value %i", result); - g_value_set_int(&value, result); - dbusmenu_menuitem_handle_event (priv->twin_item, "Transport state change", &value, 0); - + if(result != TRANSPORT_NADA){ + GValue value = {0}; + g_value_init(&value, G_TYPE_INT); + g_debug("TransportWidget::menu_press_event - going to send value %i", (int)result); + g_value_set_int(&value, (int)result); + dbusmenu_menuitem_handle_event (priv->twin_item, "Transport state change", &value, 0); + play_button_react_to_button_press(priv->play_button, result); + } return TRUE; } @@ -164,9 +164,9 @@ transport_widget_button_release_event (GtkWidget *menuitem, GdkEventButton *event) { g_debug("TransportWidget::menu_release_event"); - if(IS_TRANSPORT_WIDGET(menuitem) == FALSE){ - return FALSE; - } + g_return_val_if_fail(IS_TRANSPORT_WIDGET(menuitem), FALSE); + TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem)); + play_button_react_to_button_release(priv->play_button); return TRUE; } @@ -180,12 +180,13 @@ transport_widget_property_update(DbusmenuMenuitem* item, gchar* property, GValue* value, gpointer userdata) { g_debug("transport_widget_update_state - with property %s", property); - //int update_value = g_value_get_int(value); - //g_debug("transport_widget_update_state - with value %i", update_value); - - //TransportWidget* bar = (TransportWidget*)userdata; - //TransportWidgetPrivate *priv = TRANSPORT_WIDGET_GET_PRIVATE(bar); + TransportWidget* bar = (TransportWidget*)userdata; + g_return_if_fail(IS_TRANSPORT_WIDGET(bar)); + TransportWidgetPrivate *priv = TRANSPORT_WIDGET_GET_PRIVATE(bar); + int update_value = g_value_get_int(value); + g_debug("transport_widget_update_state - with value %i", update_value); + play_button_toggle_play_pause(priv->play_button, (PlayButtonState)update_value); } /** diff --git a/vapi/common-defs.vapi b/vapi/common-defs.vapi index 6649b26..c083e2a 100644 --- a/vapi/common-defs.vapi +++ b/vapi/common-defs.vapi @@ -20,9 +20,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>. [CCode (cheader_filename = "common-defs.h")] namespace DbusmenuMetadata{ public const string MENUITEM_TYPE; - public const string MENUITEM_TEXT_ARTIST; - public const string MENUITEM_TEXT_TITLE; - public const string MENUITEM_TEXT_ALBUM; + public const string MENUITEM_ARTIST; + public const string MENUITEM_TITLE; + public const string MENUITEM_ALBUM; public const string MENUITEM_ARTURL; } @@ -35,5 +35,13 @@ namespace DbusmenuTransport{ [CCode (cheader_filename = "common-defs.h")] namespace DbusmenuTitle{ public const string MENUITEM_TYPE; - public const string MENUITEM_TEXT_NAME; + public const string MENUITEM_NAME; +} + +[CCode (cheader_filename = "common-defs.h")] +namespace DbusmenuScrub{ + public const string MENUITEM_TYPE; + public const string MENUITEM_POSITION; + public const string MENUITEM_DURATION; + public const string MENUITEM_PLAY_STATE; }
\ No newline at end of file |