aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am165
-rw-r--r--src/com.canonical.indicator.sound6
-rw-r--r--src/common-defs.h94
-rw-r--r--src/dbus-shared-names.h37
-rw-r--r--src/device.c276
-rw-r--r--src/device.h84
-rw-r--r--src/fetch-file.vala86
-rw-r--r--src/indicator-sound.c834
-rw-r--r--src/indicator-sound.h59
-rw-r--r--src/main.vala5
-rw-r--r--src/media-player-list.vala132
-rw-r--r--src/media-player.vala216
-rw-r--r--src/metadata-menu-item.vala224
-rw-r--r--src/metadata-widget.c880
-rw-r--r--src/metadata-widget.h51
-rw-r--r--src/mpris2-controller.vala286
-rw-r--r--src/mpris2-watcher.vala4
-rw-r--r--src/music-player-bridge.vala305
-rw-r--r--src/mute-menu-item.c154
-rw-r--r--src/mute-menu-item.h59
-rw-r--r--src/mute-widget.c134
-rw-r--r--src/mute-widget.h63
-rw-r--r--src/player-activator.vala199
-rw-r--r--src/player-controller.vala252
-rw-r--r--src/player-item.vala104
-rw-r--r--src/playlists-menu-item.vala154
-rw-r--r--src/pulseaudio-mgr.c717
-rw-r--r--src/pulseaudio-mgr.h33
-rw-r--r--src/scrub-menu-item.vala56
-rw-r--r--src/service.vala321
-rw-r--r--src/settings-manager.vala136
-rw-r--r--src/slider-menu-item.c258
-rw-r--r--src/slider-menu-item.h64
-rw-r--r--src/sound-service-dbus.c489
-rw-r--r--src/sound-service-dbus.h66
-rw-r--r--src/sound-service-marshal.list2
-rw-r--r--src/sound-service.c127
-rw-r--r--src/sound-service.h35
-rw-r--r--src/sound-service.xml34
-rw-r--r--src/sound-state-manager.c480
-rw-r--r--src/sound-state-manager.h67
-rw-r--r--src/sound-state.c43
-rw-r--r--src/sound-state.h31
-rw-r--r--src/specific-items-manager.vala109
-rw-r--r--src/transport-menu-item.vala100
-rw-r--r--src/transport-widget.c1886
-rw-r--r--src/transport-widget.h67
-rw-r--r--src/voip-input-menu-item.c278
-rw-r--r--src/voip-input-widget.c284
-rw-r--r--src/voip-input-widget.h56
-rw-r--r--src/volume-control.vala272
-rw-r--r--src/volume-widget.c338
-rw-r--r--src/volume-widget.h58
53 files changed, 966 insertions, 10304 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 55df0f6..84ee0f1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,128 +1,27 @@
libexec_PROGRAMS = indicator-sound-service
-###################
-# Indicator Stuff
-###################
-
-soundmenulibdir = $(INDICATORDIR)
-soundmenulib_LTLIBRARIES = libsoundmenu.la
-libsoundmenu_la_SOURCES = \
- common-defs.h \
- indicator-sound.h \
- indicator-sound.c \
- sound-state.c \
- sound-state.h \
- sound-state-manager.c \
- sound-state-manager.h \
- transport-widget.c \
- transport-widget.h \
- metadata-widget.c \
- metadata-widget.h \
- mute-widget.c \
- mute-widget.h \
- volume-widget.c \
- volume-widget.h \
- voip-input-widget.c \
- voip-input-widget.h \
- gen-sound-service.xml.h \
- gen-sound-service.xml.c \
- dbus-shared-names.h
-
-libsoundmenu_la_CFLAGS = \
- $(APPLET_CFLAGS) \
- $(COVERAGE_CFLAGS) \
- -Wall -Werror -DG_LOG_DOMAIN=\"Indicator-Sound\"
-libsoundmenu_la_LIBADD = $(APPLET_LIBS) -lm
-libsoundmenu_la_LDFLAGS = \
- $(COVERAGE_LDFLAGS) \
- -module -avoid-version
-
-
-checkxml: $(srcdir)/sound-service.xml
- @xmllint -valid -noout $<
- @echo $< checks out ok
-
-
-####################################################################
-# Sound Service
-####################################################################
-
-glib_marshal_list = sound-service-marshal.list
-glib_marshal_prefix = _sound_service_marshal
-
-
-#####################
-# Sound service vala
-#####################
-music_bridge_VALASOURCES = \
- music-player-bridge.vala \
- transport-menu-item.vala \
- specific-items-manager.vala \
- metadata-menu-item.vala \
- player-controller.vala \
+indicator_sound_service_SOURCES = \
+ service.vala \
+ main.vala \
+ volume-control.vala \
+ media-player.vala \
+ media-player-list.vala \
mpris2-interfaces.vala \
mpris2-watcher.vala \
- mpris2-controller.vala \
- player-item.vala \
- settings-manager.vala \
- playlists-menu-item.vala \
- freedesktop-interfaces.vala \
- fetch-file.vala \
- player-activator.vala
+ freedesktop-interfaces.vala
-music_bridge_VALAFLAGS = \
+indicator_sound_service_VALAFLAGS = \
--ccode \
- -H music-player-bridge.h -d . \
--vapidir=$(top_srcdir)/vapi/ \
--vapidir=./ \
--thread \
- --pkg gee-1.0 \
- --pkg Dbusmenu-0.4 \
- --pkg common-defs \
--pkg config \
--pkg gio-2.0 \
--pkg gio-unix-2.0 \
- --pkg gdk-3.0 \
- --pkg gdk-x11-3.0 \
- --pkg gdk-pixbuf-2.0 \
- --pkg libbamf3 \
- --pkg libxml-2.0
-
- $(MAINTAINER_VALAFLAGS)
-
-music_bridge_APIFILES = \
- music-player-bridge.h
-
-music_bridge_vala.stamp $(music_bridge_APIFILES): $(music_bridge_VALASOURCES)
- $(AM_V_GEN) $(VALAC) $(music_bridge_VALAFLAGS) $^
- touch music_bridge_vala.stamp
-
-###############################
-# Sound Service C
-###############################
-indicator_sound_service_SOURCES = \
- common-defs.h \
- sound-service.h \
- sound-service.c \
- sound-state.c \
- sound-state.h \
- pulseaudio-mgr.h \
- pulseaudio-mgr.c \
- device.c \
- device.h \
- sound-service-dbus.h \
- sound-service-dbus.c \
- slider-menu-item.h \
- slider-menu-item.c \
- voip-input-menu-item.h \
- voip-input-menu-item.c \
- mute-menu-item.h \
- mute-menu-item.c \
- gen-sound-service.xml.h \
- gen-sound-service.xml.c \
- sound-service-marshal.c \
- sound-service-marshal.h \
- $(music_bridge_VALASOURCES:.vala=.c)
+ --pkg libxml-2.0 \
+ --pkg libpulse \
+ --pkg libpulse-mainloop-glib \
+ --target-glib=2.36
indicator_sound_service_CFLAGS = $(PULSEAUDIO_CFLAGS) \
$(SOUNDSERVICE_CFLAGS) \
@@ -131,43 +30,3 @@ indicator_sound_service_CFLAGS = $(PULSEAUDIO_CFLAGS) \
-DLIBEXECDIR=\"$(libexecdir)\" -Wall
indicator_sound_service_LDADD = $(PULSEAUDIO_LIBS) $(SOUNDSERVICE_LIBS) $(GCONF_LIBS)
indicator_sound_service_LDFLAGS = $(COVERAGE_LDFLAGS)
-
-#########################
-# Service xml compilation
-#########################
-DBUS_SPECS = \
- sound-service.xml
-
-gen-%.xml.h: %.xml
- @echo "Building $@ from $<"
- @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<))));" > $@
-
-gen-%.xml.c: %.xml
- @echo "Building $@ from $<"
- @echo "const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<)))) = " > $@
- @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@
- @echo ";" >> $@
-
-
-EXTRA_DIST = \
- $(DBUS_SPECS) \
- sound-service.xml \
- $(music_bridge_APIFILES) \
- $(music_bridge_VALASOURCES)
-
-#######################
-# Stuff to clean Stuff
-#######################
-BUILT_SOURCES = \
- music_bridge_vala.stamp \
- $(music_bridge_APIFILES) \
- gen-sound-service.xml.h \
- gen-sound-service.xml.c \
- $(music_bridge_VALASOURCES:.vala=.c)
-
-CLEANFILES = \
- $(BUILT_SOURCES)
-
-DISTCLEANFILES =
-
-include $(top_srcdir)/Makefile.am.marshal
diff --git a/src/com.canonical.indicator.sound b/src/com.canonical.indicator.sound
new file mode 100644
index 0000000..825fd30
--- /dev/null
+++ b/src/com.canonical.indicator.sound
@@ -0,0 +1,6 @@
+[Indicator Service]
+Name=indicator-sound
+ObjectPath=/com/canonical/indicator/sound
+
+[desktop]
+ObjectPath=/com/canonical/indicator/sound/desktop
diff --git a/src/common-defs.h b/src/common-defs.h
deleted file mode 100644
index efca5b2..0000000
--- a/src/common-defs.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-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 __COMMON_DEFS_H__
-#define __COMMON_DEFS_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-typedef enum {
- MUTED,
- ZERO_LEVEL,
- LOW_LEVEL,
- MEDIUM_LEVEL,
- HIGH_LEVEL,
- BLOCKED,
- UNAVAILABLE,
- AVAILABLE
-}SoundState;
-
-typedef enum {
- TRANSPORT_ACTION_PREVIOUS,
- TRANSPORT_ACTION_PLAY_PAUSE,
- TRANSPORT_ACTION_NEXT,
- TRANSPORT_ACTION_REWIND,
- TRANSPORT_ACTION_FORWIND,
- TRANSPORT_ACTION_NO_ACTION
-}TransportAction;
-
-typedef enum {
- TRANSPORT_STATE_PLAYING,
- TRANSPORT_STATE_PAUSED,
- TRANSPORT_STATE_LAUNCHING
-}TransportState;
-
-#define NOT_ACTIVE -1
-#define DBUSMENU_PROPERTY_EMPTY -1
-
-/* DBUS Custom Items */
-#define DBUSMENU_VOLUME_MENUITEM_TYPE "x-canonical-ido-volume-type"
-#define DBUSMENU_VOLUME_MENUITEM_LEVEL "x-canonical-ido-volume-level"
-#define DBUSMENU_VOLUME_MENUITEM_MUTE "x-canonical-ido-volume-mute"
-
-#define DBUSMENU_VOIP_INPUT_MENUITEM_TYPE "x-canonical-ido-voip-input-type"
-#define DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL "x-canonical-ido-voip-input-level"
-#define DBUSMENU_VOIP_INPUT_MENUITEM_MUTE "x-canonical-ido-voip-input-mute"
-
-#define DBUSMENU_MUTE_MENUITEM_TYPE "x-canonical-sound-menu-mute-type"
-#define DBUSMENU_MUTE_MENUITEM_VALUE "x-canonical-sound-menu-mute-value"
-
-#define DBUSMENU_TRANSPORT_MENUITEM_TYPE "x-canonical-sound-menu-player-transport-type"
-#define DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE "x-canonical-sound-menu-player-transport-state"
-#define DBUSMENU_TRANSPORT_MENUITEM_STATE_CHANGE "Transport state change"
-
-#define DBUSMENU_TRACK_SPECIFIC_MENUITEM_TYPE "x-canonical-sound-menu-player-track-specific-type"
-
-#define DBUSMENU_METADATA_MENUITEM_TYPE "x-canonical-sound-menu-player-metadata-type"
-#define DBUSMENU_METADATA_MENUITEM_ARTIST "x-canonical-sound-menu-player-metadata-xesam:artist"
-#define DBUSMENU_METADATA_MENUITEM_TITLE "x-canonical-sound-menu-player-metadata-xesam:title"
-#define DBUSMENU_METADATA_MENUITEM_ALBUM "x-canonical-sound-menu-player-metadata-xesam:album"
-#define DBUSMENU_METADATA_MENUITEM_ARTURL "x-canonical-sound-menu-player-metadata-mpris:artUrl"
-#define DBUSMENU_METADATA_MENUITEM_PLAYER_NAME "x-canonical-sound-menu-player-metadata-player-name"
-#define DBUSMENU_METADATA_MENUITEM_PLAYER_ICON "x-canonical-sound-menu-player-metadata-player-icon"
-#define DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING "x-canonical-sound-menu-player-metadata-player-running"
-#define DBUSMENU_METADATA_MENUITEM_HIDE_TRACK_DETAILS "x-canonical-sound-menu-player-metadata-hide-track-details"
-
-#define DBUSMENU_SCRUB_MENUITEM_TYPE "x-canonical-sound-menu-player-scrub-type"
-#define DBUSMENU_SCRUB_MENUITEM_DURATION "x-canonical-sound-menu-player-scrub-mpris:length"
-#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"
-
-#define DBUSMENU_PLAYLISTS_MENUITEM_TYPE "x-canonical-sound-menu-player-playlists-type"
-#define DBUSMENU_PLAYLISTS_MENUITEM_TITLE "x-canonical-sound-menu-player-playlists-title"
-#define DBUSMENU_PLAYLISTS_MENUITEM_PLAYLISTS "x-canonical-sound-menu-player-playlists-playlists"
-
-#define DBUSMENU_PLAYLIST_MENUITEM_PATH "x-canonical-sound-menu-player-playlist-path"
-
-#endif
diff --git a/src/dbus-shared-names.h b/src/dbus-shared-names.h
deleted file mode 100644
index 2517eb9..0000000
--- a/src/dbus-shared-names.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-A small wrapper utility to load indicators and put them as menu items
-into the gnome-panel using it's applet interface.
-
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
- Ted Gould <ted@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-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 __DBUS_SHARED_NAMES_H__
-#define __DBUS_SHARED_NAMES_H__
-
-#define INDICATOR_SOUND_DBUS_NAME "com.canonical.indicator.sound"
-#define INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH "/com/canonical/indicator/sound/menu"
-#define INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH "/com/canonical/indicator/sound/service"
-#define INDICATOR_SOUND_DBUS_INTERFACE "com.canonical.indicator.sound"
-#define INDICATOR_SOUND_DBUS_VERSION 0
-
-#define INDICATOR_SOUND_SIGNAL_STATE_UPDATE "SoundStateUpdate"
-
-
-#endif /* __DBUS_SHARED_NAMES_H__ */
diff --git a/src/device.c b/src/device.c
deleted file mode 100644
index 84db596..0000000
--- a/src/device.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include <libdbusmenu-glib/menuitem.h>
-
-#include "device.h"
-#include "slider-menu-item.h"
-#include "mute-menu-item.h"
-#include "voip-input-menu-item.h"
-#include "pulseaudio-mgr.h"
-#include "sound-state.h"
-
-typedef struct _DevicePrivate DevicePrivate;
-
-struct _DevicePrivate
-{
- SliderMenuItem* volume_slider_menuitem;
- MuteMenuItem* mute_menuitem;
- VoipInputMenuItem* voip_input_menu_item;
- SoundState current_sound_state;
- SoundServiceDbus* service;
-};
-
-#define DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEVICE_TYPE, DevicePrivate))
-
-/* Prototypes */
-static void device_class_init (DeviceClass *klass);
-static void device_init (Device *self);
-static void device_dispose (GObject *object);
-static void device_finalize (GObject *object);
-
-static SoundState device_get_state_from_volume (Device* self);
-static void device_mute_update (Device* self, gboolean muted);
-
-G_DEFINE_TYPE (Device, device, G_TYPE_OBJECT);
-
-static void
-device_class_init (DeviceClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (DevicePrivate));
-
- gobject_class->dispose = device_dispose;
- gobject_class->finalize = device_finalize;
-}
-
-static void
-device_init (Device *self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- priv->mute_menuitem = NULL;
- priv->volume_slider_menuitem = NULL;
- priv->voip_input_menu_item = NULL;
- priv->current_sound_state = UNAVAILABLE;
- priv->service = NULL;
-
- // Init our menu items.
- priv->mute_menuitem = g_object_new (MUTE_MENU_ITEM_TYPE, NULL);
- priv->voip_input_menu_item = g_object_new (VOIP_INPUT_MENU_ITEM_TYPE, NULL);;
- priv->volume_slider_menuitem = slider_menu_item_new (self);
- mute_menu_item_enable (priv->mute_menuitem, FALSE);
- slider_menu_item_enable (priv->volume_slider_menuitem, FALSE);
-}
-
-static void
-device_dispose (GObject *object)
-{
- G_OBJECT_CLASS (device_parent_class)->dispose (object);
-}
-
-static void
-device_finalize (GObject *object)
-{
- G_OBJECT_CLASS (device_parent_class)->finalize (object);
-}
-
-void
-device_sink_populate (Device* self,
- const pa_sink_info* update)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE(self);
- mute_menu_item_enable (priv->mute_menuitem, TRUE);
- slider_menu_item_populate (priv->volume_slider_menuitem, update);
- SoundState state = device_get_state_from_volume (self);
- if (priv->current_sound_state != state){
- priv->current_sound_state = state;
- sound_service_dbus_update_sound_state (priv->service,
- priv->current_sound_state);
- }
- device_mute_update (self, update->mute);
-}
-
-void
-device_sink_update (Device* self,
- const pa_sink_info* update)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- slider_menu_item_update (priv->volume_slider_menuitem, update);
-
- SoundState state = device_get_state_from_volume (self);
- if (priv->current_sound_state != state){
- priv->current_sound_state = state;
- sound_service_dbus_update_sound_state (priv->service,
- priv->current_sound_state);
- }
-
- device_mute_update (self, update->mute);
-}
-
-gint
-device_get_voip_source_output_index (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- return voip_input_menu_item_get_source_output_index (priv->voip_input_menu_item);
-}
-
-static void
-device_mute_update (Device* self, gboolean muted)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- mute_menu_item_update (priv->mute_menuitem, muted);
- SoundState state = device_get_state_from_volume (self);
-
- if (muted == TRUE){
- state = MUTED;
- }
- // Only send signals if something has changed
- if (priv->current_sound_state != state){
- priv->current_sound_state = state;
- sound_service_dbus_update_sound_state (priv->service, state);
- }
-}
-
-void
-device_ensure_sink_is_unmuted (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- if (mute_menu_item_is_muted (priv->mute_menuitem)){
- pm_update_mute (FALSE);
- }
-}
-
-
-static SoundState
-device_get_state_from_volume (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- GVariant* v = dbusmenu_menuitem_property_get_variant (DBUSMENU_MENUITEM(priv->volume_slider_menuitem),
- DBUSMENU_VOLUME_MENUITEM_LEVEL);
- gdouble volume_percent = g_variant_get_double (v);
-
- return sound_state_get_from_volume ((int)volume_percent);
-}
-
-void
-device_determine_blocking_state (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- if (mute_menu_item_is_muted (priv->mute_menuitem)){
- /**
- We don't want to set the current state to blocking
- as this is a fire and forget event.
- */
- sound_service_dbus_update_sound_state (priv->service,
- BLOCKED);
- }
-}
-
-gint
-device_get_sink_index (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- return slider_menu_item_get_sink_index (priv->volume_slider_menuitem);
-}
-
-gboolean
-device_is_sink_populated (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- return dbusmenu_menuitem_property_get_bool (DBUSMENU_MENUITEM (priv->volume_slider_menuitem),
- DBUSMENU_MENUITEM_PROP_ENABLED);
-}
-
-void
-device_activate_voip_item (Device* self, gint source_output_index, gint client_index)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- if (voip_input_menu_item_is_interested (priv->voip_input_menu_item,
- source_output_index,
- client_index)){
- voip_input_menu_item_enable (priv->voip_input_menu_item, TRUE);
- }
-}
-
-void
-device_deactivate_voip_source (Device* self, gboolean visible)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- visible &= voip_input_menu_item_is_active (priv->voip_input_menu_item);
- voip_input_menu_item_deactivate_source (priv->voip_input_menu_item, visible);
-}
-
-void
-device_deactivate_voip_client (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- voip_input_menu_item_deactivate_voip_client (priv->voip_input_menu_item);
-}
-
-void
-device_sink_deactivated (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- priv->current_sound_state = UNAVAILABLE;
- sound_service_dbus_update_sound_state (priv->service,
- priv->current_sound_state);
- mute_menu_item_enable (priv->mute_menuitem, FALSE);
- slider_menu_item_enable (priv->volume_slider_menuitem, FALSE);
-}
-
-SoundState
-device_get_state (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- return priv->current_sound_state;
-}
-
-void
-device_update_voip_input_source (Device* self, const pa_source_info* update)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- voip_input_menu_item_update (priv->voip_input_menu_item, update);
-}
-
-gboolean
-device_is_voip_source_populated (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- return voip_input_menu_item_is_populated (priv->voip_input_menu_item);
-}
-
-gint device_get_source_index (Device* self)
-{
- DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
- return voip_input_menu_item_get_index (priv->voip_input_menu_item);
-}
-
-Device*
-device_new (SoundServiceDbus* service)
-{
- Device* sink = g_object_new (DEVICE_TYPE, NULL);
- DevicePrivate* priv = DEVICE_GET_PRIVATE (sink);
- priv->service = service;
- sound_service_dbus_build_sound_menu (service,
- mute_menu_item_get_button (priv->mute_menuitem),
- DBUSMENU_MENUITEM (priv->volume_slider_menuitem),
- DBUSMENU_MENUITEM (priv->voip_input_menu_item));
- pm_establish_pulse_connection (sink);
- return sink;
-}
diff --git a/src/device.h b/src/device.h
deleted file mode 100644
index ccaf4ea..0000000
--- a/src/device.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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 __DEVICE_H__
-#define __DEVICE_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include "common-defs.h"
-#include "sound-service-dbus.h"
-
-#include <pulse/pulseaudio.h>
-
-G_BEGIN_DECLS
-
-#define DEVICE_TYPE (device_get_type ())
-#define DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVICE_TYPE, Device))
-#define DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DEVICE_TYPE, DeviceClass))
-#define IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVICE_TYPE))
-#define IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVICE_TYPE))
-#define DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DEVICE_TYPE, DeviceClass))
-
-typedef struct _Device Device;
-typedef struct _DeviceClass DeviceClass;
-
-struct _Device {
- GObject parent;
-};
-
-struct _DeviceClass {
- GObjectClass parent_class;
-};
-
-GType device_get_type (void) G_GNUC_CONST;
-
-/**
- * TODO
- * Refactor this to become a device manager obj basically acting as wrapper for
- * the communication between pulseaudio-mgr and the individual items.
- * First steps collapse slider/volume related stuff into slider-menu-item.
- */
-
-// Sink related
-void device_sink_populate (Device* sink, const pa_sink_info* update);
-void device_sink_update (Device* sink, const pa_sink_info* update);
-gboolean device_is_sink_populated (Device* sink);
-gint device_get_sink_index (Device* self);
-void device_sink_deactivated (Device* self);
-void device_update_mute (Device* self, gboolean mute_update);
-void device_ensure_sink_is_unmuted (Device* self);
-
-// source and sinkinput/client related for VOIP functionality
-void device_update_voip_input_source (Device* sink, const pa_source_info* update);
-void device_activate_voip_item (Device* sink, gint source_output_index, gint client_index);
-gint device_get_voip_source_output_index (Device* sink);
-gboolean device_is_voip_source_populated (Device* sink);
-gint device_get_source_index (Device* self);
-void device_determine_blocking_state (Device* self);
-void device_deactivate_voip_source (Device* self, gboolean visible);
-void device_deactivate_voip_client (Device* self);
-SoundState device_get_state (Device* self);
-
-Device* device_new (SoundServiceDbus* service);
-
-G_END_DECLS
-
-#endif
diff --git a/src/fetch-file.vala b/src/fetch-file.vala
deleted file mode 100644
index e94afef..0000000
--- a/src/fetch-file.vala
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2010 Canonical, Ltd.
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License
- * version 3.0 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3.0 for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors
- * Gordon Allott <gord.allott@canonical.com>
- * Conor Curran <conor.curran@canonical.com>
- */
-
-public class FetchFile : Object
-{
- /* public variables */
- public string uri {get; construct;}
- public string intended_property {get; construct;}
-
- /* private variables */
- private DataInputStream stream;
- private File? file;
- private ByteArray data;
-
- /* public signals */
- public signal void failed ();
- public signal void completed (ByteArray data, string property);
-
- public FetchFile (string uri, string prop)
- {
- Object (uri: uri, intended_property: prop);
- }
-
- construct
- {
- this.file = File.new_for_uri(this.uri);
- this.data = new ByteArray ();
- }
-
- public async void fetch_data ()
- {
- try {
- this.stream = new DataInputStream(this.file.read(null));
- this.stream.set_byte_order (DataStreamByteOrder.LITTLE_ENDIAN);
- } catch (GLib.Error e) {
- this.failed ();
- }
- this.read_something_async ();
- }
-
- private async void read_something_async ()
- {
- ssize_t size = 1024;
- uint8[] buffer = new uint8[size];
-
- ssize_t bufsize = 1;
- do {
- try {
- bufsize = yield this.stream.read_async (buffer, GLib.Priority.DEFAULT, null);
- if (bufsize < 1) { break;}
-
- if (bufsize != size)
- {
- uint8[] cpybuf = new uint8[bufsize];
- Memory.copy (cpybuf, buffer, bufsize);
- this.data.append (cpybuf);
- }
- else
- {
- this.data.append (buffer);
- }
- } catch (Error e) {
- this.failed ();
- }
- } while (bufsize > 0);
- this.completed (this.data, this.intended_property);
- }
-}
diff --git a/src/indicator-sound.c b/src/indicator-sound.c
deleted file mode 100644
index d21d722..0000000
--- a/src/indicator-sound.c
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
-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 "config.h"
-
-#include <math.h>
-#include <glib.h>
-#include <glib-object.h>
-#include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-#include <libdbusmenu-gtk/menu.h>
-#include <libido/idoscalemenuitem.h>
-
-#include <gio/gio.h>
-
-#include "indicator-sound.h"
-#include "transport-widget.h"
-#include "metadata-widget.h"
-#include "volume-widget.h"
-#include "voip-input-widget.h"
-#include "dbus-shared-names.h"
-#include "sound-state-manager.h"
-#include "mute-widget.h"
-
-#include "gen-sound-service.xml.h"
-#include "common-defs.h"
-
-typedef struct _IndicatorSoundPrivate IndicatorSoundPrivate;
-
-struct _IndicatorSoundPrivate
-{
- GtkWidget* volume_widget;
- GtkWidget* voip_widget;
- MuteWidget *mute_widget;
- GList* transport_widgets_list;
- GDBusProxy *dbus_proxy;
- SoundStateManager* state_manager;
- gchar *accessible_desc;
- GSettings *settings;
-};
-
-#define INDICATOR_SOUND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SOUND_TYPE, IndicatorSoundPrivate))
-
-#define SOUND_INDICATOR_GSETTINGS_SCHEMA_ID "com.canonical.indicator.sound"
-
-// GObject Boiler plate
-INDICATOR_SET_VERSION
-INDICATOR_SET_TYPE(INDICATOR_SOUND_TYPE)
-
-// GObject Boiler plate
-static void indicator_sound_class_init (IndicatorSoundClass *klass);
-static void indicator_sound_init (IndicatorSound *self);
-static void indicator_sound_dispose (GObject *object);
-static void indicator_sound_finalize (GObject *object);
-G_DEFINE_TYPE (IndicatorSound, indicator_sound, INDICATOR_OBJECT_TYPE);
-
-//GTK+ items
-static GtkLabel * get_label (IndicatorObject * io);
-static GtkImage * get_icon (IndicatorObject * io);
-static GtkMenu * get_menu (IndicatorObject * io);
-static const gchar * get_accessible_desc (IndicatorObject * io);
-static const gchar * get_name_hint (IndicatorObject * io);
-static void indicator_sound_scroll (IndicatorObject * io,
- IndicatorObjectEntry * entry, gint delta,
- IndicatorScrollDirection direction);
-static void indicator_sound_middle_click (IndicatorObject * io,
- IndicatorObjectEntry * entry,
- guint time, gpointer data);
-
-//key/moust event handlers
-static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data);
-static gboolean key_release_cb(GtkWidget* widget, GdkEventKey* event, gpointer data);
-
-//custom widget realisation methods
-static gboolean new_volume_slider_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data);
-static gboolean new_voip_slider_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data);
-static gboolean new_transport_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data);
-static gboolean new_metadata_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data);
-static gboolean new_mute_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data);
-
-// DBUS communication
-static GDBusNodeInfo *node_info = NULL;
-static GDBusInterfaceInfo *interface_info = NULL;
-static void create_connection_to_service (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data);
-static void connection_changed (IndicatorServiceManager * sm,
- gboolean connected,
- gpointer userdata);
-
-// Visiblity
-static void settings_init (IndicatorSound * self);
-
-
-static void
-indicator_sound_class_init (IndicatorSoundClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = indicator_sound_dispose;
- object_class->finalize = indicator_sound_finalize;
-
- IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS(klass);
-
- g_type_class_add_private (klass, sizeof (IndicatorSoundPrivate));
-
- io_class->get_label = get_label;
- io_class->get_image = get_icon;
- io_class->get_menu = get_menu;
- io_class->get_accessible_desc = get_accessible_desc;
- io_class->get_name_hint = get_name_hint;
- io_class->entry_scrolled = indicator_sound_scroll;
- io_class->secondary_activate = indicator_sound_middle_click;
-}
-
-static void
-indicator_sound_init (IndicatorSound *self)
-{
- self->service = NULL;
- self->service = indicator_service_manager_new_version(INDICATOR_SOUND_DBUS_NAME,
- INDICATOR_SOUND_DBUS_VERSION);
-
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
- priv->volume_widget = NULL;
- priv->voip_widget = NULL;
- priv->mute_widget = NULL;
- priv->dbus_proxy = NULL;
- GList* t_list = NULL;
- priv->transport_widgets_list = t_list;
- priv->state_manager = g_object_new (SOUND_TYPE_STATE_MANAGER, NULL);
- priv->accessible_desc = NULL;
- priv->settings = NULL;
-
- settings_init (self);
-
- g_signal_connect ( G_OBJECT(self->service),
- INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
- G_CALLBACK(connection_changed), self );
-}
-
-static void
-indicator_sound_dispose (GObject *object)
-{
- IndicatorSound * self = INDICATOR_SOUND(object);
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
-
- if (priv->settings != NULL) {
- g_object_unref (G_OBJECT(priv->settings));
- priv->settings = NULL;
- }
-
- if (self->service != NULL) {
- g_object_unref(G_OBJECT(self->service));
- self->service = NULL;
- }
- g_list_free (priv->transport_widgets_list);
-
- G_OBJECT_CLASS (indicator_sound_parent_class)->dispose (object);
-}
-
-static void
-indicator_sound_finalize (GObject *object)
-{
- IndicatorSound * self = INDICATOR_SOUND(object);
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
-
- if (priv->accessible_desc) {
- g_free (priv->accessible_desc);
- priv->accessible_desc = NULL;
- }
-
- G_OBJECT_CLASS (indicator_sound_parent_class)->finalize (object);
-}
-
-static GtkLabel *
-get_label (IndicatorObject * io)
-{
- return NULL;
-}
-
-static GtkImage *
-get_icon (IndicatorObject * io)
-{
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
- gtk_widget_show( GTK_WIDGET(sound_state_manager_get_current_icon (priv->state_manager)) );
- return sound_state_manager_get_current_icon (priv->state_manager);
-}
-
-/* Indicator based function to get the menu for the whole
- applet. This starts up asking for the parts of the menu
- from the various services. */
-static GtkMenu *
-get_menu (IndicatorObject * io)
-{
- DbusmenuGtkMenu* menu = dbusmenu_gtkmenu_new(INDICATOR_SOUND_DBUS_NAME,
- INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH);
-
- DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(menu);
- g_object_set_data (G_OBJECT (client), "indicator", io);
- dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
- DBUSMENU_VOLUME_MENUITEM_TYPE,
- new_volume_slider_widget);
- dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
- DBUSMENU_VOIP_INPUT_MENUITEM_TYPE,
- new_voip_slider_widget);
- dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
- DBUSMENU_TRANSPORT_MENUITEM_TYPE,
- new_transport_widget);
- dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
- DBUSMENU_METADATA_MENUITEM_TYPE,
- new_metadata_widget);
- dbusmenu_client_add_type_handler (DBUSMENU_CLIENT(client),
- DBUSMENU_MUTE_MENUITEM_TYPE,
- new_mute_widget);
- // Note: Not ideal but all key handling needs to be managed here and then
- // delegated to the appropriate widget.
- g_signal_connect (menu, "key-press-event", G_CALLBACK(key_press_cb), io);
- g_signal_connect (menu, "key-release-event", G_CALLBACK(key_release_cb), io);
-
- return GTK_MENU(menu);
-}
-
-static const gchar *
-get_accessible_desc (IndicatorObject * io)
-{
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(io);
- return priv->accessible_desc;
-}
-
-static const gchar *get_name_hint (IndicatorObject * io)
-{
- return PACKAGE_NAME;
-}
-
-static void
-connection_changed (IndicatorServiceManager * sm,
- gboolean connected,
- gpointer user_data)
-{
- IndicatorSound* indicator = INDICATOR_SOUND(user_data);
- g_return_if_fail ( IS_INDICATOR_SOUND (indicator) );
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE (indicator);
- GError *error = NULL;
-
- if (connected == FALSE){
- sound_state_manager_deal_with_disconnect (priv->state_manager);
- return;
- //TODO: Gracefully handle disconnection
- // do a timeout to wait for reconnection
- // for 5 seconds and then if no connection message
- // is received put the state at 'sink not available'
- }
- // If the proxy is not null and connected is true => its a reconnect,
- // we don't need to anything, gdbus takes care of the rest - bless.
- // just fetch the state.
- if (priv->dbus_proxy != NULL){
- g_dbus_proxy_call ( priv->dbus_proxy,
- "GetSoundState",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- (GAsyncReadyCallback)sound_state_manager_get_state_cb,
- priv->state_manager);
- return;
- }
-
- if ( node_info == NULL ){
- node_info = g_dbus_node_info_new_for_xml ( _sound_service,
- &error );
- if (error != NULL) {
- g_critical ( "Failed to get create interface info from xml: %s",
- error->message );
- g_error_free(error);
- return;
- }
- }
-
- if (interface_info == NULL) {
- interface_info = g_dbus_node_info_lookup_interface (node_info,
- INDICATOR_SOUND_DBUS_INTERFACE);
- if (interface_info == NULL) {
- g_critical ("Unable to find interface '" INDICATOR_SOUND_DBUS_INTERFACE "'");
- }
- }
-
- g_dbus_proxy_new_for_bus( G_BUS_TYPE_SESSION,
- G_DBUS_PROXY_FLAGS_NONE,
- interface_info,
- INDICATOR_SOUND_DBUS_NAME,
- INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
- INDICATOR_SOUND_DBUS_INTERFACE,
- NULL,
- create_connection_to_service,
- indicator );
-}
-
-static void create_connection_to_service (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- IndicatorSound *self = INDICATOR_SOUND(user_data);
- GError *error = NULL;
-
- g_return_if_fail( IS_INDICATOR_SOUND(self) );
-
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
-
- priv->dbus_proxy = g_dbus_proxy_new_finish(res, &error);
-
- if (error != NULL) {
- g_critical ("Failed to get dbus proxy: %s", error->message);
- g_error_free(error);
- return;
- }
- sound_state_manager_connect_to_dbus (priv->state_manager,
- priv->dbus_proxy);
-
-}
-
-static gboolean
-new_transport_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data)
-{
- g_debug("indicator-sound: new_transport_bar() called ");
-
- GtkWidget* bar = NULL;
- IndicatorObject *io = NULL;
-
- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
-
- bar = transport_widget_new(newitem);
- io = g_object_get_data (G_OBJECT (client), "indicator");
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
- priv->transport_widgets_list = g_list_append ( priv->transport_widgets_list, bar );
-
- GtkMenuItem *menu_transport_bar = GTK_MENU_ITEM(bar);
-
- gtk_widget_show_all(bar);
- dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client),
- newitem,
- menu_transport_bar,
- parent);
- return TRUE;
-}
-
-static gboolean
-new_metadata_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data)
-{
- g_debug("indicator-sound: new_metadata_widget");
-
- GtkWidget* metadata = NULL;
-
- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
-
-
- metadata = metadata_widget_new (newitem);
-
- g_debug ("%s (\"%s\")", __func__,
- dbusmenu_menuitem_property_get(newitem, DBUSMENU_METADATA_MENUITEM_PLAYER_NAME));
-
- GtkMenuItem *menu_metadata_widget = GTK_MENU_ITEM(metadata);
-
- gtk_widget_show_all(metadata);
- dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client),
- newitem,
- menu_metadata_widget,
- parent);
- return TRUE;
-}
-
-static gboolean
-new_volume_slider_widget(DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data)
-{
- g_debug("indicator-sound: new_volume_slider_widget");
-
- GtkWidget* volume_widget = NULL;
- IndicatorObject *io = NULL;
-
- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
-
- io = g_object_get_data (G_OBJECT (client), "indicator");
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
-
- if (priv->volume_widget != NULL){
- volume_widget_tidy_up (priv->volume_widget);
- gtk_widget_destroy (priv->volume_widget);
- priv->volume_widget = NULL;
- }
- volume_widget = volume_widget_new (newitem, io);
- priv->volume_widget = volume_widget;
- // Don't forget to set the accessible desc.
- update_accessible_desc (io);
-
-
- GtkWidget* ido_slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
-
- gtk_widget_show_all(ido_slider_widget);
- // register the style callback on this widget with state manager's style change
- // handler (needs to remake the blocking animation for each style).
- g_signal_connect (ido_slider_widget, "style-set",
- G_CALLBACK(sound_state_manager_style_changed_cb),
- priv->state_manager);
-
- GtkMenuItem *menu_volume_item = GTK_MENU_ITEM(ido_slider_widget);
- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
- newitem,
- menu_volume_item,
- parent);
- return TRUE;
-}
-/**
- * new_voip_slider_widget
- * Create the voip menu item widget, must of the time this widget will be hidden.
- * @param newitem
- * @param parent
- * @param client
- * @param user_data
- * @return
- */
-static gboolean
-new_voip_slider_widget (DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data)
-{
- g_debug("indicator-sound: new_voip_slider_widget");
- GtkWidget* voip_widget = NULL;
- IndicatorObject *io = NULL;
-
- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
-
- io = g_object_get_data (G_OBJECT (client), "indicator");
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
-
- if (priv->voip_widget != NULL){
- voip_input_widget_tidy_up (priv->voip_widget);
- gtk_widget_destroy (priv->voip_widget);
- priv->voip_widget = NULL;
- }
-
- voip_widget = voip_input_widget_new (newitem);
- priv->voip_widget = voip_widget;
-
- GtkWidget* ido_slider_widget = voip_input_widget_get_ido_slider(VOIP_INPUT_WIDGET(voip_widget));
-
- gtk_widget_show_all(ido_slider_widget);
-
- GtkMenuItem *menu_volume_item = GTK_MENU_ITEM(ido_slider_widget);
- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
- newitem,
- menu_volume_item,
- parent);
- return TRUE;
-}
-
-static gboolean
-new_mute_widget(DbusmenuMenuitem * newitem,
- DbusmenuMenuitem * parent,
- DbusmenuClient * client,
- gpointer user_data)
-{
- IndicatorObject *io = NULL;
-
- g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
- g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
-
- io = g_object_get_data (G_OBJECT (client), "indicator");
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
-
- if (priv->mute_widget != NULL){
- g_object_unref (priv->mute_widget);
- priv->mute_widget = NULL;
- }
-
- priv->mute_widget = mute_widget_new(newitem);
- GtkMenuItem *item = mute_widget_get_menu_item (priv->mute_widget);
-
- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client),
- newitem,
- item,
- parent);
-
- return TRUE;
-}
-
-/*******************************************************************/
-//UI callbacks
-/******************************************************************/
-
-static GtkWidget *
-get_current_item (GtkContainer * container)
-{
- GList *children = gtk_container_get_children (container);
- GList *iter;
- GtkWidget *rv = NULL;
-
- /* Suprisingly, GTK+ doesn't really let us query "what is the currently
- selected item?". But it does note it internally by prelighting the
- widget, so we watch for that. */
- for (iter = children; iter; iter = iter->next) {
- if (gtk_widget_get_state (GTK_WIDGET (iter->data)) & GTK_STATE_PRELIGHT) {
- rv = GTK_WIDGET (iter->data);
- break;
- }
- }
-
- return rv;
-}
-
-/**
-key_press_cb:
-**/
-static gboolean
-key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data)
-{
- gboolean digested = FALSE;
-
- g_return_val_if_fail(IS_INDICATOR_SOUND(data), FALSE);
-
- IndicatorSound *indicator = INDICATOR_SOUND (data);
-
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(indicator);
- GtkWidget *menuitem;
- menuitem = get_current_item (GTK_CONTAINER (widget));
-
- if (IDO_IS_SCALE_MENU_ITEM(menuitem) == TRUE){
- gdouble current_value = 0;
- gdouble new_value = 0;
- const gdouble five_percent = 5;
- gboolean is_voip_slider = FALSE;
-
- if (g_ascii_strcasecmp (ido_scale_menu_item_get_primary_label (IDO_SCALE_MENU_ITEM(menuitem)), "VOLUME") == 0) {
- g_debug ("vOLUME SLIDER KEY PRESS");
- GtkWidget* slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
- GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)slider_widget);
- GtkRange* range = (GtkRange*)slider;
- g_return_val_if_fail(GTK_IS_RANGE(range), FALSE);
- current_value = gtk_range_get_value(range);
- new_value = current_value;
- }
- else if (g_ascii_strcasecmp (ido_scale_menu_item_get_primary_label (IDO_SCALE_MENU_ITEM(menuitem)), "VOIP") == 0) {
- g_debug ("VOIP SLIDER KEY PRESS");
- GtkWidget* slider_widget = voip_input_widget_get_ido_slider(VOIP_INPUT_WIDGET(priv->voip_widget));
- GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)slider_widget);
- GtkRange* range = (GtkRange*)slider;
- g_return_val_if_fail(GTK_IS_RANGE(range), FALSE);
- current_value = gtk_range_get_value(range);
- new_value = current_value;
- is_voip_slider = TRUE;
- }
-
- switch (event->keyval) {
- case GDK_KEY_Right:
- digested = TRUE;
- new_value = current_value + five_percent;
- break;
- case GDK_KEY_Left:
- digested = TRUE;
- new_value = current_value - five_percent;
- break;
- case GDK_KEY_plus:
- digested = TRUE;
- new_value = current_value + five_percent;
- break;
- case GDK_KEY_minus:
- digested = TRUE;
- new_value = current_value - five_percent;
- break;
- default:
- break;
- }
- new_value = CLAMP(new_value, 0, 100);
- if (new_value != current_value){
- if (is_voip_slider == TRUE){
- voip_input_widget_update (VOIP_INPUT_WIDGET(priv->voip_widget), new_value);
- }
- else{
- volume_widget_update (VOLUME_WIDGET(priv->volume_widget), new_value, "keypress-update");
- }
- }
- }
- else if (IS_TRANSPORT_WIDGET(menuitem) == TRUE) {
- TransportWidget* transport_widget = NULL;
- GList* elem;
-
- for ( elem = priv->transport_widgets_list; elem; elem = elem->next ) {
- transport_widget = TRANSPORT_WIDGET ( elem->data );
- if ( transport_widget_is_selected( transport_widget ) )
- break;
- }
-
- switch (event->keyval) {
- case GDK_KEY_Right:
- transport_widget_react_to_key_press_event ( transport_widget,
- TRANSPORT_ACTION_NEXT );
- digested = TRUE;
- break;
- case GDK_KEY_Left:
- transport_widget_react_to_key_press_event ( transport_widget,
- TRANSPORT_ACTION_PREVIOUS );
- digested = TRUE;
- break;
- case GDK_KEY_space:
- transport_widget_react_to_key_press_event ( transport_widget,
- TRANSPORT_ACTION_PLAY_PAUSE );
- digested = TRUE;
- break;
- case GDK_KEY_Up:
- case GDK_KEY_Down:
- digested = FALSE;
- break;
- default:
- break;
- }
- }
- return digested;
-}
-
-
-/**
-key_release_cb:
-**/
-static gboolean
-key_release_cb(GtkWidget* widget, GdkEventKey* event, gpointer data)
-{
- gboolean digested = FALSE;
-
- g_return_val_if_fail(IS_INDICATOR_SOUND(data), FALSE);
-
- IndicatorSound *indicator = INDICATOR_SOUND (data);
-
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(indicator);
-
- GtkWidget *menuitem;
-
- menuitem = get_current_item (GTK_CONTAINER (widget));
- if (IS_TRANSPORT_WIDGET(menuitem) == TRUE) {
- TransportWidget* transport_widget = NULL;
- GList* elem;
-
- for(elem = priv->transport_widgets_list; elem; elem = elem->next) {
- transport_widget = TRANSPORT_WIDGET (elem->data);
- if ( transport_widget_is_selected( transport_widget ) )
- break;
- }
-
- switch (event->keyval) {
- case GDK_KEY_Right:
- transport_widget_react_to_key_release_event ( transport_widget,
- TRANSPORT_ACTION_NEXT );
- digested = TRUE;
- break;
- case GDK_KEY_Left:
- transport_widget_react_to_key_release_event ( transport_widget,
- TRANSPORT_ACTION_PREVIOUS );
- digested = TRUE;
- break;
- case GDK_KEY_space:
- transport_widget_react_to_key_release_event ( transport_widget,
- TRANSPORT_ACTION_PLAY_PAUSE );
- digested = TRUE;
- break;
- case GDK_KEY_Up:
- case GDK_KEY_Down:
- digested = FALSE;
- break;
- default:
- break;
- }
- }
- return digested;
-}
-
-static void
-indicator_sound_scroll (IndicatorObject * io, IndicatorObjectEntry * entry,
- gint delta, IndicatorScrollDirection direction)
-{
- //g_debug("indicator-sound-scroll - current slider value");
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(INDICATOR_SOUND (io));
- SoundState current_state = sound_state_manager_get_current_state (priv->state_manager);
-
- if (current_state == UNAVAILABLE || current_state == MUTED)
- return;
-
- GtkWidget* slider_widget = volume_widget_get_ido_slider(VOLUME_WIDGET(priv->volume_widget));
- GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)slider_widget);
- GtkRange* range = (GtkRange*)slider;
- g_return_if_fail(GTK_IS_RANGE(range));
-
- gdouble value = gtk_range_get_value(range);
- GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (slider));
- //g_debug("indicator-sound-scroll - current slider value %f", value);
- if (direction == INDICATOR_OBJECT_SCROLL_UP) {
- value += gtk_adjustment_get_step_increment (adj);
- } else {
- value -= gtk_adjustment_get_step_increment (adj);
- }
- //g_debug("indicator-sound-scroll - update slider with value %f", value);
- volume_widget_update(VOLUME_WIDGET(priv->volume_widget), value, "scroll updates");
-
- if (!gtk_widget_get_mapped(GTK_WIDGET (entry->menu)))
- sound_state_manager_show_notification (priv->state_manager, value);
-}
-
-static void
-indicator_sound_middle_click (IndicatorObject * io, IndicatorObjectEntry * entry,
- guint time, gpointer data)
-{
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(io);
- g_return_if_fail (priv);
-
- mute_widget_toggle(priv->mute_widget);
-}
-
-void
-update_accessible_desc (IndicatorObject * io)
-{
- GList *entries = indicator_object_get_entries(io);
- if (!entries)
- return;
- IndicatorObjectEntry * entry = (IndicatorObjectEntry *)entries->data;
-
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(io);
- gchar *old_desc = priv->accessible_desc;
-
- if (priv->volume_widget) {
- priv->accessible_desc = g_strdup_printf(_("Volume (%'.0f%%)"),
- volume_widget_get_current_volume (priv->volume_widget));
- }
- else {
- priv->accessible_desc = NULL;
- }
-
- entry->accessible_desc = priv->accessible_desc;
- g_free (old_desc);
- g_signal_emit(G_OBJECT(io),
- INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID,
- 0,
- entry,
- TRUE);
- g_list_free(entries);
-}
-
-/***
-****
-***/
-
-#define VISIBLE_KEY "visible"
-
-static void
-on_visible_changed (GSettings * settings, gchar * key, gpointer user_data)
-{
- g_return_if_fail (!g_strcmp0 (key, VISIBLE_KEY));
-
- IndicatorObject * io = INDICATOR_OBJECT(user_data);
- const gboolean visible = g_settings_get_boolean (settings, key);
- indicator_object_set_visible (io, visible);
- if (visible)
- update_accessible_desc (io); // requires an entry
-}
-
-static void
-settings_init (IndicatorSound *self)
-{
- const char * schema = SOUND_INDICATOR_GSETTINGS_SCHEMA_ID;
-
- gint i;
- gboolean schema_exists = FALSE;
- const char * const * schemas = g_settings_list_schemas ();
- for (i=0; !schema_exists && schemas && schemas[i]; i++)
- if (!g_strcmp0 (schema, schemas[i]))
- schema_exists = TRUE;
-
- IndicatorSoundPrivate* priv = INDICATOR_SOUND_GET_PRIVATE(self);
- if (schema_exists) {
- priv->settings = g_settings_new (schema);
- } else {
- priv->settings = NULL;
- }
-
- if (priv->settings != NULL) {
- g_signal_connect (G_OBJECT(priv->settings), "changed::" VISIBLE_KEY,
- G_CALLBACK(on_visible_changed), self);
- const gboolean b = g_settings_get_boolean (priv->settings, VISIBLE_KEY);
- g_object_set (G_OBJECT(self),
- "indicator-object-default-visibility", b,
- NULL);
- }
-}
diff --git a/src/indicator-sound.h b/src/indicator-sound.h
deleted file mode 100644
index c945efa..0000000
--- a/src/indicator-sound.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __INCLUDE_INDICATOR_SOUND_H__
-#define __INCLUDE_INDICATOR_SOUND_H__
-
-/*
-A small wrapper utility to load indicators and put them as menu items
-into the gnome-panel using it's applet interface.
-
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curra@canonical.com>
- Ted Gould <ted@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-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 "config.h"
-
-#include <libindicator/indicator.h>
-#include <libindicator/indicator-object.h>
-#include <libindicator/indicator-service-manager.h>
-
-#define INDICATOR_SOUND_TYPE (indicator_sound_get_type ())
-#define INDICATOR_SOUND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SOUND_TYPE, IndicatorSound))
-#define INDICATOR_SOUND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SOUND_TYPE, IndicatorSoundClass))
-#define IS_INDICATOR_SOUND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SOUND_TYPE))
-#define IS_INDICATOR_SOUND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SOUND_TYPE))
-#define INDICATOR_SOUND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SOUND_TYPE, IndicatorSoundClass))
-
-typedef struct _IndicatorSound IndicatorSound;
-typedef struct _IndicatorSoundClass IndicatorSoundClass;
-
-//GObject class struct
-struct _IndicatorSoundClass {
- IndicatorObjectClass parent_class;
-};
-
-//GObject instance struct
-struct _IndicatorSound {
- IndicatorObject parent;
- IndicatorServiceManager *service;
-};
-
-// GObject Boiler plate
-GType indicator_sound_get_type (void);
-
-// Update the accessible description
-void update_accessible_desc (IndicatorObject * io);
-
-#endif
diff --git a/src/main.vala b/src/main.vala
new file mode 100644
index 0000000..1ec7d2c
--- /dev/null
+++ b/src/main.vala
@@ -0,0 +1,5 @@
+
+static int main (string[] args) {
+ var service = new IndicatorSound.Service ();
+ return service.run ();
+}
diff --git a/src/media-player-list.vala b/src/media-player-list.vala
new file mode 100644
index 0000000..6d37b4d
--- /dev/null
+++ b/src/media-player-list.vala
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Lars Uebernickel <lars.uebernickel@canonical.com>
+ */
+
+/**
+ * MediaPlayerList is a list of media players that should appear in the sound menu. Its main responsibility is
+ * to listen for MPRIS players on the bus and attach them to the corresponding %Player objects.
+ */
+public class MediaPlayerList {
+
+ public MediaPlayerList () {
+ this._players = new HashTable<string, MediaPlayer> (str_hash, str_equal);
+
+ this.mpris_watcher = new Mpris2Watcher ();
+ this.mpris_watcher.client_appeared.connect (this.player_appeared);
+ this.mpris_watcher.client_disappeared.connect (this.player_disappeared);
+ }
+
+ /* only valid while the list is not changed */
+ public class Iterator {
+ HashTableIter<string, MediaPlayer> iter;
+
+ public Iterator (MediaPlayerList list) {
+ this.iter = HashTableIter<string, MediaPlayer> (list._players);
+ }
+
+ public MediaPlayer? next_value () {
+ MediaPlayer? player;
+
+ if (this.iter.next (null, out player))
+ return player;
+ else
+ return null;
+ }
+ }
+
+ public Iterator iterator () {
+ return new Iterator (this);
+ }
+
+ /**
+ * Adds the player associated with @desktop_id. Does nothing if such a player already exists.
+ */
+ public MediaPlayer? insert (string desktop_id) {
+ var id = desktop_id.has_suffix (".desktop") ? desktop_id : desktop_id + ".desktop";
+ MediaPlayer? player = this._players.lookup (id);
+
+ if (player == null) {
+ var appinfo = new DesktopAppInfo (id);
+ if (appinfo == null) {
+ warning ("unable to find application '%s'", id);
+ return null;
+ }
+
+ player = new MediaPlayer (appinfo);
+ this._players.insert (player.id, player);
+ this.player_added (player);
+ }
+
+ return player;
+ }
+
+ /**
+ * Removes the player associated with @desktop_id, unless it is currently running.
+ */
+ public void remove (string desktop_id) {
+ MediaPlayer? player = this._players.lookup (desktop_id);
+
+ if (player != null && !player.is_running) {
+ this._players.remove (desktop_id);
+ this.player_removed (player);
+ }
+ }
+
+ /**
+ * Synchronizes the player list with @desktop_ids. After this call, this list will only contain the players
+ * in @desktop_ids. Players that were running but are not in @desktop_ids will remain in the list.
+ */
+ public void sync (string[] desktop_ids) {
+
+ /* hash desktop_ids for faster lookup */
+ var hash = new HashTable<string, unowned string> (str_hash, str_equal);
+ foreach (var id in desktop_ids)
+ hash.add (id);
+
+ /* remove players that are not desktop_ids */
+ foreach (var id in this._players.get_keys ()) {
+ if (!hash.contains (id))
+ this.remove (id);
+ }
+
+ /* insert all players (insert() takes care of not adding a player twice */
+ foreach (var id in desktop_ids)
+ this.insert (id);
+ }
+
+ public signal void player_added (MediaPlayer player);
+ public signal void player_removed (MediaPlayer player);
+
+ HashTable<string, MediaPlayer> _players;
+ Mpris2Watcher mpris_watcher;
+
+ void player_appeared (string desktop_id, string dbus_name, bool use_playlists) {
+ var player = this.insert (desktop_id);
+ if (player != null)
+ player.attach (dbus_name);
+ }
+
+ void player_disappeared (string dbus_name) {
+ MediaPlayer? player = this._players.find ( (name, player) => {
+ return player.dbus_name == dbus_name;
+ });
+
+ if (player != null)
+ player.detach ();
+ }
+}
diff --git a/src/media-player.vala b/src/media-player.vala
new file mode 100644
index 0000000..5b59efb
--- /dev/null
+++ b/src/media-player.vala
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Lars Uebernickel <lars.uebernickel@canonical.com>
+ */
+
+/**
+ * MediaPlayer represents an MRPIS-capable media player.
+ */
+public class MediaPlayer: Object {
+
+ public MediaPlayer (DesktopAppInfo appinfo) {
+ this.appinfo = appinfo;
+ }
+
+ /** Desktop id of the player */
+ public string id {
+ get {
+ return this.appinfo.get_id ();
+ }
+ }
+
+ /** Display name of the player */
+ public string name {
+ get {
+ return this.appinfo.get_name ();
+ }
+ }
+
+ /** Application icon of the player */
+ public Icon icon {
+ get {
+ return this.appinfo.get_icon ();
+ }
+ }
+
+ /**
+ * True if an instance of the player is currently running.
+ *
+ * See also: attach(), detach()
+ */
+ public bool is_running {
+ get {
+ return this.proxy != null;
+ }
+ }
+
+ /** Name of the player on the bus, if an instance is currently running */
+ public string dbus_name {
+ get {
+ return this._dbus_name;
+ }
+ }
+
+ public string state {
+ get; private set; default = "Paused";
+ }
+
+ public class Track : Object {
+ public string artist { get; construct; }
+ public string title { get; construct; }
+ public string album { get; construct; }
+ public string art_url { get; construct; }
+
+ public Track (string artist, string title, string album, string art_url) {
+ Object (artist: artist, title: title, album: album, art_url: art_url);
+ }
+ }
+
+ public Track current_track {
+ get; set;
+ }
+
+ /**
+ * Attach this object to a process of the associated media player. The player must own @dbus_name and
+ * implement the org.mpris.MediaPlayer2.Player interface.
+ *
+ * Only one player can be attached at any given time. Use detach() to detach a player.
+ *
+ * This method does not block. If it is successful, "is-running" will be set to %TRUE.
+ */
+ public void attach (string dbus_name) {
+ return_if_fail (this._dbus_name == null && this.proxy == null);
+
+ this._dbus_name = dbus_name;
+ Bus.get_proxy.begin<MprisPlayer> (BusType.SESSION, dbus_name, "/org/mpris/MediaPlayer2",
+ DBusProxyFlags.GET_INVALIDATED_PROPERTIES, null, got_proxy);
+ }
+
+ /**
+ * Detach this object from a process running the associated media player.
+ *
+ * See also: attach()
+ */
+ public void detach () {
+ this.proxy = null;
+ this._dbus_name = null;
+ this.notify_property ("is-running");
+ this.state = "Paused";
+ this.current_track = null;
+ }
+
+ /**
+ * Launch the associated media player.
+ *
+ * Note: this will _not_ call attach(), because it doesn't know on which dbus-name the player will appear.
+ * Use attach() to attach this object to a running instance of the player.
+ */
+ public void launch () {
+ try {
+ this.appinfo.launch (null, null);
+ }
+ catch (Error e) {
+ warning ("unable to launch %s: %s", appinfo.get_name (), e.message);
+ }
+ this.state = "Launching";
+ }
+
+ /**
+ * Toggles playing status.
+ */
+ public void play_pause () {
+ if (this.proxy != null)
+ this.proxy.PlayPause.begin ();
+ }
+
+ /**
+ * Skips to the next track.
+ */
+ public void next () {
+ if (this.proxy != null)
+ this.proxy.Next.begin ();
+ }
+
+ /**
+ * Skips to the previous track.
+ */
+ public void previous () {
+ if (this.proxy != null)
+ this.proxy.Previous.begin ();
+ }
+
+ DesktopAppInfo appinfo;
+ MprisPlayer? proxy;
+ string _dbus_name;
+
+ void got_proxy (Object? obj, AsyncResult res) {
+ try {
+ this.proxy = Bus.get_proxy.end (res);
+
+ /* Connecting to GDBusProxy's "g-properties-changed" signal here, because vala's dbus objects don't
+ * emit notify signals */
+ var gproxy = this.proxy as DBusProxy;
+ gproxy.g_properties_changed.connect (this.proxy_properties_changed);
+
+ this.notify_property ("is-running");
+ this.state = this.proxy.PlaybackStatus;
+ this.update_current_track (gproxy.get_cached_property ("Metadata"));
+ }
+ catch (Error e) {
+ this._dbus_name = null;
+ warning ("unable to attach to media player: %s", e.message);
+ }
+ }
+
+ /* some players (e.g. Spotify) don't follow the spec closely and pass single strings in metadata fields
+ * where an array of string is expected */
+ static string sanitize_metadata_value (Variant? v) {
+ if (v == null)
+ return "";
+ else if (v.is_of_type (VariantType.STRING))
+ return v.get_string ();
+ else if (v.is_of_type (VariantType.STRING_ARRAY))
+ return string.joinv (",", v.get_strv ());
+
+ warn_if_reached ();
+ return "";
+ }
+
+ void proxy_properties_changed (DBusProxy proxy, Variant changed_properties, string[] invalidated_properties) {
+ if (changed_properties.lookup ("PlaybackStatus", "s", null)) {
+ this.state = this.proxy.PlaybackStatus;
+ }
+
+ var metadata = changed_properties.lookup_value ("Metadata", new VariantType ("a{sv}"));
+ if (metadata != null)
+ this.update_current_track (metadata);
+ }
+
+ void update_current_track (Variant metadata) {
+ if (metadata != null) {
+ this.current_track = new Track (
+ sanitize_metadata_value (metadata.lookup_value ("xesam:artist", null)),
+ sanitize_metadata_value (metadata.lookup_value ("xesam:title", null)),
+ sanitize_metadata_value (metadata.lookup_value ("xesam:album", null)),
+ sanitize_metadata_value (metadata.lookup_value ("mpris:artUrl", null))
+ );
+ }
+ else {
+ this.current_track = null;
+ }
+ }
+}
diff --git a/src/metadata-menu-item.vala b/src/metadata-menu-item.vala
deleted file mode 100644
index f4a7e68..0000000
--- a/src/metadata-menu-item.vala
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using Gee;
-using Dbusmenu;
-using DbusmenuMetadata;
-using Gdk;
-
-public class MetadataMenuitem : PlayerItem
-{
- public const string ALBUM_ART_DIR_SUFFIX = "indicator/sound/album-art-cache";
-
- public static string album_art_cache_dir;
- private static FetchFile fetcher;
- private string previous_temp_album_art_path;
-
- public MetadataMenuitem (PlayerController parent)
- {
- Object(item_type: MENUITEM_TYPE, owner: parent);
- }
-
- construct{
- MetadataMenuitem.clean_album_art_temp_dir();
- this.previous_temp_album_art_path = null;
- this.album_art_cache_dir = MetadataMenuitem.create_album_art_temp_dir();
- //debug ("JUST ABOUT TO ATTEMPT PLAYER NAME SETTING %s", this.owner.app_info.get_name());
- this.property_set (MENUITEM_PLAYER_NAME, this.owner.app_info.get_name());
- this.property_set (MENUITEM_PLAYER_ICON, this.owner.icon_name);
- this.property_set_bool (MENUITEM_PLAYER_RUNNING, false);
- this.property_set_bool (MENUITEM_HIDE_TRACK_DETAILS, true);
- reset (relevant_attributes_for_ui());
- }
-
- private static void clean_album_art_temp_dir()
- {
- string path = GLib.Path.build_filename(Environment.get_user_cache_dir(), ALBUM_ART_DIR_SUFFIX);
-
- GLib.File? album_art_dir = GLib.File.new_for_path(path);
-
- if(delete_album_art_contents(album_art_dir) == false)
- {
- warning("could not remove the temp album art files %s", path);
- }
- }
-
- private static string? create_album_art_temp_dir()
- {
- string path = GLib.Path.build_filename(Environment.get_user_cache_dir(), ALBUM_ART_DIR_SUFFIX);
- if(DirUtils.create_with_parents(path, 0700) == -1){
- warning("could not create temp dir %s for remote album art, it must have been created already", path);
- }
- return path;
- }
-
- private static bool delete_album_art_contents (GLib.File dir)
- {
- bool result = true;
- try {
- var e = dir.enumerate_children (FILE_ATTRIBUTE_STANDARD_NAME,
- FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
- null);
- while (true)
- {
- var file = e.next_file (null);
-
- if (file == null)
- break;
-
- debug("file name = %s", file.get_name());
-
- var child = dir.get_child (file.get_name ());
-
- try {
- child.delete (null);
- } catch (Error error_) {
- warning (@"Unable to delete file '$(child.get_basename ()): $(error_.message)");
- result = false;
- }
- }
- } catch (Error error) {
- warning (@"Unable to read files from directory '$(dir.get_basename ())': %s",
- error.message);
- result = false;
- }
- return result;
- }
-
- public void fetch_art(string uri, string prop)
- {
- File art_file = File.new_for_uri(uri);
- if (art_file.is_native() == true){
- if (art_file.query_exists() == false){
- // Can't load the image, set prop to empty and return.
- this.property_set_int ( prop, EMPTY );
- return;
- }
- string path;
- try{
- path = Filename.from_uri ( uri.strip() );
- debug ("Populating the artwork field with %s", uri.strip());
- this.property_set ( prop, path );
- }
- catch(ConvertError e){
- warning("Problem converting URI %s to file path",
- uri);
- }
- // eitherway return, the artwork was local
- return;
- }
- debug("fetch_art -remotely %s", this.album_art_cache_dir);
- // If we didn't manage to create the temp dir
- // don't bother with remote
- if(this.album_art_cache_dir == null){
- return;
- }
- // green light to go remote
- this.fetcher = new FetchFile (uri, prop);
- this.fetcher.failed.connect (() => { this.on_fetcher_failed ();});
- this.fetcher.completed.connect (this.on_fetcher_completed);
- this.fetcher.fetch_data ();
- }
-
- private void on_fetcher_failed ()
- {
- warning("on_fetcher_failed -> could not fetch artwork");
- }
-
- private void on_fetcher_completed(ByteArray update, string property)
- {
- try{
- PixbufLoader loader = new PixbufLoader ();
- loader.write (update.data);
- loader.close ();
- Pixbuf icon = loader.get_pixbuf ();
- string path = this.album_art_cache_dir.concat("/downloaded-coverart-XXXXXX");
- int r = FileUtils.mkstemp(path);
- if(r != -1){
- icon.save (path, loader.get_format().get_name());
- this.property_set(property, path);
- if(this.previous_temp_album_art_path != null){
- FileUtils.remove(this.previous_temp_album_art_path);
- }
- this.previous_temp_album_art_path = path;
- }
- }
- catch(GLib.Error e){
- warning("Problem creating file from bytearray fetched from the interweb - error: %s",
- e.message);
- }
- }
-
- public override void handle_event (string name,
- Variant input_value,
- uint timestamp)
- {
- if (name != Dbusmenu.MENUITEM_EVENT_ACTIVATED)
- return;
-
- if(this.owner.current_state == PlayerController.state.OFFLINE)
- {
- this.owner.instantiate(timestamp);
- }
- else if (this.owner.current_state == PlayerController.state.CONNECTED) {
- this.owner.player_activator.activate(timestamp);
- this.owner.mpris_bridge.expose(timestamp);
- }
- }
-
- public void alter_label (string? new_title)
- {
- if (new_title == null) return;
- this.property_set (MENUITEM_PLAYER_NAME, new_title);
- }
-
- public void toggle_active_triangle (bool update)
- {
- debug ("toggle active triangle");
- this.property_set_bool (MENUITEM_PLAYER_RUNNING, update);
- }
-
- public void should_collapse(bool collapse)
- {
- this.property_set_bool (MENUITEM_HIDE_TRACK_DETAILS, collapse);
- }
-
- public static HashSet<string> attributes_format()
- {
- HashSet<string> attrs = new HashSet<string>();
- attrs.add(MENUITEM_TITLE);
- attrs.add(MENUITEM_ARTIST);
- attrs.add(MENUITEM_ALBUM);
- attrs.add(MENUITEM_ARTURL);
- attrs.add(MENUITEM_PLAYER_NAME);
- attrs.add(MENUITEM_PLAYER_ICON);
- attrs.add(MENUITEM_PLAYER_RUNNING);
- return attrs;
- }
-
- public static HashSet<string> relevant_attributes_for_ui()
- {
- HashSet<string> attrs = new HashSet<string>();
- attrs.add(MENUITEM_TITLE);
- attrs.add(MENUITEM_ARTIST);
- attrs.add(MENUITEM_ALBUM);
- attrs.add(MENUITEM_ARTURL);
- return attrs;
- }
-}
diff --git a/src/metadata-widget.c b/src/metadata-widget.c
deleted file mode 100644
index 812f340..0000000
--- a/src/metadata-widget.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
- Mirco Müller <mirco.mueller@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-lib.h>
-#include "metadata-widget.h"
-#include "common-defs.h"
-#include <gtk/gtk.h>
-#include <glib.h>
-#include "transport-widget.h"
-#include <libindicator/indicator-image-helper.h>
-
-typedef struct _MetadataWidgetPrivate MetadataWidgetPrivate;
-
-struct _MetadataWidgetPrivate
-{
- gboolean theme_change_occured;
- GtkWidget* meta_data_h_box;
- GtkWidget* meta_data_v_box;
- GtkWidget* album_art;
- GString* image_path;
- GString* old_image_path;
- GtkWidget* artist_label;
- GtkWidget* piece_label;
- GtkWidget* container_label;
- GtkWidget* player_label;
- GtkWidget* player_icon;
- DbusmenuMenuitem* twin_item;
- gint current_height;
-};
-
-#define METADATA_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), METADATA_WIDGET_TYPE, MetadataWidgetPrivate))
-
-/* Prototypes */
-static void metadata_widget_class_init (MetadataWidgetClass *klass);
-static void metadata_widget_init (MetadataWidget *self);
-static void metadata_widget_dispose (GObject *object);
-static void metadata_widget_finalize (GObject *object);
-static void metadata_widget_set_style (GtkWidget* button, GtkStyle* style);
-static void metadata_widget_set_twin_item (MetadataWidget* self,
- DbusmenuMenuitem* twin_item);
-// keyevent consumers
-static gboolean metadata_widget_button_release_event (GtkWidget *menuitem,
- GdkEventButton *event);
-// Dbusmenuitem properties update callback
-static void metadata_widget_property_update (DbusmenuMenuitem* item,
- gchar* property,
- GVariant* value,
- gpointer userdata);
-static void metadata_widget_style_labels ( MetadataWidget* self,
- GtkLabel* label);
-static void draw_album_art_placeholder (GtkWidget *metadata);
-
-static void draw_album_border (GtkWidget *metadata, gboolean selected);
-static void metadata_widget_selection_received_event_callback( GtkWidget *widget,
- GtkSelectionData *data,
- guint time,
- gpointer user_data);
-
-
-
-#if GTK_CHECK_VERSION(3, 0, 0)
-static void metadata_widget_get_preferred_width (GtkWidget* self,
- gint* minimum_width,
- gint* natural_width);
-static gboolean metadata_widget_icon_triangle_draw_cb_gtk_3 (GtkWidget *image,
- cairo_t* cr,
- gpointer user_data);
-static gboolean metadata_image_expose_gtk_3 (GtkWidget *image,
- cairo_t* cr,
- gpointer user_data);
-#else
-static gboolean metadata_widget_icon_triangle_draw_cb (GtkWidget *image,
- GdkEventExpose *event,
- gpointer user_data);
-static gboolean metadata_image_expose (GtkWidget *image,
- GdkEventExpose *event,
- gpointer user_data);
-#endif
-
-static void metadata_widget_set_icon (MetadataWidget *self);
-static void metadata_widget_handle_resizing (MetadataWidget* self);
-
-
-G_DEFINE_TYPE (MetadataWidget, metadata_widget, GTK_TYPE_MENU_ITEM);
-
-static void
-metadata_widget_class_init (MetadataWidgetClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- widget_class->button_release_event = metadata_widget_button_release_event;
- #if GTK_CHECK_VERSION(3, 0, 0)
- widget_class->get_preferred_width = metadata_widget_get_preferred_width;
- #endif
- g_type_class_add_private (klass, sizeof (MetadataWidgetPrivate));
-
- gobject_class->dispose = metadata_widget_dispose;
- gobject_class->finalize = metadata_widget_finalize;
-}
-
-static void
-metadata_widget_init (MetadataWidget *self)
-{
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self);
- GtkWidget *hbox;
- GtkWidget *outer_v_box;
-
- #if GTK_CHECK_VERSION(3, 0, 0)
- outer_v_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- #else
- outer_v_box = gtk_vbox_new (FALSE, 0);
- #endif
-
- #if GTK_CHECK_VERSION(3, 0, 0)
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- #else
- hbox = gtk_hbox_new(FALSE, 0);
- #endif
-
- priv->meta_data_h_box = hbox;
- priv->current_height = 1;
-
- // image
- priv->album_art = gtk_image_new();
- priv->image_path = g_string_new("");
- priv->old_image_path = g_string_new("");
-
- #if GTK_CHECK_VERSION(3, 0, 0)
- g_signal_connect(priv->album_art, "draw",
- G_CALLBACK(metadata_image_expose_gtk_3),
- GTK_WIDGET(self));
-
- g_signal_connect_after (GTK_WIDGET(self), "draw",
- G_CALLBACK(metadata_widget_icon_triangle_draw_cb_gtk_3),
- GTK_WIDGET(self));
- #else
- g_signal_connect(priv->album_art, "expose-event",
- G_CALLBACK(metadata_image_expose),
- GTK_WIDGET(self));
-
- g_signal_connect_after (GTK_WIDGET(self), "expose-event",
- G_CALLBACK(metadata_widget_icon_triangle_draw_cb),
- GTK_WIDGET(self));
- #endif
- gtk_box_pack_start (GTK_BOX (priv->meta_data_h_box),
- priv->album_art,
- FALSE,
- FALSE,
- 1);
- priv->theme_change_occured = FALSE;
-
- #if GTK_CHECK_VERSION(3, 0, 0)
- GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- #else
- GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
- #endif
-
- // artist
- GtkWidget* artist;
- artist = gtk_label_new("");
- gtk_misc_set_alignment(GTK_MISC(artist), (gfloat)0, (gfloat)0);
- gtk_misc_set_padding (GTK_MISC(artist), (gfloat)10, (gfloat)0);
- gtk_widget_set_size_request (artist, 140, 15);
-
- gtk_label_set_ellipsize(GTK_LABEL(artist), PANGO_ELLIPSIZE_MIDDLE);
- metadata_widget_style_labels(self, GTK_LABEL(artist));
- priv->artist_label = artist;
-
- // title
- GtkWidget* piece;
- piece = gtk_label_new("");
- gtk_misc_set_alignment(GTK_MISC(piece), (gfloat)0, (gfloat)0);
- gtk_misc_set_padding (GTK_MISC(piece), (gfloat)10, (gfloat)-5);
-
- gtk_widget_set_size_request (piece, 140, 15);
- gtk_label_set_ellipsize(GTK_LABEL(piece), PANGO_ELLIPSIZE_MIDDLE);
- metadata_widget_style_labels(self, GTK_LABEL(piece));
- priv->piece_label = piece;
-
- // container
- GtkWidget* container;
- container = gtk_label_new("");
- gtk_misc_set_alignment(GTK_MISC(container), (gfloat)0, (gfloat)0);
- gtk_misc_set_padding (GTK_MISC(container), (gfloat)10, (gfloat)0);
- gtk_widget_set_size_request (container, 140, 15);
-
- gtk_label_set_ellipsize(GTK_LABEL(container), PANGO_ELLIPSIZE_MIDDLE);
- metadata_widget_style_labels(self, GTK_LABEL(container));
- priv->container_label = container;
-
- gtk_box_pack_start (GTK_BOX (vbox), priv->piece_label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), priv->artist_label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), priv->container_label, FALSE, FALSE, 0);
-
- gtk_box_pack_start (GTK_BOX (priv->meta_data_h_box), vbox, FALSE, FALSE, 0);
-
- g_signal_connect(self, "style-set",
- G_CALLBACK(metadata_widget_set_style), GTK_WIDGET(self));
- g_signal_connect (self, "selection-received",
- G_CALLBACK(metadata_widget_selection_received_event_callback),
- GTK_WIDGET(self));
-
- gint padding = 4;
- gtk_widget_style_get(GTK_WIDGET(self), "toggle-spacing", &padding, NULL);
-
-#if GTK_CHECK_VERSION(3, 0, 0)
- GtkWidget * tophbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, padding);
-#else
- GtkWidget * tophbox = gtk_hbox_new(FALSE, padding);
-#endif
-
- GtkWidget *player_icon;
- player_icon = gtk_image_new();
- priv->player_icon = player_icon;
-
- gtk_misc_set_alignment (GTK_MISC(priv->player_icon), 1.0 /* right aligned */, 0.5);
- gtk_box_pack_start (GTK_BOX (tophbox), priv->player_icon, FALSE, FALSE, 0);
- GtkWidget* spacer;
- spacer = gtk_alignment_new (0,0,0,0);
- gtk_container_add (GTK_CONTAINER (spacer), priv->meta_data_h_box);
- gtk_alignment_set_padding (GTK_ALIGNMENT (spacer),5,0,0,0);
-
- // player label
- GtkWidget* player_label;
- player_label = gtk_label_new ("");
- gtk_misc_set_alignment(GTK_MISC(player_label), (gfloat)0, 0.5);
- priv->player_label = player_label;
- gtk_box_pack_start (GTK_BOX (tophbox), priv->player_label, TRUE, TRUE, 0);
-
- gtk_box_pack_start (GTK_BOX(outer_v_box), tophbox, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX(outer_v_box), spacer, FALSE, FALSE, 0);
-
- gtk_container_add (GTK_CONTAINER (self), outer_v_box);
-
- gtk_widget_show_all (priv->meta_data_h_box);
- gtk_widget_set_no_show_all (priv->meta_data_h_box, TRUE);
-
- gtk_widget_hide (priv->meta_data_h_box);
-}
-
-static void
-metadata_widget_dispose (GObject *object)
-{
- G_OBJECT_CLASS (metadata_widget_parent_class)->dispose (object);
-}
-
-static void
-metadata_widget_finalize (GObject *object)
-{
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(METADATA_WIDGET(object));
- g_string_free (priv->image_path, TRUE);
- g_string_free (priv->old_image_path, TRUE);
-
- G_OBJECT_CLASS (metadata_widget_parent_class)->finalize (object);
-}
-
-/**
-* Make sure to only clear the album art only when it is not empty
-* Otherwise it will continuously call queue_draw after each empty call.
-*/
-static void
-clear_album_art (GtkImage* album_art)
-{
- if (gtk_image_get_storage_type(album_art) != GTK_IMAGE_EMPTY){
- gtk_image_clear (album_art);
- }
-}
-
-
-#if GTK_CHECK_VERSION(3, 0, 0)
-static void
-metadata_widget_get_preferred_width (GtkWidget* self,
- gint* minimum_width,
- gint* natural_width)
-{
- *minimum_width = *natural_width = 200;
-}
-
-/**
- * We override the expose method to enable primitive drawing of the
- * empty album art image.
- */
-static gboolean
-metadata_image_expose_gtk_3 (GtkWidget *metadata,
- cairo_t* cr,
- gpointer user_data)
-{
- g_return_val_if_fail(IS_METADATA_WIDGET(user_data), FALSE);
- MetadataWidget* widget = METADATA_WIDGET(user_data);
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widget);
-
- if ( TRUE == dbusmenu_menuitem_property_get_bool (DBUSMENU_MENUITEM(priv->twin_item),
- DBUSMENU_METADATA_MENUITEM_HIDE_TRACK_DETAILS))
- {
- return FALSE;
- }
-
- if((guint)priv->image_path->len != 0){
-
- if(g_string_equal (priv->image_path, priv->old_image_path) == FALSE ||
- priv->theme_change_occured == TRUE){
- priv->theme_change_occured = FALSE;
- GdkPixbuf* pixbuf;
- pixbuf = gdk_pixbuf_new_from_file_at_size(priv->image_path->str, 60, 60, NULL);
-
- if(GDK_IS_PIXBUF(pixbuf) == FALSE){
- clear_album_art (GTK_IMAGE(priv->album_art));
- gtk_widget_set_size_request(GTK_WIDGET(priv->album_art), 60, 60);
- draw_album_border (metadata, FALSE);
- draw_album_art_placeholder(metadata);
- return FALSE;
- }
-
- gtk_image_set_from_pixbuf(GTK_IMAGE(priv->album_art), pixbuf);
- gtk_widget_set_size_request(GTK_WIDGET(priv->album_art),
- gdk_pixbuf_get_width(pixbuf),
- gdk_pixbuf_get_height(pixbuf));
-
- draw_album_border (metadata, FALSE);
- g_string_erase (priv->old_image_path, 0, -1);
- g_string_overwrite (priv->old_image_path, 0, priv->image_path->str);
- g_object_unref(pixbuf);
- }
- return FALSE;
- }
- clear_album_art (GTK_IMAGE(priv->album_art));
- g_string_erase (priv->old_image_path, 0, -1);
- gtk_widget_set_size_request(GTK_WIDGET(priv->album_art), 60, 60);
- draw_album_border (metadata, FALSE);
- draw_album_art_placeholder(metadata);
- return FALSE;
-}
-
-// Draw the triangle if the player is running ...
-static gboolean
-metadata_widget_icon_triangle_draw_cb_gtk_3 (GtkWidget *widget,
- cairo_t* cr,
- gpointer user_data)
-{
- g_return_val_if_fail (IS_METADATA_WIDGET (user_data), FALSE);
- MetadataWidget* meta = METADATA_WIDGET (user_data);
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(meta);
-
- gboolean running = dbusmenu_menuitem_property_get_bool (priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING);
-
- if (!running)
- return FALSE;
-
- GtkStyle *style;
- int x, y, arrow_width, arrow_height;
-
- arrow_width = 5;
- arrow_height = 9;
-
- style = gtk_widget_get_style (widget);
-
- GtkAllocation allocation;
- gtk_widget_get_allocation (widget, &allocation);
- x = allocation.x;
- y = 0;
-
- // Draw triangle but only if the player is running.
- y += gtk_image_get_pixel_size (GTK_IMAGE (priv->player_icon)) / 3 + 5;
- cairo_set_line_width (cr, 1.0);
-
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x, y + arrow_height);
- cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0);
- cairo_close_path (cr);
- cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
- style->fg[gtk_widget_get_state(widget)].green/65535.0,
- style->fg[gtk_widget_get_state(widget)].blue/65535.0);
- cairo_fill (cr);
-
- return FALSE;
-}
-
-// GTK 2 Expose handler
-#else
-
-static gboolean
-metadata_image_expose (GtkWidget *metadata,
- GdkEventExpose *event,
- gpointer user_data)
-{
- g_return_val_if_fail(IS_METADATA_WIDGET(user_data), FALSE);
- MetadataWidget* widget = METADATA_WIDGET(user_data);
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widget);
-
- if ( TRUE == dbusmenu_menuitem_property_get_bool (DBUSMENU_MENUITEM(priv->twin_item),
- DBUSMENU_METADATA_MENUITEM_HIDE_TRACK_DETAILS))
- {
- return FALSE;
- }
-
- draw_album_border(metadata, FALSE);
-
- if(priv->image_path->len > 0){
- if(g_string_equal(priv->image_path, priv->old_image_path) == FALSE ||
- priv->theme_change_occured == TRUE){
- priv->theme_change_occured = FALSE;
- GdkPixbuf* pixbuf;
- pixbuf = gdk_pixbuf_new_from_file_at_size(priv->image_path->str, 60, 60, NULL);
-
- if(GDK_IS_PIXBUF(pixbuf) == FALSE){
- clear_album_art (GTK_IMAGE(priv->album_art));
- gtk_widget_set_size_request(GTK_WIDGET(priv->album_art), 60, 60);
- draw_album_art_placeholder(metadata);
- return FALSE;
- }
-
- gtk_image_set_from_pixbuf(GTK_IMAGE(priv->album_art), pixbuf);
- gtk_widget_set_size_request(GTK_WIDGET(priv->album_art),
- gdk_pixbuf_get_width(pixbuf),
- gdk_pixbuf_get_height(pixbuf));
-
- g_string_erase (priv->old_image_path, 0, -1);
- g_string_overwrite (priv->old_image_path, 0, priv->image_path->str);
- g_object_unref(pixbuf);
- }
- return FALSE;
- }
- clear_album_art (GTK_IMAGE(priv->album_art));
- g_string_erase (priv->old_image_path, 0, -1);
- gtk_widget_set_size_request(GTK_WIDGET(priv->album_art), 60, 60);
- draw_album_art_placeholder(metadata);
- return FALSE;
-}
-
-
-// Draw the triangle if the player is running ...
-static gboolean
-metadata_widget_icon_triangle_draw_cb (GtkWidget *widget,
- GdkEventExpose *event,
- gpointer user_data)
-{
- g_return_val_if_fail(IS_METADATA_WIDGET(user_data), FALSE);
-
- MetadataWidget* meta = METADATA_WIDGET(user_data);
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(meta);
-
- gboolean running = dbusmenu_menuitem_property_get_bool (priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING);
-
- if (!running)
- return FALSE;
-
- GtkStyle *style;
- cairo_t *cr;
- int x, y, arrow_width, arrow_height;
-
- arrow_width = 5;
- arrow_height = 9;
-
- style = gtk_widget_get_style (widget);
-
- cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));
-
- GtkAllocation allocation;
- gtk_widget_get_allocation (widget, &allocation);
- x = allocation.x;
- y = allocation.y;
-
- // Draw triangle but only if the player is running.
- y += allocation.height/2.0 - (double)arrow_height/2.0;
- cairo_set_line_width (cr, 1.0);
-
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x, y + arrow_height);
- cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0);
- cairo_close_path (cr);
- cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
- style->fg[gtk_widget_get_state(widget)].green/65535.0,
- style->fg[gtk_widget_get_state(widget)].blue/65535.0);
- cairo_fill (cr);
-
- cairo_destroy (cr);
- return FALSE;
-}
-#endif
-
-static void
-draw_album_border(GtkWidget *metadata,
- gboolean selected)
-{
- cairo_t *cr;
- cr = gdk_cairo_create (gtk_widget_get_window (metadata));
- #if GTK_CHECK_VERSION(3, 0, 0)
- gtk_style_context_add_class (gtk_widget_get_style_context (metadata),
- "menu");
- #endif
-
- GtkStyle *style;
- style = gtk_widget_get_style (metadata);
-
- GtkAllocation alloc;
- gtk_widget_get_allocation (metadata, &alloc);
- gint offset = 1;
-
- alloc.width = alloc.width + (offset * 2);
- alloc.height = alloc.height + (offset * 2) - 7;
- alloc.x = alloc.x - offset;
- alloc.y = alloc.y - offset + 3;
-
- CairoColorRGB bg_normal, fg_normal;
-
- bg_normal.r = style->bg[0].red/65535.0;
- bg_normal.g = style->bg[0].green/65535.0;
- bg_normal.b = style->bg[0].blue/65535.0;
-
- const gint state = selected ? GTK_STATE_SELECTED : GTK_STATE_NORMAL;
-
- fg_normal.r = style->fg[state].red/65535.0;
- fg_normal.g = style->fg[state].green/65535.0;
- fg_normal.b = style->fg[state].blue/65535.0;
-
- CairoColorRGB dark_top_color;
- CairoColorRGB light_bottom_color;
- CairoColorRGB background_color;
-
- _color_shade ( &bg_normal, 0.93, &background_color );
- _color_shade ( &bg_normal, 0.23, &dark_top_color );
- _color_shade ( &fg_normal, 0.55, &light_bottom_color );
-
- cairo_rectangle (cr,
- alloc.x, alloc.y,
- alloc.width, alloc.height);
-
- cairo_set_line_width (cr, 1.0);
-
- cairo_clip ( cr );
-
- cairo_move_to (cr, alloc.x, alloc.y );
- cairo_line_to (cr, alloc.x + alloc.width,
- alloc.y );
- cairo_line_to ( cr, alloc.x + alloc.width,
- alloc.y + alloc.height );
- cairo_line_to ( cr, alloc.x, alloc.y + alloc.height );
- cairo_line_to ( cr, alloc.x, alloc.y);
- cairo_close_path (cr);
-
- cairo_set_source_rgba ( cr,
- background_color.r,
- background_color.g,
- background_color.b,
- 1.0 );
-
- cairo_fill ( cr );
-
- cairo_move_to (cr, alloc.x, alloc.y );
- cairo_line_to (cr, alloc.x + alloc.width,
- alloc.y );
-
- cairo_close_path (cr);
- cairo_set_source_rgba ( cr,
- dark_top_color.r,
- dark_top_color.g,
- dark_top_color.b,
- 1.0 );
-
- cairo_stroke ( cr );
-
- cairo_move_to ( cr, alloc.x + alloc.width,
- alloc.y + alloc.height );
- cairo_line_to ( cr, alloc.x, alloc.y + alloc.height );
-
- cairo_close_path (cr);
- cairo_set_source_rgba ( cr,
- light_bottom_color.r,
- light_bottom_color.g,
- light_bottom_color.b,
- 1.0);
-
- cairo_stroke ( cr );
- cairo_destroy (cr);
-}
-
-static void
-draw_album_art_placeholder(GtkWidget *metadata)
-{
- cairo_t *cr;
- cr = gdk_cairo_create (gtk_widget_get_window (metadata));
- GtkStyle *style;
- style = gtk_widget_get_style (metadata);
-
- GtkAllocation alloc;
- gtk_widget_get_allocation (metadata, &alloc);
-
- PangoLayout *layout;
- PangoFontDescription *desc;
- layout = pango_cairo_create_layout(cr);
- PangoContext* pcontext = pango_cairo_create_context(cr);
- pango_cairo_context_set_resolution (pcontext, 96);
-
- GString* string = g_string_new("");
- gssize size = -1;
- gunichar code = g_utf8_get_char_validated("\342\231\253", size);
- g_string_append_unichar (string, code);
-
- pango_layout_set_text(layout, string->str, -1);
- desc = pango_font_description_from_string("Sans Bold 30");
- pango_layout_set_font_description(layout, desc);
- pango_font_description_free(desc);
-
- CairoColorRGB fg_normal, light_bottom_color;
-
- fg_normal.r = style->fg[0].red/65535.0;
- fg_normal.g = style->fg[0].green/65535.0;
- fg_normal.b = style->fg[0].blue/65535.0;
-
- _color_shade ( &fg_normal, 0.78, &light_bottom_color );
-
- cairo_set_source_rgba (cr,
- light_bottom_color.r,
- light_bottom_color.g,
- light_bottom_color.b,
- 1.0);
-
- pango_cairo_update_layout(cr, layout);
- cairo_move_to (cr, alloc.x + alloc.width/6, alloc.y + 3);
- pango_cairo_show_layout(cr, layout);
-
- g_object_unref(layout);
- g_object_unref(pcontext);
- g_string_free (string, TRUE);
- cairo_destroy (cr);
-}
-
-static void
-metadata_widget_selection_received_event_callback ( GtkWidget *widget,
- GtkSelectionData *data,
- guint time,
- gpointer user_data )
-
-{
- draw_album_border(widget, TRUE);
-}
-
-/* Suppress/consume keyevents */
-static gboolean
-metadata_widget_button_release_event (GtkWidget *menuitem,
- GdkEventButton *event)
-{
- g_return_val_if_fail (IS_METADATA_WIDGET (menuitem), FALSE);
- MetadataWidgetPrivate* priv = METADATA_WIDGET_GET_PRIVATE(METADATA_WIDGET(menuitem));
- // For the left raise/launch the player
- if (event->button == 1){
- GVariant* new_title_event = g_variant_new_boolean(TRUE);
- dbusmenu_menuitem_handle_event (priv->twin_item,
- "Title menu event",
- new_title_event,
- 0);
- }
- // For the right copy track details to clipboard only if the player is running
- // and there is something there
- else if (event->button == 3){
- gboolean running = dbusmenu_menuitem_property_get_bool (priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING);
- gboolean hidden = dbusmenu_menuitem_property_get_bool (priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_HIDE_TRACK_DETAILS);
- g_return_val_if_fail ( running, FALSE );
-
- g_return_val_if_fail ( !hidden, FALSE );
-
- GtkClipboard* board = gtk_clipboard_get (GDK_NONE);
- gchar* contents = g_strdup_printf("artist: %s \ntitle: %s \nalbum: %s",
- dbusmenu_menuitem_property_get(priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_ARTIST),
- dbusmenu_menuitem_property_get(priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_TITLE),
- dbusmenu_menuitem_property_get(priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_ALBUM));
- gtk_clipboard_set_text (board, contents, -1);
- gtk_clipboard_store (board);
- g_free(contents);
- }
- return FALSE;
-}
-
-static void
-metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property,
- GVariant* value, gpointer userdata)
-{
- g_return_if_fail (IS_METADATA_WIDGET (userdata));
-
- if(g_variant_is_of_type(value, G_VARIANT_TYPE_INT32) == TRUE &&
- g_variant_get_int32(value) == DBUSMENU_PROPERTY_EMPTY){
- GVariant* new_value = g_variant_new_string ("");
- value = new_value;
- }
-
- MetadataWidget* mitem = METADATA_WIDGET(userdata);
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(mitem);
-
- if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ARTIST, property) == 0){
- gtk_label_set_text(GTK_LABEL(priv->artist_label), g_variant_get_string(value, NULL));
- metadata_widget_style_labels(mitem, GTK_LABEL(priv->artist_label));
- }
- else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TITLE, property) == 0){
- gtk_label_set_text(GTK_LABEL(priv->piece_label), g_variant_get_string(value, NULL));
- metadata_widget_style_labels(mitem, GTK_LABEL(priv->piece_label));
- }
- else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ALBUM, property) == 0){
- gtk_label_set_text(GTK_LABEL(priv->container_label), g_variant_get_string(value, NULL));
- metadata_widget_style_labels(mitem, GTK_LABEL(priv->container_label));
- }
- else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ARTURL, property) == 0){
- g_string_erase(priv->image_path, 0, -1);
- g_string_overwrite (priv->image_path, 0, g_variant_get_string (value, NULL));
- gtk_widget_queue_draw(GTK_WIDGET(mitem));
- }
- else if (g_ascii_strcasecmp (DBUSMENU_METADATA_MENUITEM_PLAYER_NAME, property) == 0){
- gtk_label_set_label (GTK_LABEL (priv->player_label),
- g_variant_get_string(value, NULL));
- }
- else if (g_ascii_strcasecmp (DBUSMENU_METADATA_MENUITEM_PLAYER_ICON, property) == 0){
- metadata_widget_set_icon (mitem);
- }
- else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_HIDE_TRACK_DETAILS, property) == 0){
- metadata_widget_handle_resizing (mitem);
- }
-}
-
-static void
-metadata_widget_handle_resizing (MetadataWidget* self)
-{
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self);
-
- if (dbusmenu_menuitem_property_get_bool (priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_HIDE_TRACK_DETAILS) == TRUE){
- gtk_widget_hide (priv->meta_data_h_box);
- }
- else{
- gtk_widget_show (priv->meta_data_h_box);
- }
- gtk_widget_queue_draw(GTK_WIDGET(self));
-}
-
-static void
-metadata_widget_style_labels(MetadataWidget* self, GtkLabel* label)
-{
- char* markup;
- markup = g_markup_printf_escaped ("<span size=\"smaller\">%s</span>",
- gtk_label_get_text(GTK_LABEL(label)));
- gtk_label_set_markup (GTK_LABEL (label), markup);
- g_free(markup);
-}
-
-static void
-metadata_widget_set_style(GtkWidget* metadata, GtkStyle* style)
-{
- g_return_if_fail(IS_METADATA_WIDGET(metadata));
- MetadataWidget* widg = METADATA_WIDGET(metadata);
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widg);
- priv->theme_change_occured = TRUE;
- gtk_widget_queue_draw (GTK_WIDGET(metadata));
-}
-
-static void
-metadata_widget_set_icon (MetadataWidget *self)
-{
- MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self);
-
- GString* banshee_string = g_string_new ( "banshee" );
- gchar * tmp = g_utf8_strdown (dbusmenu_menuitem_property_get(priv->twin_item, DBUSMENU_METADATA_MENUITEM_PLAYER_NAME), -1);
- GString* app_panel = g_string_new (tmp);
- g_free (tmp);
-
- // Banshee Special case!
- // Not ideal but apparently we want the banshee icon to be the greyscale one
- // and any others to be the icon from the desktop file => colour.
- if ( g_string_equal ( banshee_string, app_panel ) == TRUE &&
- gtk_icon_theme_has_icon ( gtk_icon_theme_get_default(), app_panel->str ) ){
- g_string_append ( app_panel, "-panel" );
- }
- else{
- // Otherwise use what is stored in the props
- g_string_erase (app_panel, 0, -1);
- g_string_overwrite (app_panel,
- 0,
- dbusmenu_menuitem_property_get ( priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_PLAYER_ICON ));
- }
-
- const GtkIconSize icon_size = GTK_ICON_SIZE_MENU;
- if (g_path_is_absolute(app_panel->str) && g_file_test (app_panel->str, G_FILE_TEST_IS_REGULAR)){
- gint width, height;
- gtk_icon_size_lookup (icon_size, &width, &height);
- GdkPixbuf *pix = gdk_pixbuf_new_from_file_at_scale(app_panel->str, width, height, TRUE, NULL);
- gtk_image_set_from_pixbuf (GTK_IMAGE (priv->player_icon), pix);
- g_object_unref (pix);
- }
- else{
- gtk_image_set_from_icon_name(GTK_IMAGE (priv->player_icon), app_panel->str, icon_size);
- }
-
- g_string_free ( app_panel, TRUE);
- g_string_free ( banshee_string, TRUE);
-}
-
-static void
-metadata_widget_set_twin_item (MetadataWidget* self,
- DbusmenuMenuitem* twin_item)
-{
- MetadataWidgetPrivate* priv = METADATA_WIDGET_GET_PRIVATE(self);
- priv->twin_item = twin_item;
- g_signal_connect( G_OBJECT(priv->twin_item), "property-changed",
- G_CALLBACK(metadata_widget_property_update), self);
- gtk_label_set_text( GTK_LABEL(priv->container_label),
- dbusmenu_menuitem_property_get( priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_ALBUM));
- metadata_widget_style_labels( self, GTK_LABEL(priv->container_label));
-
- gtk_label_set_text( GTK_LABEL(priv->piece_label),
- dbusmenu_menuitem_property_get( priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_TITLE));
- metadata_widget_style_labels( self, GTK_LABEL(priv->piece_label));
- gtk_label_set_text( GTK_LABEL(priv->artist_label),
- dbusmenu_menuitem_property_get( priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_ARTIST));
- metadata_widget_style_labels( self, GTK_LABEL(priv->artist_label));
-
- g_string_erase(priv->image_path, 0, -1);
- const gchar *arturl = dbusmenu_menuitem_property_get( priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_ARTURL );
-
- gtk_label_set_label (GTK_LABEL(priv->player_label),
- dbusmenu_menuitem_property_get(priv->twin_item,
- DBUSMENU_METADATA_MENUITEM_PLAYER_NAME));
-
- metadata_widget_set_icon(self);
-
- if (arturl != NULL){
- g_string_overwrite( priv->image_path,
- 0,
- arturl);
- // if its a remote image queue a redraw incase the download took too long
- if (g_str_has_prefix (arturl, g_get_user_cache_dir())){
- gtk_widget_queue_draw(GTK_WIDGET(self));
- }
- }
- metadata_widget_handle_resizing (self);
-}
-
- /**
- * transport_new:
- * @returns: a new #MetadataWidget.
- **/
-GtkWidget*
-metadata_widget_new(DbusmenuMenuitem *item)
-{
- GtkWidget* widget = g_object_new(METADATA_WIDGET_TYPE, NULL);
- metadata_widget_set_twin_item ( METADATA_WIDGET(widget),
- item );
- return widget;
-}
-
diff --git a/src/metadata-widget.h b/src/metadata-widget.h
deleted file mode 100644
index fc6944e..0000000
--- a/src/metadata-widget.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef __METADATA_WIDGET_H__
-#define __METADATA_WIDGET_H__
-
-#include <gtk/gtk.h>
-#include <libdbusmenu-gtk/menuitem.h>
-
-G_BEGIN_DECLS
-
-#define METADATA_WIDGET_TYPE (metadata_widget_get_type ())
-#define METADATA_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), METADATA_WIDGET_TYPE, MetadataWidget))
-#define METADATA_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), METADATA_WIDGET_TYPE, MetadataWidgetClass))
-#define IS_METADATA_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), METADATA_WIDGET_TYPE))
-#define IS_METADATA_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), METADATA_WIDGET_TYPE))
-#define METADATA_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), METADATA_WIDGET_TYPE, MetadataWidgetClass))
-
-typedef struct _MetadataWidget MetadataWidget;
-typedef struct _MetadataWidgetClass MetadataWidgetClass;
-
-struct _MetadataWidgetClass {
- GtkMenuItemClass parent_class;
-};
-
-struct _MetadataWidget {
- GtkMenuItem parent;
-};
-
-GType metadata_widget_get_type (void);
-GtkWidget* metadata_widget_new(DbusmenuMenuitem *twin_item);
-
-G_END_DECLS
-
-#endif
-
diff --git a/src/mpris2-controller.vala b/src/mpris2-controller.vala
deleted file mode 100644
index 9230a59..0000000
--- a/src/mpris2-controller.vala
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-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 Transport;
-
-public class Mpris2Controller : GLib.Object
-{
- public const int MAX_PLAYLIST_COUNT = 100;
-
- public MprisRoot mpris2_root {get; construct;}
- public MprisPlayer player {get; construct;}
- public MprisPlaylists playlists {get; construct;}
- public FreeDesktopProperties properties_interface {get; construct;}
- public PlayerController owner {get; construct;}
-
- public Mpris2Controller(PlayerController ctrl)
- {
- GLib.Object(owner: ctrl);
- }
-
- construct{
- try {
- this.mpris2_root = Bus.get_proxy_sync ( BusType.SESSION,
- this.owner.dbus_name,
- "/org/mpris/MediaPlayer2" );
- this.player = Bus.get_proxy_sync ( BusType.SESSION,
- this.owner.dbus_name,
- "/org/mpris/MediaPlayer2" );
- this.properties_interface = Bus.get_proxy_sync ( BusType.SESSION,
- "org.freedesktop.Properties.PropertiesChanged",
- "/org/mpris/MediaPlayer2" );
- this.properties_interface.PropertiesChanged.connect ( property_changed_cb );
- if ( this.owner.use_playlists == true ){
- this.playlists = Bus.get_proxy_sync ( BusType.SESSION,
- this.owner.dbus_name,
- "/org/mpris/MediaPlayer2" );
- this.playlists.PlaylistChanged.connect (on_playlistdetails_changed);
- }
- }
- catch (IOError e) {
- critical("Problems connecting to the session bus - %s", e.message);
- }
- }
- /*
- * property_changed_cb
- * Called when a property changed signal is emitted from any of mpris
- * objects on the bus.
- * Note that the signal will be received by each instance for each player
- * and at that moment there is no way to know what player that signal
- * came from therefore it is necessary to query each relevant property
- * to update the respective dbusmenuitem property inorder to keep the UI in sync
- * Please also note due to some race condition in the depths of gdbus
- * a timeout is needed between receiving the prop update and query the respective property.
- * This can be seen at various points below.
- */
- public void property_changed_cb ( string interface_source,
- HashTable<string, Variant?> changed_properties,
- string[] invalid )
- {
- if ( changed_properties == null ||
- interface_source.has_prefix ( MPRIS_PREFIX ) == false ){
- warning("Property-changed hash is null or this is an interface that doesn't concern us");
- return;
- }
- Variant? play_v = changed_properties.lookup("PlaybackStatus");
- if(play_v != null){
- string state = this.player.PlaybackStatus;
- Timeout.add ( 200, ensure_correct_playback_status );
- Transport.State p = (Transport.State)this.determine_play_state(state);
- (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(p);
- }
- Variant? meta_v = changed_properties.lookup("Metadata");
- if(meta_v != null)
- {
- Timeout.add ( 200, ensure_correct_metadata );
- }
- Variant? playlist_v = changed_properties.lookup("ActivePlaylist");
- if ( playlist_v != null && this.owner.use_playlists == true ){
- Timeout.add (500, this.fetch_active_playlist);
- }
- Variant? playlist_count_v = changed_properties.lookup("PlaylistCount");
- if ( playlist_count_v != null && this.owner.use_playlists == true ){
- this.fetch_playlists.begin();
- this.fetch_active_playlist();
- }
- Variant? playlist_orderings_v = changed_properties.lookup("Orderings");
- if ( playlist_orderings_v != null && this.owner.use_playlists == true ){
- this.fetch_playlists.begin();
- this.fetch_active_playlist();
- }
- Variant? identity_v = changed_properties.lookup("Identity");
- if (identity_v != null){
- MetadataMenuitem md = this.owner.custom_items[PlayerController.widget_order.METADATA] as MetadataMenuitem;
- md.alter_label (this.mpris2_root.Identity);
- }
- }
-
- private bool ensure_correct_metadata ()
- {
- GLib.HashTable<string, Variant?> changed_updates = clean_metadata();
- PlayerItem metadata = this.owner.custom_items[PlayerController.widget_order.METADATA];
- metadata.reset (MetadataMenuitem.relevant_attributes_for_ui());
- metadata.update ( changed_updates,
- MetadataMenuitem.relevant_attributes_for_ui());
- MetadataMenuitem md = this.owner.custom_items[PlayerController.widget_order.METADATA] as MetadataMenuitem;
- bool collapsing = !metadata.populated(MetadataMenuitem.relevant_attributes_for_ui());
- md.should_collapse(collapsing);
-
- return false;
- }
-
- private bool ensure_correct_playback_status()
- {
- Transport.State p = (Transport.State)this.determine_play_state(this.player.PlaybackStatus);
- (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state(p);
- return false;
- }
-
- private GLib.HashTable<string, Variant?>? clean_metadata()
- {
- GLib.HashTable<string, Variant?> changed_updates = this.player.Metadata;
-
- Variant? artist_v = this.player.Metadata.lookup("xesam:artist");
- if(artist_v != null){
- string display_artists;
- // Accomodate Spotify (should return 'as' and not 's')
- if(artist_v.get_type_string() == "s"){
- display_artists = artist_v.get_string();
- }
- else{
- string[] artists = artist_v.dup_strv();
- display_artists = string.joinv(", ", artists);
- }
- changed_updates.replace("xesam:artist", display_artists);
- }
- return changed_updates;
- }
-
- private Transport.State determine_play_state(string? status){
- if(status != null && status == "Playing"){
- return Transport.State.PLAYING;
- }
- return Transport.State.PAUSED;
- }
-
- public void initial_update()
- {
- Transport.State update;
-
- if(this.player.PlaybackStatus == null){
- update = Transport.State.PAUSED;
- }
- else{
- update = determine_play_state (this.player.PlaybackStatus);
- }
- if (this.mpris2_root.Identity != null){
- MetadataMenuitem md = this.owner.custom_items[PlayerController.widget_order.METADATA] as MetadataMenuitem;
- md.alter_label (this.mpris2_root.Identity);
- }
- (this.owner.custom_items[PlayerController.widget_order.TRANSPORT] as TransportMenuitem).change_play_state (update);
- GLib.HashTable<string, Value?>? cleaned_metadata = this.clean_metadata();
- this.owner.custom_items[PlayerController.widget_order.METADATA].update (cleaned_metadata,
- MetadataMenuitem.attributes_format());
-
- if ( this.owner.use_playlists == true ){
- this.fetch_playlists.begin();
- this.fetch_active_playlist();
- }
- }
-
- public void transport_update(Transport.Action command)
- {
- if(command == Transport.Action.PLAY_PAUSE){
- this.player.PlayPause.begin();
- }
- else if(command == Transport.Action.PREVIOUS){
- this.player.Previous.begin();
- }
- else if(command == Transport.Action.NEXT){
- this.player.Next.begin();
- }
- else if(command == Transport.Action.REWIND){
- this.player.Seek.begin(-500000);
- }
- else if(command == Transport.Action.FORWIND){
- this.player.Seek.begin(400000);
- }
- }
-
- public bool connected()
- {
- return (this.player != null && this.mpris2_root != null);
- }
-
- public void expose(uint timestmap)
- {
- if (this.connected() == true) {
- this.mpris2_root.Raise.begin();
- }
- }
-
- private void on_playlistdetails_changed (PlaylistDetails details)
- {
- PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem;
- playlists_item.update_individual_playlist (details);
- }
-
- public async void fetch_playlists()
- {
- PlaylistDetails[] current_playlists = null;
-
- try{
- current_playlists = yield this.playlists.GetPlaylists (0,
- MAX_PLAYLIST_COUNT,
- "Alphabetical",
- false);
- }
- catch (IOError e){
- return;
- }
-
- if( current_playlists != null ){
- PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem;
- playlists_item.update(current_playlists);
- }
- else{
- warning(" Playlists are on but %s is returning no current_playlists ?",
- this.owner.app_info.get_name());
- this.owner.use_playlists = false;
- }
- }
-
- private bool validate_playlists_details()
- {
- if (this.playlists.ActivePlaylist == null){
- return false;
- }
- if (this.playlists.ActivePlaylist.valid == false){
- return false;
- }
- if (this.playlists.ActivePlaylist.details == null){
- return false;
- }
- if (this.playlists.ActivePlaylist.details.path == null ||
- this.playlists.ActivePlaylist.details.name == null){
- return false;
- }
- return true;
- }
-
- private bool fetch_active_playlist()
- {
- if (this.validate_playlists_details() == false){
- return false;
- }
- PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem;
- playlists_item.active_playlist_update ( this.playlists.ActivePlaylist.details );
- return false;
- }
-
- public void activate_playlist (ObjectPath path)
- {
- try{
- this.playlists.ActivatePlaylist.begin(path);
- }
- catch(IOError e){
- warning ("Could not activate playlist %s because %s", (string)path, e.message);
- }
- }
-}
diff --git a/src/mpris2-watcher.vala b/src/mpris2-watcher.vala
index cdfb9c6..740089d 100644
--- a/src/mpris2-watcher.vala
+++ b/src/mpris2-watcher.vala
@@ -94,7 +94,7 @@ public class Mpris2Watcher : GLib.Object
MprisRoot? mpris2_root = this.create_mpris_root(address);
if (mpris2_root == null) return;
bool use_playlists = this.supports_playlists ( address );
- client_appeared (mpris2_root.DesktopEntry, address, use_playlists);
+ client_appeared (mpris2_root.DesktopEntry + ".desktop", address, use_playlists);
}
}
}
@@ -116,7 +116,7 @@ public class Mpris2Watcher : GLib.Object
else if (previous_owner == "" && current_owner != "") {
debug ("Client '%s' has appeared", name);
bool use_playlists = this.supports_playlists ( name );
- client_appeared (mpris2_root.DesktopEntry, name, use_playlists);
+ client_appeared (mpris2_root.DesktopEntry + ".desktop", name, use_playlists);
}
}
diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala
deleted file mode 100644
index 59ced36..0000000
--- a/src/music-player-bridge.vala
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using Dbusmenu;
-using Gee;
-using GLib;
-
-public class MusicPlayerBridge : GLib.Object
-{
- const int DEVICE_ITEMS_COUNT = 3;
-
- private SettingsManager settings_manager;
- private Dbusmenu.Menuitem root_menu;
- private HashMap<string, PlayerController> registered_clients;
- private HashMap<string, string> file_monitors;
- private HashMap<string, string> mpris_to_desktop;
- private Mpris2Watcher watcher;
-
- public MusicPlayerBridge()
- {
- }
-
- construct{
- this.registered_clients = new HashMap<string, PlayerController> ();
- this.file_monitors = new HashMap<string, string> ();
- this.mpris_to_desktop = new HashMap<string, string> ();
- this.settings_manager = new SettingsManager();
- this.settings_manager.blacklist_updates.connect ( this.on_blacklist_update );
- this.settings_manager.preferred_updates.connect ( this.on_preferred_update );
- }
-
- private void on_blacklist_update ( string[] blacklist )
- {
- debug("some blacklist update");
-
- foreach(var desktop_id in blacklist){
- string key = desktop_id;
- if (this.registered_clients.has_key (key)){
- debug ("Apparently %s is now blacklisted - remove thy self", key);
- this.registered_clients[key].remove_from_menu();
- this.registered_clients.unset (key);
- }
- }
- // double check present players to ensure dynamic removal/addition
- this.watcher.check_for_active_clients.begin();
- }
-
- private void on_preferred_update ( Gee.ArrayList<string> preferred )
- {
- debug ("Preferred players update. Clearing current preferred players...");
-
- foreach (var player_controller in this.registered_clients.values) {
- player_controller.set_as_preferred (false);
- }
-
- foreach (var desktop_id in preferred) {
- string key = desktop_id;
- if (this.registered_clients.has_key (key)) {
- debug ("Setting %s as preferred player", key);
- this.registered_clients[key].set_as_preferred (true);
- }
- }
- }
-
- private void try_to_add_inactive_familiar_clients()
- {
- var preferred_players = this.settings_manager.fetch_preferred ();
- foreach ( string desktop in this.settings_manager.fetch_interested()){
- debug ( "interested client found : %s", desktop );
- AppInfo? app_info = create_app_info ( desktop.concat( ".desktop" ) );
- if ( app_info == null ){
- warning ( "Could not create app_info for path %s \n Getting out of here ",
- desktop );
- continue;
- }
- bool is_preferred = desktop in preferred_players;
- PlayerController ctrl = new PlayerController ( this.root_menu,
- app_info,
- null,
- this.fetch_icon_name(desktop),
- calculate_menu_position(),
- null,
- PlayerController.state.OFFLINE,
- is_preferred );
- var mpris_key = desktop;
- this.registered_clients.set(mpris_key, ctrl);
- this.establish_file_monitoring (app_info, mpris_key);
- }
- }
-
- private void establish_file_monitoring (AppInfo info, string mpris_key){
- DesktopAppInfo desktop_info = info as DesktopAppInfo;
- var file_path = desktop_info.get_filename ();
- File f = File.new_for_path (file_path);
- try {
- FileMonitor monitor = f.monitor (FileMonitorFlags.SEND_MOVED, null);
- unowned FileMonitor weak_monitor = monitor;
- monitor.changed.connect ((desktop_file, other_file, event_type) => {
- this.relevant_desktop_file_changed (desktop_file, other_file, event_type, weak_monitor);
- });
- monitor.ref(); // will be unref()ed by relevant_desktop_file_changed()
- GLib.debug ("monitoring file '%s'", file_path);
- this.file_monitors.set (file_path, mpris_key);
- }
- catch (Error e){
- warning ("Unable to create a file monitor for %s", info.get_name());
- return;
- }
- }
-
- private void relevant_desktop_file_changed (File desktop_file,
- File? other_file,
- FileMonitorEvent event_type,
- FileMonitor monitor)
- {
- if (event_type != FileMonitorEvent.DELETED)
- return;
-
- string? path = desktop_file.get_path ();
- if (path == null){
- warning ("relevant_desktop_file_changed is returning a file with no path !");
- return;
- }
- if (!this.file_monitors.has_key (path)){
- warning ("relevant_desktop_file_changed is returning a file which we know nothing about - %s",
- path);
- return;
- }
-
- var mpris_key = this.file_monitors[path];
- GLib.debug ("file \"%s\" was removed; stopping monitoring \"%s\"", path, mpris_key);
- this.registered_clients[mpris_key].remove_from_menu();
- this.settings_manager.remove_interested (mpris_key);
- this.registered_clients.unset (mpris_key);
- monitor.cancel ();
- monitor.unref();
- }
-
- private int calculate_menu_position()
- {
- if(this.registered_clients.size == 0){
- return DEVICE_ITEMS_COUNT;
- }
- else{
- return (DEVICE_ITEMS_COUNT + (this.registered_clients.size * PlayerController.WIDGET_QUANTITY));
- }
- }
-
- public void client_has_become_available ( string desktop,
- string dbus_name,
- bool use_playlists )
- {
- if (desktop == null || desktop == ""){
- warning("Client %s attempting to register without desktop entry being set on the mpris root",
- dbus_name);
- return;
- }
- if (desktop in this.settings_manager.fetch_blacklist()) {
- debug ("Client %s attempting to register but I'm afraid it is blacklisted",
- desktop);
- return;
- }
-
- debug ( "client_has_become_available %s", desktop );
- AppInfo? app_info = create_app_info ( desktop.concat( ".desktop" ) );
- if ( app_info == null ){
- warning ( "Could not create app_info for path %s \n Getting out of here ",
- desktop );
- return;
- }
-
- var mpris_key = desktop;
- bool is_preferred = desktop in this.settings_manager.fetch_preferred ();
-
- mpris_to_desktop.set (dbus_name, desktop);
- if ( this.registered_clients.has_key (mpris_key) == false ){
- debug("New client has registered that we have not seen before: %s", dbus_name );
- PlayerController ctrl = new PlayerController ( this.root_menu,
- app_info,
- dbus_name,
- this.fetch_icon_name(desktop),
- this.calculate_menu_position(),
- use_playlists,
- PlayerController.state.READY,
- is_preferred);
- this.registered_clients.set ( mpris_key, ctrl );
- debug ( "Have not seen this %s before, new controller created.", desktop );
- this.settings_manager.add_interested ( desktop );
- this.establish_file_monitoring (app_info, mpris_key);
- debug ( "application added to the interested list" );
- }
- else{
- this.registered_clients[mpris_key].use_playlists = use_playlists;
- this.registered_clients[mpris_key].update_state ( PlayerController.state.READY );
- this.registered_clients[mpris_key].activate ( dbus_name );
- debug("Application has already registered - awaken the hibernation: %s with playlists %s \n", dbus_name, use_playlists.to_string() );
- }
- }
-
- public void client_has_vanished ( string mpris_root_interface )
- {
- debug("\n MusicPlayerBridge -> client with dbus interface %s has vanished",
- mpris_root_interface );
- if (root_menu != null){
- debug("\n attempt to remove %s", mpris_root_interface);
- if (mpris_to_desktop.has_key(mpris_root_interface)){
- var mpris_key = mpris_to_desktop[mpris_root_interface];
- mpris_to_desktop.unset(mpris_root_interface);
- if ( mpris_key != null && this.registered_clients.has_key(mpris_key)){
- registered_clients[mpris_key].hibernate();
- debug("\n Successively offlined client %s", mpris_key);
- }
- }
- }
- }
-
- public void set_root_menu_item ( Dbusmenu.Menuitem menu )
- {
- this.root_menu = menu;
- this.try_to_add_inactive_familiar_clients();
- this.watcher = new Mpris2Watcher ();
- this.watcher.client_appeared.connect (this.client_has_become_available);
- this.watcher.client_disappeared.connect (this.client_has_vanished);
- }
-
- public void enable_player_specific_items_for_client (string object_path,
- string desktop_id)
- {
- var mpris_key = desktop_id;
- if (this.registered_clients.has_key (mpris_key) == false){
- warning ("we don't have a client with desktop id %s registered", desktop_id);
- return;
- }
- this.registered_clients[mpris_key].enable_player_specific_items(object_path);
- }
-
- public void enable_track_specific_items_for_client (string object_path,
- string desktop_id)
- {
- var mpris_key = desktop_id;
- if (this.registered_clients.has_key (mpris_key) == false){
- warning ("we don't have a client with desktop id %s registered", desktop_id);
- return;
- }
- this.registered_clients[mpris_key].enable_track_specific_items(object_path);
- }
-
- private static AppInfo? create_app_info ( string desktop )
- {
- DesktopAppInfo info = new DesktopAppInfo ( desktop );
- if ( desktop == null || info == null ){
- warning ( "Could not create a desktopappinfo instance from app: %s", desktop );
- return null;
- }
- GLib.AppInfo app_info = info as GLib.AppInfo;
- return app_info;
- }
-
- private static string? fetch_icon_name(string desktop)
- {
- // We know the appinfo is good because it was loaded in the previous reg step.
- DesktopAppInfo info = new DesktopAppInfo ( desktop.concat( ".desktop" ) ) ;
- KeyFile desktop_keyfile = new KeyFile ();
- try{
- desktop_keyfile.load_from_file (info.get_filename(), KeyFileFlags.NONE);
- }
- catch(GLib.FileError error){
- warning("Error loading keyfile - FileError");
- return null;
- }
- catch(GLib.KeyFileError error){
- warning("Error loading keyfile - KeyFileError");
- return null;
- }
-
- try{
- return desktop_keyfile.get_string (KeyFileDesktop.GROUP,
- KeyFileDesktop.KEY_ICON);
- }
- catch(GLib.KeyFileError error){
- warning("Error trying to fetch the icon name from the keyfile");
- return null;
- }
- }
-}
-
-
-
-
diff --git a/src/mute-menu-item.c b/src/mute-menu-item.c
deleted file mode 100644
index 0e6a46f..0000000
--- a/src/mute-menu-item.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib/gi18n.h>
-
-#include "common-defs.h"
-#include "mute-menu-item.h"
-#include "pulseaudio-mgr.h"
-
-typedef struct _MuteMenuItemPrivate MuteMenuItemPrivate;
-
-struct _MuteMenuItemPrivate {
- DbusmenuMenuitem* button;
-};
-
-#define MUTE_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MUTE_MENU_ITEM_TYPE, MuteMenuItemPrivate))
-
-/* Prototypes */
-static void mute_menu_item_class_init (MuteMenuItemClass *klass);
-static void mute_menu_item_init (MuteMenuItem *self);
-static void mute_menu_item_dispose (GObject *object);
-static void mute_menu_item_finalize (GObject *object);
-static void mute_menu_item_set_global_mute_from_ui (gpointer user_data);
-
-G_DEFINE_TYPE (MuteMenuItem, mute_menu_item, G_TYPE_OBJECT);
-
-static void
-mute_menu_item_class_init (MuteMenuItemClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (MuteMenuItemPrivate));
-
- object_class->dispose = mute_menu_item_dispose;
- object_class->finalize = mute_menu_item_finalize;
-
- return;
-}
-
-static void
-mute_menu_item_init (MuteMenuItem *self)
-{
- g_debug("Building new Mute Menu Item");
- MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE(self);
- priv->button = NULL;
- priv->button = dbusmenu_menuitem_new();
-
- dbusmenu_menuitem_property_set(priv->button,
- DBUSMENU_MENUITEM_PROP_TYPE,
- DBUSMENU_MUTE_MENUITEM_TYPE);
-
- dbusmenu_menuitem_property_set_bool (priv->button,
- DBUSMENU_MENUITEM_PROP_VISIBLE,
- TRUE);
-
- g_signal_connect (G_OBJECT (priv->button),
- DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- G_CALLBACK (mute_menu_item_set_global_mute_from_ui),
- self);
- return;
-}
-
-static void
-mute_menu_item_dispose (GObject *object)
-{
- G_OBJECT_CLASS (mute_menu_item_parent_class)->dispose (object);
- return;
-}
-
-static void
-mute_menu_item_finalize (GObject *object)
-{
- G_OBJECT_CLASS (mute_menu_item_parent_class)->finalize (object);
-}
-
-static void
-mute_menu_item_set_global_mute_from_ui (gpointer user_data)
-{
- g_return_if_fail (DBUSMENU_IS_MENUITEM (user_data));
- DbusmenuMenuitem* button = DBUSMENU_MENUITEM (user_data);
- gboolean current_value = dbusmenu_menuitem_property_get_bool (button,
- DBUSMENU_MUTE_MENUITEM_VALUE);
- gboolean new_value = !current_value;
- pm_update_mute (new_value);
-}
-
-void
-mute_menu_item_update (MuteMenuItem* item, gboolean value_update)
-{
- MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item);
-
- dbusmenu_menuitem_property_set_bool (priv->button,
- DBUSMENU_MUTE_MENUITEM_VALUE,
- value_update);
- dbusmenu_menuitem_property_set (priv->button,
- DBUSMENU_MENUITEM_PROP_LABEL,
- value_update == FALSE ? _("Mute") : _("Unmute"));
-}
-
-void
-mute_menu_item_enable (MuteMenuItem* item, gboolean active)
-{
- MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item);
- dbusmenu_menuitem_property_set_bool (priv->button,
- DBUSMENU_MENUITEM_PROP_VISIBLE,
- TRUE);
-
- dbusmenu_menuitem_property_set_bool (priv->button,
- DBUSMENU_MENUITEM_PROP_ENABLED,
- active);
-}
-
-DbusmenuMenuitem*
-mute_menu_item_get_button (MuteMenuItem* item)
-{
- MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item);
- return priv->button;
-}
-
-gboolean
-mute_menu_item_is_muted (MuteMenuItem* item)
-{
- MuteMenuItemPrivate* priv = MUTE_MENU_ITEM_GET_PRIVATE (item);
- return dbusmenu_menuitem_property_get_bool (priv->button,
- DBUSMENU_MUTE_MENUITEM_VALUE);
-}
-
-MuteMenuItem*
-mute_menu_item_new (gboolean initial_update, gboolean enabled)
-{
- MuteMenuItem *self = g_object_new (MUTE_MENU_ITEM_TYPE, NULL);
- mute_menu_item_update (self, initial_update);
- mute_menu_item_enable (self, enabled);
- return self;
-}
diff --git a/src/mute-menu-item.h b/src/mute-menu-item.h
deleted file mode 100644
index 81a4b33..0000000
--- a/src/mute-menu-item.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-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 __MUTE_MENU_ITEM_H__
-#define __MUTE_MENU_ITEM_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <libdbusmenu-glib/menuitem.h>
-
-G_BEGIN_DECLS
-
-#define MUTE_MENU_ITEM_TYPE (mute_menu_item_get_type ())
-#define MUTE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTE_MENU_ITEM_TYPE, MuteMenuItem))
-#define MUTE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTE_MENU_ITEM_TYPE, MuteMenuItemClass))
-#define IS_MUTE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTE_MENU_ITEM_TYPE))
-#define IS_MUTE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTE_MENU_ITEM_TYPE))
-#define MUTE_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTE_MENU_ITEM_TYPE, MuteMenuItemClass))
-
-typedef struct _MuteMenuItem MuteMenuItem;
-typedef struct _MuteMenuItemClass MuteMenuItemClass;
-
-struct _MuteMenuItemClass {
- GObjectClass parent_class;
-};
-
-struct _MuteMenuItem {
- GObject parent;
-};
-
-GType mute_menu_item_get_type (void);
-
-MuteMenuItem* mute_menu_item_new ();
-
-void mute_menu_item_update (MuteMenuItem* item, gboolean update);
-void mute_menu_item_enable (MuteMenuItem* item, gboolean active);
-gboolean mute_menu_item_is_muted (MuteMenuItem* item);
-
-DbusmenuMenuitem* mute_menu_item_get_button (MuteMenuItem* item);
-
-G_END_DECLS
-
-#endif \ No newline at end of file
diff --git a/src/mute-widget.c b/src/mute-widget.c
deleted file mode 100644
index 500f575..0000000
--- a/src/mute-widget.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Marco Trevisan (Treviño) <mail@3v1n0.net>
-
-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.h>
-#include "mute-widget.h"
-#include "common-defs.h"
-#include "indicator-sound.h"
-
-typedef struct _MuteWidgetPrivate MuteWidgetPrivate;
-
-struct _MuteWidgetPrivate
-{
- DbusmenuMenuitem *item;
- GtkMenuItem *gitem;
-};
-
-#define MUTE_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MUTE_WIDGET_TYPE, MuteWidgetPrivate))
-
-/* Prototypes */
-static void mute_widget_class_init (MuteWidgetClass *klass);
-static void mute_widget_init (MuteWidget *self);
-static void mute_widget_dispose (GObject *object);
-static void mute_widget_finalize (GObject *object);
-
-G_DEFINE_TYPE (MuteWidget, mute_widget, G_TYPE_OBJECT);
-
-static void
-mute_widget_class_init (MuteWidgetClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->dispose = mute_widget_dispose;
- gobject_class->finalize = mute_widget_finalize;
- g_type_class_add_private (klass, sizeof (MuteWidgetPrivate));
-}
-
-static void
-mute_widget_init (MuteWidget *self)
-{
- MuteWidgetPrivate *priv = MUTE_WIDGET_GET_PRIVATE(self);
- priv->item = NULL;
- priv->gitem = GTK_MENU_ITEM(gtk_menu_item_new ());
-}
-
-static void
-mute_widget_dispose (GObject *object)
-{
- G_OBJECT_CLASS (mute_widget_parent_class)->dispose (object);
-}
-
-static void
-mute_widget_finalize (GObject *object)
-{
- MuteWidget *self = MUTE_WIDGET (object);
- MuteWidgetPrivate *priv = MUTE_WIDGET_GET_PRIVATE(self);
-
- g_object_unref (priv->item);
- g_object_unref (G_OBJECT (priv->gitem));
- G_OBJECT_CLASS (mute_widget_parent_class)->finalize (object);
-}
-
-GtkMenuItem *
-mute_widget_get_menu_item(MuteWidget *self)
-{
- MuteWidgetPrivate *priv = MUTE_WIDGET_GET_PRIVATE(self);
- return priv->gitem;
-}
-
-MuteStatus
-mute_widget_get_status (MuteWidget *self)
-{
- g_return_val_if_fail(self, MUTE_STATUS_UNAVAILABLE);
- MuteStatus status = MUTE_STATUS_UNAVAILABLE;
- MuteWidgetPrivate *priv = MUTE_WIDGET_GET_PRIVATE(self);
-
- GVariant *vstatus = dbusmenu_menuitem_property_get_variant(priv->item,
- DBUSMENU_MUTE_MENUITEM_VALUE);
-
- if (g_variant_is_of_type (vstatus, G_VARIANT_TYPE_BOOLEAN))
- {
- if (g_variant_get_boolean (vstatus))
- status = MUTE_STATUS_MUTED;
- else
- status = MUTE_STATUS_UNMUTED;
- }
-
- return status;
-}
-
-void mute_widget_toggle (MuteWidget *self)
-{
- g_return_if_fail (self);
- MuteWidgetPrivate *priv = MUTE_WIDGET_GET_PRIVATE(self);
- gtk_menu_item_activate (priv->gitem);
-}
-
-/**
- * mute_widget_new:
- * @returns: a new #MuteWidget.
- **/
-MuteWidget *
-mute_widget_new (DbusmenuMenuitem *item)
-{
- MuteWidget* widget = g_object_new(MUTE_WIDGET_TYPE, NULL);
- MuteWidgetPrivate* priv = MUTE_WIDGET_GET_PRIVATE(widget);
- priv->item = g_object_ref(item);
-
- GVariant *label = dbusmenu_menuitem_property_get_variant(priv->item,
- DBUSMENU_MENUITEM_PROP_LABEL);
-
- if (g_variant_is_of_type(label, G_VARIANT_TYPE_STRING))
- gtk_menu_item_set_label(priv->gitem, g_variant_get_string(label, NULL));
-
- return widget;
-}
diff --git a/src/mute-widget.h b/src/mute-widget.h
deleted file mode 100644
index 88ddd41..0000000
--- a/src/mute-widget.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Marco Trevisan (Treviño) <mail@3v1n0.net>
-
-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 __MUTE_WIDGET_H__
-#define __MUTE_WIDGET_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
-#include <libdbusmenu-gtk/menuitem.h>
-#include <libindicator/indicator-object.h>
-
-G_BEGIN_DECLS
-
-#define MUTE_WIDGET_TYPE (mute_widget_get_type ())
-#define MUTE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTE_WIDGET_TYPE, MuteWidget))
-#define MUTE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTE_WIDGET_TYPE, MuteWidgetClass))
-#define IS_MUTE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTE_WIDGET_TYPE))
-#define IS_MUTE_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTE_WIDGET_TYPE))
-#define MUTE_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTE_WIDGET_TYPE, MuteWidgetClass))
-
-typedef struct _MuteWidget MuteWidget;
-typedef struct _MuteWidgetClass MuteWidgetClass;
-
-struct _MuteWidgetClass {
- GObjectClass parent_class;
-};
-
-struct _MuteWidget {
- GObject parent;
-};
-
-typedef enum {
- MUTE_STATUS_UNAVAILABLE,
- MUTE_STATUS_MUTED,
- MUTE_STATUS_UNMUTED
-} MuteStatus;
-
-GType mute_widget_get_type (void) G_GNUC_CONST;
-MuteWidget* mute_widget_new (DbusmenuMenuitem *item);
-MuteStatus mute_widget_get_status (MuteWidget *self);
-void mute_widget_toggle (MuteWidget *self);
-GtkMenuItem *mute_widget_get_menu_item (MuteWidget *self);
-
-G_END_DECLS
-
-#endif
-
diff --git a/src/player-activator.vala b/src/player-activator.vala
deleted file mode 100644
index 7437a35..0000000
--- a/src/player-activator.vala
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
-Copyright 2013 Canonical Ltd.
-
-Authors:
- Marco Trevisan <marco.trevisan@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/>.
-*/
-
-[DBus (name = "org.gtk.Application")]
-public interface DBusGtkApplication : Object {
- public abstract void Activate(GLib.HashTable<string, Variant?> platform_data) throws IOError;
-}
-
-public class PlayerActivator : GLib.Object
-{
- public PlayerController owner {get; construct;}
-
- private bool gtk_application_searched = false;
- private DBusGtkApplication gtk_application;
- private Bamf.Application bamf_application;
-
- private const uint MAX_BAMF_APPLICATION_WAIT_MS = 1000;
- private int64 last_check_time;
-
- public PlayerActivator(PlayerController ctrl)
- {
- GLib.Object(owner: ctrl);
- }
-
- public void activate(uint timestamp)
- {
- if (!activate_gtk_appplication(timestamp)) {
- if (!activate_bamf_appplication(timestamp)) {
- // Let's wait BAMF to update its windows list
- this.last_check_time = get_monotonic_time();
-
- Idle.add(() => {
- bool activated = activate_bamf_appplication(timestamp);
- int64 waited = (get_monotonic_time() - this.last_check_time) / 1000;
- return !activated && waited < MAX_BAMF_APPLICATION_WAIT_MS;
- });
- }
- }
- }
-
- private bool activate_gtk_appplication(uint timestamp)
- {
- this.setup_gtk_application();
-
- if (this.gtk_application == null) {
- return false;
- }
-
- var context = Gdk.Display.get_default().get_app_launch_context();
- context.set_timestamp(timestamp);
-
- var data = new GLib.HashTable<string, Variant?>(str_hash, str_equal);
- data["desktop-startup-id"] = context.get_startup_notify_id(this.owner.app_info, new GLib.List<GLib.File>());
-
- try {
- this.gtk_application.Activate(data);
- }
- catch (IOError e) {
- return false;
- }
-
- return true;
- }
-
- private void setup_gtk_application()
- {
- if (owner.current_state != PlayerController.state.CONNECTED)
- return;
-
- if (this.gtk_application != null || this.gtk_application_searched)
- return;
-
- try {
- var connection = Bus.get_sync(BusType.SESSION);
- var name = this.owner.dbus_name;
- string gtk_application_path;
- this.find_iface_path(connection, name, "/", "org.gtk.Application", out gtk_application_path);
- this.gtk_application_searched = true;
-
- if (gtk_application_path != null) {
- this.gtk_application = Bus.get_proxy_sync(BusType.SESSION, this.owner.dbus_name, gtk_application_path);
- }
- } catch (Error e) {
- return;
- }
- }
-
- private void find_iface_path(DBusConnection connection, string name, string path, string target_iface, out string found_path)
- {
- found_path = null;
- DBusNodeInfo node = null;
-
- try {
- unowned string xml_string;
- var xml = connection.call_sync(name, path, "org.freedesktop.DBus.Introspectable", "Introspect", null, new VariantType("(s)"), DBusCallFlags.NONE, 1000);
- xml.get("(&s)", out xml_string);
- node = new DBusNodeInfo.for_xml(xml_string);
- } catch (Error e) {
- return;
- }
-
- if (node == null) {
- return;
- }
-
- foreach (var iface in node.interfaces) {
- if (iface.name == target_iface) {
- found_path = path;
- return;
- }
- }
-
- bool is_root = (path == "/");
-
- foreach (var subnode in node.nodes) {
- string new_path = path;
-
- if (!is_root) {
- new_path += "/";
- }
-
- new_path += subnode.path;
-
- find_iface_path(connection, name, new_path, target_iface, out found_path);
-
- if (found_path != null) {
- return;
- }
- }
- }
-
- private void setup_bamf_application()
- {
- this.bamf_application = null;
- var desktop_app = this.owner.app_info as DesktopAppInfo;
-
- if (desktop_app == null)
- return;
-
- foreach (var app in Bamf.Matcher.get_default().get_applications()) {
- if (app.get_desktop_file() == desktop_app.get_filename()) {
- this.bamf_application = app;
- break;
- }
- }
- }
-
- private bool activate_bamf_appplication(uint timestamp)
- {
- this.setup_bamf_application();
-
- if (this.bamf_application == null)
- return false;
-
- bool focused = false;
- var dpy = Gdk.Display.get_default();
-
- foreach (var win in this.bamf_application.get_windows()) {
- X.Window xid = 0;
-
- if (win is Bamf.Window) {
- if (win.get_window_type() != Bamf.WindowType.NORMAL)
- continue;
-
- xid = win.get_xid();
- }
- else if (win is Bamf.Tab) {
- xid = (X.Window) (win as Bamf.Tab).get_xid();
- }
-
- if (xid > 0) {
- var xwin = Gdk.X11Window.foreign_new_for_display(dpy, xid);
-
- if (xwin != null) {
- xwin.focus(timestamp);
- focused = true;
- }
- }
- }
-
- return focused;
- }
-}
diff --git a/src/player-controller.vala b/src/player-controller.vala
deleted file mode 100644
index 8c3339e..0000000
--- a/src/player-controller.vala
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using Dbusmenu;
-using Gee;
-
-public class PlayerController : GLib.Object
-{
- public const int WIDGET_QUANTITY = 4;
-
- public enum widget_order{
- SEPARATOR,
- METADATA,
- TRANSPORT,
- PLAYLISTS
- }
-
- public enum state{
- OFFLINE,
- INSTANTIATING,
- READY,
- CONNECTED,
- DISCONNECTED
- }
-
- public int current_state = state.OFFLINE;
-
- public Dbusmenu.Menuitem root_menu;
- public string dbus_name { get; set;}
- public ArrayList<PlayerItem> custom_items;
- public Mpris2Controller mpris_bridge;
- public PlayerActivator player_activator;
- public AppInfo? app_info { get; set;}
- public int menu_offset { get; set;}
- public string icon_name { get; set; }
- public bool? use_playlists;
- public bool is_preferred { get; private set; }
- private SpecificItemsManager track_specific_mgr;
- private SpecificItemsManager player_specific_mgr;
-
- public PlayerController(Dbusmenu.Menuitem root,
- GLib.AppInfo app,
- string? dbus_name,
- string icon_name,
- int offset,
- bool? use_playlists,
- state initial_state,
- bool is_preferred)
- {
- this.use_playlists = use_playlists;
- this.root_menu = root;
- this.app_info = app;
- this.dbus_name = dbus_name;
- this.icon_name = icon_name;
- this.custom_items = new ArrayList<PlayerItem>();
- this.current_state = initial_state;
- this.menu_offset = offset;
- this.is_preferred = is_preferred;
-
- this.construct_widgets();
- this.establish_mpris_connection();
- this.update_layout();
- debug ("New player controller for %s with icon name %s", this.app_info.get_name(), this.icon_name);
- }
-
- public void update_state(state new_state)
- {
- debug("update_state - player controller %s : new state %i", this.app_info.get_name(),
- new_state);
- this.current_state = new_state;
- this.update_layout();
- }
-
- public void activate( string dbus_name )
- {
- this.dbus_name = dbus_name;
- this.establish_mpris_connection();
- }
-
- /*
- instantiate()
- The user should be able to start the app from the transport bar when in an offline state
- There is a need to wait before the application is on DBus before attempting to access its mpris address
- Hence only when the it has registered with us via libindicate do we attempt to kick off mpris communication
- */
- public void instantiate(uint timestamp)
- {
- debug("instantiate in player controller for %s", this.app_info.get_name() );
-
- try{
- var context = Gdk.Display.get_default().get_app_launch_context();
- context.set_timestamp(timestamp);
- this.app_info.launch(null, context);
- this.update_state(state.INSTANTIATING);
- }
- catch(GLib.Error error){
- warning("Failed to launch app %s with error message: %s", this.app_info.get_name(),
- error.message );
- }
- }
-
- public void enable_track_specific_items (string object_path)
- {
- if (this.track_specific_mgr == null){
- track_specific_mgr = new SpecificItemsManager (this,
- object_path,
- SpecificItemsManager.category.TRACK);
- }
- }
-
- public void enable_player_specific_items (string object_path)
- {
- if (this.player_specific_mgr == null){
- player_specific_mgr = new SpecificItemsManager (this,
- object_path,
- SpecificItemsManager.category.PLAYER);
- }
- }
-
- public int track_specific_count ()
- {
- if (this.track_specific_mgr == null) {
- return 0;
- }
- return this.track_specific_mgr.proxy_items.size;
- }
-
- private void establish_mpris_connection()
- {
- if(this.current_state != state.READY || this.dbus_name == null ){
- debug("establish_mpris_connection - Not ready to connect");
- return;
- }
- debug ( " establish mpris connection - use playlists value = %s ",
- this.use_playlists.to_string() );
- this.mpris_bridge = new Mpris2Controller (this);
- this.player_activator = new PlayerActivator (this);
- this.determine_state ();
- }
-
- public void remove_from_menu()
- {
- foreach(PlayerItem item in this.custom_items){
- this.root_menu.child_delete(item);
- }
- if (this.use_playlists == true){
- PlaylistsMenuitem playlists_menuitem = this.custom_items[widget_order.PLAYLISTS] as PlaylistsMenuitem;
- this.root_menu.child_delete (playlists_menuitem.root_item);
- }
- }
-
- public void set_as_preferred (bool val) {
- this.is_preferred = val;
- this.update_layout();
- }
-
- public void hibernate()
- {
- update_state(PlayerController.state.OFFLINE);
- TransportMenuitem transport = this.custom_items[widget_order.TRANSPORT] as TransportMenuitem;
- transport.change_play_state (Transport.State.PAUSED);
- this.custom_items[widget_order.METADATA].reset(MetadataMenuitem.relevant_attributes_for_ui());
- MetadataMenuitem md = this.custom_items[widget_order.METADATA] as MetadataMenuitem;
- md.toggle_active_triangle (false);
- this.mpris_bridge = null;
- }
-
- public void update_layout()
- {
- PlaylistsMenuitem playlists_menuitem = this.custom_items[widget_order.PLAYLISTS] as PlaylistsMenuitem;
- MetadataMenuitem metadata_menuitem = this.custom_items[widget_order.METADATA] as MetadataMenuitem;
- if(this.current_state != state.CONNECTED){
- metadata_menuitem.should_collapse (true);
- playlists_menuitem.root_item.property_set_bool (MENUITEM_PROP_VISIBLE,
- false);
- this.custom_items[widget_order.TRANSPORT].property_set_bool (MENUITEM_PROP_VISIBLE, is_preferred);
- return;
- }
-
- bool should_collapse = !this.custom_items[widget_order.METADATA].populated (MetadataMenuitem.relevant_attributes_for_ui());
- metadata_menuitem.should_collapse (should_collapse);
-
- if (is_preferred){
- TransportMenuitem transport = this.custom_items[widget_order.TRANSPORT] as TransportMenuitem;
- transport.handle_cached_action();
- }
- else{
- this.custom_items[widget_order.TRANSPORT].property_set_bool (MENUITEM_PROP_VISIBLE,
- true);
- }
- playlists_menuitem.root_item.property_set_bool ( MENUITEM_PROP_VISIBLE,
- this.use_playlists );
- }
-
- private void construct_widgets()
- {
- // Separator item
- this.custom_items.add(new PlayerItem(CLIENT_TYPES_SEPARATOR));
-
- // Metadata item
- MetadataMenuitem metadata_item = new MetadataMenuitem(this);
- this.custom_items.add(metadata_item);
-
- // Transport item
- TransportMenuitem transport_item = new TransportMenuitem(this);
- this.custom_items.add(transport_item);
-
- // Playlist item
- PlaylistsMenuitem playlist_menuitem = new PlaylistsMenuitem(this);
- this.custom_items.add(playlist_menuitem);
-
- foreach(PlayerItem item in this.custom_items){
- if (this.custom_items.index_of(item) == WIDGET_QUANTITY-1) {
- PlaylistsMenuitem playlists_menuitem = item as PlaylistsMenuitem;
- root_menu.child_add_position(playlists_menuitem.root_item, this.menu_offset + this.custom_items.index_of(item));
- }
- else{
- root_menu.child_add_position (item,
- this.menu_offset + this.custom_items.index_of(item));
- }
- }
- }
-
- private void determine_state()
- {
- if(this.mpris_bridge.connected() == true){
- this.update_state(state.CONNECTED);
- MetadataMenuitem md = this.custom_items[widget_order.METADATA] as MetadataMenuitem;
- md.toggle_active_triangle(true);
- this.mpris_bridge.initial_update();
- }
- else{
- this.update_state(state.DISCONNECTED);
- }
- }
-}
diff --git a/src/player-item.vala b/src/player-item.vala
deleted file mode 100644
index 7867653..0000000
--- a/src/player-item.vala
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using Dbusmenu;
-using Gee;
-
-public class PlayerItem : Dbusmenu.Menuitem
-{
- public PlayerController owner {get; construct;}
- public string item_type { get; construct; }
- public const int EMPTY = -1;
-
- public PlayerItem(string type)
- {
- Object(item_type: type);
- }
-
- construct {
- this.property_set(MENUITEM_PROP_TYPE, item_type);
- }
-
- public void reset(HashSet<string> attrs){
- foreach(string s in attrs){
- this.property_set_int(s, EMPTY);
- }
- }
-
- /**
- * update()
- * Base update method for playeritems, takes the attributes and the incoming updates
- * and attmepts to update the appropriate props on the object.
- * Album art is handled separately to deal with remote and local file paths.
- */
- public void update(HashTable<string, Variant?> data, HashSet<string> attributes)
- {
- //debug("PlayerItem::update()");
- if(data == null){
- warning("PlayerItem::Update -> The hashtable was null - just leave it!");
- return;
- }
-
- foreach(string property in attributes){
- string[] input_keys = property.split("-");
- string search_key = input_keys[input_keys.length-1 : input_keys.length][0];
- //debug("search key = %s", search_key);
- Variant? v = data.lookup(search_key);
-
- if (v == null) continue;
-
- if (v.is_of_type ( VariantType.STRING )){
- string update = v.get_string().strip();
- //debug("with value : %s", update);
- if(property.contains("mpris:artUrl")){
- // We know its a metadata instance because thats the only
- // object with the arturl prop
- MetadataMenuitem metadata = this as MetadataMenuitem;
- metadata.fetch_art ( update, property );
- continue;
- }
- this.property_set(property, update);
- }
- else if (v.is_of_type (VariantType.INT32 )){
- //debug("with value : %i", v.get_int32());
- this.property_set_int(property, v.get_int32());
- }
- else if (v.is_of_type (VariantType.INT64 )){
- //debug("with value : %i", (int)v.get_int64());
- this.property_set_int(property, (int)v.get_int64());
- }
- else if(v.is_of_type ( VariantType.BOOLEAN )){
- //debug("with value : %s", v.get_boolean().to_string());
- this.property_set_bool(property, v.get_boolean());
- }
- }
- }
-
- public bool populated(HashSet<string> attrs)
- {
- foreach(string prop in attrs){
- if(property_get_int(prop) != EMPTY){
- return true;
- }
- }
- return false;
- }
-
-}
-
diff --git a/src/playlists-menu-item.vala b/src/playlists-menu-item.vala
deleted file mode 100644
index 4666a50..0000000
--- a/src/playlists-menu-item.vala
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-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 Config;
-using Dbusmenu;
-using DbusmenuPlaylists;
-using DbusmenuPlaylist;
-using Gee;
-
-
-public class PlaylistsMenuitem : PlayerItem
-{
- private HashMap<int, Dbusmenu.Menuitem> current_playlists;
- public Menuitem root_item;
-
- public PlaylistsMenuitem ( PlayerController parent )
- {
- Object ( item_type: MENUITEM_TYPE, owner: parent );
- }
-
- construct{
- this.current_playlists = new HashMap<int, Dbusmenu.Menuitem>();
- this.root_item = new Menuitem();
- this.root_item.property_set ( MENUITEM_PROP_LABEL, _("Choose Playlist") );
- this.root_item.property_set ( MENUITEM_PATH, "" );
- }
-
- public new void update (PlaylistDetails[] playlists)
- {
- foreach ( PlaylistDetails detail in playlists ){
- // We don't want to list playlists which are for videos)'
- if (this.already_observed(detail) || this.is_video_related(detail))
- continue;
-
- Dbusmenu.Menuitem menuitem = new Menuitem();
- menuitem.property_set (MENUITEM_PROP_LABEL,
- truncate_item_label_if_needs_be (detail.name));
- menuitem.property_set (MENUITEM_PROP_ICON_NAME, "playlist-symbolic");
-
- menuitem.property_set (MENUITEM_PATH, (string)detail.path);
- menuitem.property_set_bool (MENUITEM_PROP_VISIBLE, true);
- menuitem.property_set_bool (MENUITEM_PROP_ENABLED, true);
-
- menuitem.item_activated.connect(() => {
- submenu_item_activated (menuitem.id );
- }
- );
- this.current_playlists.set( menuitem.id, menuitem );
- this.root_item.child_append( menuitem );
- debug ("populating valid playlists %s", detail.name);
- }
- // Finally remove any that might have been deleted
- foreach (Dbusmenu.Menuitem item in this.current_playlists.values) {
- bool within = false;
- foreach (PlaylistDetails detail in playlists){
- if (detail.path == item.property_get (MENUITEM_PATH)) {
- within = true;
- break;
- }
- }
- if (within == false){
- if (this.root_item.property_get (MENUITEM_PATH) == item.property_get (MENUITEM_PATH)){
- this.root_item.property_set (MENUITEM_PROP_LABEL, _("Choose Playlist"));
- }
- this.root_item.child_delete (item);
- }
- }
- }
-
- public void update_individual_playlist (PlaylistDetails new_detail)
- {
- foreach ( Dbusmenu.Menuitem item in this.current_playlists.values ){
- if (new_detail.path == item.property_get (MENUITEM_PATH)){
- item.property_set (MENUITEM_PROP_LABEL,
- truncate_item_label_if_needs_be (new_detail.name));
- }
- }
- // If its active make sure the name is updated on the root item.
- if (this.root_item.property_get (MENUITEM_PATH) == new_detail.path) {
- this.root_item.property_set (MENUITEM_PROP_LABEL,
- truncate_item_label_if_needs_be (new_detail.name));
- }
- }
-
- private bool already_observed (PlaylistDetails new_detail)
- {
- foreach ( Dbusmenu.Menuitem item in this.current_playlists.values ){
- var path = item.property_get (MENUITEM_PATH);
- if (new_detail.path == path) return true;
- }
- return false;
- }
-
- private bool is_video_related (PlaylistDetails new_detail)
- {
- var location = (string)new_detail.path;
- if (location.contains ("/VideoLibrarySource/")) return true;
- return false;
- }
-
- public void active_playlist_update (PlaylistDetails detail)
- {
- var update = detail.name;
- if ( update == "" ) update = _("Choose Playlist");
- this.root_item.property_set (MENUITEM_PROP_LABEL,
- truncate_item_label_if_needs_be(update));
- this.root_item.property_set (MENUITEM_PATH, detail.path);
- }
-
- private void submenu_item_activated (int menu_item_id)
- {
- if (!this.current_playlists.has_key(menu_item_id)) {
- warning( "item %i was activated but we don't have a corresponding playlist",
- menu_item_id );
- return;
- }
- this.owner.mpris_bridge.activate_playlist ( (GLib.ObjectPath)this.current_playlists[menu_item_id].property_get (MENUITEM_PATH) );
- }
-
- private string truncate_item_label_if_needs_be(string item_label)
- {
- var result = item_label;
- if (item_label.char_count(-1) > 17){
- result = item_label.slice ((long)0, (long)15);
- result += "…";
- }
- return result;
- }
-
- public static HashSet<string> attributes_format()
- {
- HashSet<string> attrs = new HashSet<string>();
- attrs.add(MENUITEM_TITLE);
- attrs.add(MENUITEM_PLAYLISTS);
- return attrs;
- }
-
-}
diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c
deleted file mode 100644
index f205723..0000000
--- a/src/pulseaudio-mgr.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**Notes
- *
- * Approach now is to set up the communication channels, query the server
- * fetch its default sink/source. If this fails then fetch the list of sinks/sources
- * and take the first one which is not the auto-null sink.
- * TODO: need to handle the situation where one chink in this linear chain breaks
- * i.e. start off the process again and count the attempts (note different to
- reconnect attempts)
- */
-#include <pulse/gccmacro.h>
-#include <pulse/glib-mainloop.h>
-#include <pulse/error.h>
-
-#include "pulseaudio-mgr.h"
-#include "config.h"
-
-#define RECONNECT_DELAY 5
-
-
-static void pm_context_state_callback(pa_context *c, void *userdata);
-static void pm_subscribed_events_callback (pa_context *c,
- enum pa_subscription_event_type t,
- uint32_t index,
- void* userdata);
-static void pm_server_info_callback (pa_context *c,
- const pa_server_info *info,
- void *userdata);
-static void pm_default_sink_info_callback (pa_context *c,
- const pa_sink_info *info,
- int eol,
- void *userdata);
-static void pm_default_source_info_callback (pa_context *c,
- const pa_source_info *info,
- int eol,
- void *userdata);
-static void pm_sink_info_callback (pa_context *c,
- const pa_sink_info *sink,
- int eol,
- void *userdata);
-static void pm_source_info_callback (pa_context *c,
- const pa_source_info *info,
- int eol,
- void *userdata);
-static void pm_update_source_info_callback (pa_context *c,
- const pa_source_info *info,
- int eol,
- void *userdata);
-static void pm_sink_input_info_callback (pa_context *c,
- const pa_sink_input_info *info,
- int eol,
- void *userdata);
-static void pm_update_device (pa_context *c,
- const pa_sink_info *info,
- int eol,
- void *userdata);
-static void pm_toggle_mute_for_every_sink_callback (pa_context *c,
- const pa_sink_info *sink,
- int eol,
- void* userdata);
-static void pm_source_output_info_callback (pa_context *c,
- const pa_source_output_info *info,
- int eol,
- void *userdata);
-
-static gboolean reconnect_to_pulse (gpointer user_data);
-
-static gint connection_attempts = 0;
-static gint reconnect_idle_id = 0;
-static pa_context *pulse_context = NULL;
-static pa_glib_mainloop *pa_main_loop = NULL;
-
-/**
- Entry Point
- **/
-void
-pm_establish_pulse_connection (Device* device)
-{
- pa_main_loop = pa_glib_mainloop_new (g_main_context_default ());
- g_assert (pa_main_loop);
- reconnect_to_pulse ((gpointer)device);
-}
-
-/**
-close_pulse_activites()
-Gracefully close our connection with the Pulse async library.
-**/
-void close_pulse_activites()
-{
- if (pulse_context != NULL) {
- pa_context_unref(pulse_context);
- pulse_context = NULL;
- }
- pa_glib_mainloop_free(pa_main_loop);
- pa_main_loop = NULL;
-}
-
-/**
-reconnect_to_pulse (gpointer user_data)
-Method which connects to the pulse server and is used to track reconnects.
- */
-static gboolean
-reconnect_to_pulse (gpointer user_data)
-{
- g_debug("Attempt a pulse connection");
- g_return_val_if_fail (IS_DEVICE (user_data), FALSE);
-
- connection_attempts += 1;
- if (pulse_context != NULL) {
- pa_context_unref(pulse_context);
- pulse_context = NULL;
- }
-
- pa_proplist *proplist;
-
- proplist = pa_proplist_new ();
- pa_proplist_sets (proplist,
- PA_PROP_APPLICATION_NAME,
- "Indicator Sound");
- pa_proplist_sets (proplist,
- PA_PROP_APPLICATION_ID,
- "com.canonical.indicator.sound");
- pa_proplist_sets (proplist,
- PA_PROP_APPLICATION_ICON_NAME,
- "multimedia-volume-control");
- pa_proplist_sets (proplist,
- PA_PROP_APPLICATION_VERSION,
- PACKAGE_VERSION);
-
- pulse_context = pa_context_new_with_proplist (pa_glib_mainloop_get_api( pa_main_loop ),
- NULL,
- proplist);
- pa_proplist_free (proplist);
- g_assert(pulse_context);
- pa_context_set_state_callback (pulse_context,
- pm_context_state_callback,
- user_data);
- int result = pa_context_connect (pulse_context,
- NULL,
- (pa_context_flags_t)PA_CONTEXT_NOFAIL,
- NULL);
-
- if (result < 0) {
- g_warning ("Failed to connect context: %s",
- pa_strerror (pa_context_errno (pulse_context)));
- }
- if (connection_attempts > 5){
- return FALSE;
- }
- else{
- return TRUE;
- }
-}
-
-void
-pm_update_volume (gint sink_index, pa_cvolume new_volume)
-{
- if (sink_index < 0 || pulse_context == NULL){
- g_warning ("pm_update_volume sink index is negative or the context is null");
- return;
- }
-
- if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){
- g_warning ("pm_update_volume context is not in a ready state");
- return;
- }
-
- pa_operation *operation = NULL;
-
- operation = pa_context_set_sink_volume_by_index (pulse_context,
- sink_index,
- &new_volume,
- NULL,
- NULL);
- if (!operation){
- g_warning ("pm_update_volume operation failed for some reason");
- return;
- }
- pa_operation_unref (operation);
-}
-
-void
-pm_update_mute (gboolean update)
-{
- if (pulse_context == NULL){
- g_warning ("pm_update_mute - the context is null");
- return;
- }
-
- if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){
- g_warning ("pm_update_mute context is not in a ready state");
- return;
- }
-
- pa_operation *operation = NULL;
-
- operation = pa_context_get_sink_info_list (pulse_context,
- pm_toggle_mute_for_every_sink_callback,
- GINT_TO_POINTER (update));
- if (!operation){
- g_warning ("pm_update_mute operation failed for some reason");
- return;
- }
- pa_operation_unref (operation);
-}
-
-void
-pm_update_mic_gain (gint source_index, pa_cvolume new_gain)
-{
- if (source_index < 0 || pulse_context == NULL){
- g_warning ("pm_update_mic_gain source index is negative or the context is null");
- return;
- }
-
- if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){
- g_warning ("pm_update_mic_gain context is not in a ready state");
- return;
- }
-
- pa_operation *operation = NULL;
-
- operation = pa_context_set_source_volume_by_index (pulse_context,
- source_index,
- &new_gain,
- NULL,
- NULL);
- if (!operation){
- g_warning ("pm_update_mic_gain operation failed for some reason");
- return;
- }
- pa_operation_unref (operation);
-}
-
-void
-pm_update_mic_mute (gint source_index, gint mute_update)
-{
- if (source_index < 0){
- return;
- }
-
- if (pa_context_get_state (pulse_context) != PA_CONTEXT_READY ){
- g_warning ("pm_update_mic_mute context is not in a ready state");
- return;
- }
-
- pa_operation *operation = NULL;
-
- operation = pa_context_set_source_mute_by_index (pulse_context,
- source_index,
- mute_update,
- NULL,
- NULL);
- if (!operation){
- g_warning ("pm_update_mic_mute operation failed for some reason");
- return;
- }
- pa_operation_unref (operation);
-}
-
-/**********************************************************************************************************************/
-// Pulse-Audio asychronous call-backs
-/**********************************************************************************************************************/
-
-
-static void
-pm_subscribed_events_callback (pa_context *c,
- enum pa_subscription_event_type t,
- uint32_t index,
- void* userdata)
-{
- if (IS_DEVICE (userdata) == FALSE){
- g_critical ("subscribed events callback - our userdata is not what we think it should be");
- return;
- }
- Device* sink = DEVICE (userdata);
-
- switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
- case PA_SUBSCRIPTION_EVENT_SINK:
-
- // We don't care about any other sink other than the active one.
- if (index != device_get_sink_index (sink))
- return;
-
- if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
- device_sink_deactivated (sink);
-
- }
- else{
- pa_operation_unref (pa_context_get_sink_info_by_index (c,
- index,
- pm_update_device,
- userdata) );
- }
- break;
- case PA_SUBSCRIPTION_EVENT_SOURCE:
- g_debug ("Looks like source event of some description - index = %i", index);
- // We don't care about any other sink other than the active one.
- if (index != device_get_source_index (sink))
- return;
- if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
- g_debug ("Source removal event - index = %i", index);
- device_deactivate_voip_source (sink, FALSE);
- }
- else{
- pa_operation_unref (pa_context_get_source_info_by_index (c,
- index,
- pm_update_source_info_callback,
- userdata) );
- }
- break;
- case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
- if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
- g_debug ("some new sink input event ? - index = %i", index);
- // Maybe blocking state ?.
- pa_operation_unref (pa_context_get_sink_input_info (c,
- index,
- pm_sink_input_info_callback, userdata));
- }
- break;
- case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
- g_debug ("source output event");
- if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
- gint cached_source_output_index = device_get_voip_source_output_index (sink);
- if (index == cached_source_output_index){
- g_debug ("Just saw a source output removal event - index = %i and cached index = %i", index, cached_source_output_index);
- device_deactivate_voip_client (sink);
- }
- }
- else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
- g_debug ("some new source output event ? - index = %i", index);
- // Determine if its a VOIP app.
- pa_operation_unref (pa_context_get_source_output_info (c,
- index,
- pm_source_output_info_callback, userdata));
- }
- break;
- case PA_SUBSCRIPTION_EVENT_SERVER:
- g_debug("PA_SUBSCRIPTION_EVENT_SERVER event triggered.");
- pa_operation *o;
- if (!(o = pa_context_get_server_info (c, pm_server_info_callback, userdata))) {
- g_warning("subscribed_events_callback - pa_context_get_server_info() failed");
- return;
- }
- pa_operation_unref(o);
- break;
- }
-}
-
-static void
-pm_context_state_callback (pa_context *c, void *userdata)
-{
- switch (pa_context_get_state(c)) {
- case PA_CONTEXT_UNCONNECTED:
- g_debug("unconnected");
- break;
- case PA_CONTEXT_CONNECTING:
- g_debug("connecting - waiting for the server to become available");
- break;
- case PA_CONTEXT_AUTHORIZING:
- g_debug ("Authorizing");
- break;
- case PA_CONTEXT_SETTING_NAME:
- g_debug ("Setting name");
- break;
- case PA_CONTEXT_FAILED:
- g_warning("PA_CONTEXT_FAILED - Is PulseAudio Daemon running ?");
- device_sink_deactivated (DEVICE (userdata));
- if (reconnect_idle_id == 0){
- reconnect_idle_id = g_timeout_add_seconds (RECONNECT_DELAY,
- reconnect_to_pulse,
- (gpointer)userdata);
- }
- break;
- case PA_CONTEXT_TERMINATED:
- g_debug ("Terminated");
- device_sink_deactivated (DEVICE (userdata));
-
- if (reconnect_idle_id != 0){
- g_source_remove (reconnect_idle_id);
- reconnect_idle_id = 0;
- }
- break;
- case PA_CONTEXT_READY:
- connection_attempts = 0;
- g_debug("PA_CONTEXT_READY");
-
- if (reconnect_idle_id != 0){
- g_source_remove (reconnect_idle_id);
- reconnect_idle_id = 0;
- }
-
- pa_context_set_subscribe_callback(c, pm_subscribed_events_callback, userdata);
- pa_operation *o = NULL;
-
- o = pa_context_subscribe (c, (pa_subscription_mask_t)
- (PA_SUBSCRIPTION_MASK_SINK|
- PA_SUBSCRIPTION_MASK_SOURCE|
- PA_SUBSCRIPTION_MASK_SINK_INPUT|
- PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
- PA_SUBSCRIPTION_MASK_SERVER),
- NULL,
- NULL);
-
-
- if (!o){
- g_critical("pa_context_subscribe() failed - ?");
- return;
- }
-
- pa_operation_unref(o);
-
- o = pa_context_get_server_info (c, pm_server_info_callback, userdata);
-
- if (!o){
- g_warning("pa_context_get_server_info() failed - ?");
- return;
- }
-
- pa_operation_unref(o);
-
- break;
- }
-}
-
-/**
- After startup we go straight for the server info to see if it has details of
- the default sink and source. Normally these are valid, if there is none set
- fetch the list of each and try to determine the sink.
- **/
-static void
-pm_server_info_callback (pa_context *c,
- const pa_server_info *info,
- void *userdata)
-{
- pa_operation *operation;
- g_debug ("server info callback");
-
- if (info == NULL) {
- g_warning("No PA server - get the hell out of here");
- device_sink_deactivated (DEVICE (userdata));
- return;
- }
- // Go for the default sink
- if (info->default_sink_name != NULL) {
- g_debug ("default sink name from the server ain't null'");
- if (!(operation = pa_context_get_sink_info_by_name (c,
- info->default_sink_name,
- pm_default_sink_info_callback,
- userdata) )) {
- g_warning("pa_context_get_sink_info_by_namet() failed");
- device_sink_deactivated (DEVICE (userdata));
- pa_operation_unref(operation);
- return;
- }
- } // If there is no default sink, try to determine a sink from the list of sinks
- else if (!(operation = pa_context_get_sink_info_list(c,
- pm_sink_info_callback,
- userdata))) {
- g_warning("pa_context_get_sink_info_list() failed");
- device_sink_deactivated (DEVICE (userdata));
- pa_operation_unref(operation);
- return;
- }
- // And the source
- if (info->default_source_name != NULL) {
- g_debug ("default source name from the server is not null'");
- if (!(operation = pa_context_get_source_info_by_name (c,
- info->default_source_name,
- pm_default_source_info_callback,
- userdata) )) {
- g_warning("pa_context_get_default_source_info() failed");
- // TODO: call some input deactivate method on active sink
- pa_operation_unref(operation);
- return;
- }
- }
- else if (!(operation = pa_context_get_source_info_list(c,
- pm_source_info_callback,
- userdata))) {
- g_warning("pa_context_get_sink_info_list() failed");
- // TODO: call some input deactivate method for the source
- }
- pa_operation_unref(operation);
-}
-
-// If the server doesn't have a default sink to give us
-// we should attempt to pick up the first of the list of sinks which doesn't have
-// the name 'auto_null' (that was all really I was doing before)
-static void
-pm_sink_info_callback (pa_context *c,
- const pa_sink_info *sink,
- int eol,
- void* userdata)
-{
- if (eol > 0) {
- return;
- }
- else {
- if (IS_DEVICE (userdata) == FALSE || sink == NULL){
- g_warning ("sink info callback - our user data is not what we think it should be or the sink parameter is null");
- return;
- }
- Device* a_sink = DEVICE (userdata);
- if (device_is_sink_populated (a_sink) == FALSE &&
- g_ascii_strncasecmp("auto_null", sink->name, 9) != 0){
- device_sink_populate (a_sink, sink);
- }
- }
-}
-
-static void
-pm_default_sink_info_callback (pa_context *c,
- const pa_sink_info *info,
- int eol,
- void *userdata)
-{
- if (eol > 0) {
- return;
- }
- else {
- if (IS_DEVICE (userdata) == FALSE || info == NULL){
- g_warning ("Default sink info callback - our user data is not what we think it should be or the info parameter is null");
- return;
- }
- // Only repopulate if there is a change with regards the index
- if (device_get_sink_index (DEVICE (userdata)) == info->index)
- return;
-
- g_debug ("Pulse Server has handed us a new default sink");
- device_sink_populate (DEVICE (userdata), info);
- }
-}
-
-static void
-pm_sink_input_info_callback (pa_context *c,
- const pa_sink_input_info *info,
- int eol,
- void *userdata)
-{
- if (eol > 0) {
- return;
- }
- else {
- if (info == NULL || IS_DEVICE (userdata) == FALSE) {
- g_warning("Sink input info callback : SINK INPUT INFO IS NULL or our user_data is not what we think it should be");
- return;
- }
- Device* a_sink = DEVICE (userdata);
- // And finally check for the mute blocking state
- if (device_get_sink_index (a_sink) == info->sink){
- device_determine_blocking_state (a_sink);
- }
- }
-}
-
-static void
-pm_source_output_info_callback (pa_context *c,
- const pa_source_output_info *info,
- int eol,
- void *userdata)
-{
- if (eol > 0) {
- return;
- }
- else {
- if (info == NULL || IS_DEVICE (userdata) == FALSE) {
- g_warning("Source output callback: SOURCE OUTPUT INFO IS NULL or our user_data is not what we think it should be");
- return;
- }
-
- // Check if this is Voip sink input
- gint result = pa_proplist_contains (info->proplist, PA_PROP_MEDIA_ROLE);
- Device* a_sink = DEVICE (userdata);
-
- if (result == 1){
- //g_debug ("Source output info has media role property");
- const char* value = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE);
- //g_debug ("prop role = %s", value);
- if (g_strcmp0 (value, "phone") == 0 || g_strcmp0 (value, "production") == 0) {
- g_debug ("We have a VOIP/PRODUCTION ! - index = %i", info->index);
- device_activate_voip_item (a_sink, (gint)info->index, (gint)info->client);
- // TODO to start with we will assume our source is the same as what this 'client'
- // is pointing at. This should probably be more intelligent :
- // query for the list of source output info's and going on the name of the client
- // from the sink input ensure our voip item is using the right source.
- }
- }
- }
-}
-
-static void
-pm_update_device (pa_context *c,
- const pa_sink_info *info,
- int eol,
- void *userdata)
-{
- if (eol > 0) {
- return;
- }
- else{
- if (IS_DEVICE (userdata) == FALSE || info == NULL){
- g_warning ("update_device - our user data is not what we think it should be or the info parameter is null");
- return;
- }
- device_sink_update (DEVICE(userdata), info);
- }
-}
-
-static void
-pm_toggle_mute_for_every_sink_callback (pa_context *c,
- const pa_sink_info *sink,
- int eol,
- void* userdata)
-{
- if (eol > 0) {
- return;
- }
-
- if (sink == NULL) {
- g_warning ("toggle_mute cb - sink parameter is null - why ?");
- return;
- }
-
- pa_operation *operation = NULL;
- operation = pa_context_set_sink_mute_by_index (c,
- sink->index,
- GPOINTER_TO_INT(userdata),
- NULL,
- NULL);
- if (!operation){
- g_warning ("pm_update_mic_mute operation failed for some reason");
- return;
- }
- pa_operation_unref (operation);
-}
-
-// Source info related callbacks
-static void
-pm_default_source_info_callback (pa_context *c,
- const pa_source_info *info,
- int eol,
- void *userdata)
-{
- if (eol > 0) {
- return;
- }
- else {
- if (IS_DEVICE (userdata) == FALSE || info == NULL){
- g_warning ("Default source info callback - our user data is not what we think it should be or the source info parameter is null");
- return;
- }
- // If there is an index change we need to change our cached source
- if (device_get_source_index (DEVICE (userdata)) == info->index)
- return;
- g_debug ("Pulse Server has handed us a new default source");
- device_deactivate_voip_source (DEVICE (userdata), TRUE);
- device_update_voip_input_source (DEVICE (userdata), info);
- }
-}
-
-static void
-pm_source_info_callback (pa_context *c,
- const pa_source_info *info,
- int eol,
- void *userdata)
-{
- if (eol > 0) {
- return;
- }
- else {
- if (IS_DEVICE (userdata) == FALSE || info == NULL){
- g_warning ("source info callback - our user data is not what we think it should be or the source info parameter is null");
- return;
- }
- // For now we will take the first available
- if (device_is_voip_source_populated (DEVICE (userdata)) == FALSE){
- device_update_voip_input_source (DEVICE (userdata), info);
- }
- }
-}
-
-static void
-pm_update_source_info_callback (pa_context *c,
- const pa_source_info *info,
- int eol,
- void *userdata)
-{
- if (eol > 0) {
- return;
- }
- else {
- if (IS_DEVICE (userdata) == FALSE || info == NULL ){
- g_warning ("source info update callback - our user data is not what we think it should be or the source info paramter is null");
- return;
- }
- g_debug ("Got a source update for %s , index %i", info->name, info->index);
- device_update_voip_input_source (DEVICE (userdata), info);
- }
-}
diff --git a/src/pulseaudio-mgr.h b/src/pulseaudio-mgr.h
deleted file mode 100644
index ace47f3..0000000
--- a/src/pulseaudio-mgr.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "device.h"
-
-void pm_establish_pulse_connection (Device* device);
-void close_pulse_activites();
-void pm_update_volume (gint sink_index, pa_cvolume new_volume);
-void pm_update_mic_gain (gint source_index, pa_cvolume new_gain);
-void pm_update_mic_mute (gint source_index, int mute_update);
-void pm_update_mute (gboolean update);
-
-
-
-
-
-
diff --git a/src/scrub-menu-item.vala b/src/scrub-menu-item.vala
deleted file mode 100644
index e300050..0000000
--- a/src/scrub-menu-item.vala
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-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);
- reset(attributes_format());
- }
-
- 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_bridge.set_track_position(input_value.get_double());
- }
-
- public void update_position(int32 new_position)
- {
- this.property_set_int(MENUITEM_POSITION, new_position);
- }
-
- public void update_playstate(int state)
- {
- this.property_set_int(MENUITEM_PLAY_STATE, state);
- }
-
- 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/service.vala b/src/service.vala
new file mode 100644
index 0000000..2196135
--- /dev/null
+++ b/src/service.vala
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Lars Uebernickel <lars.uebernickel@canonical.com>
+ */
+
+/* Icon.serialize() is not yet in gio-2.0.vapi; remove this when it is */
+extern Variant? g_icon_serialize (Icon icon);
+
+public class IndicatorSound.Service {
+ public Service () {
+ this.settings = new Settings ("com.canonical.indicator.sound");
+
+ this.volume_control = new VolumeControl ();
+ this.volume_control.notify["active-mic"].connect (active_mic_changed);
+
+ this.players = new MediaPlayerList ();
+ this.players.player_added.connect (this.player_added);
+ this.players.player_removed.connect (this.player_removed);
+
+ this.actions = new SimpleActionGroup ();
+ this.actions.add_entries (action_entries, this);
+ this.actions.add_action (this.create_mute_action ());
+ this.actions.add_action (this.create_volume_action ());
+ this.actions.add_action (this.create_mic_volume_action ());
+
+ this.menu = create_menu ();
+ this.root_menu = create_root_menu (this.menu);
+
+ this.players.sync (settings.get_strv ("preferred-media-players"));
+ this.settings.changed["preferred-media-players"].connect ( () => {
+ this.players.sync (settings.get_strv ("preferred-media-players"));
+ });
+ }
+
+ public int run () {
+ if (this.loop != null) {
+ warning ("service is already running");
+ return 1;
+ }
+
+ Bus.own_name (BusType.SESSION, "com.canonical.indicator.sound", BusNameOwnerFlags.NONE,
+ this.bus_acquired, null, this.name_lost);
+
+ this.loop = new MainLoop (null, false);
+ this.loop.run ();
+
+ return 0;
+ }
+
+ const ActionEntry[] action_entries = {
+ { "root", null, null, "{ 'icon': <'audio-volume-high-panel'> }", null },
+ { "settings", activate_settings, null, null, null },
+ };
+
+ MainLoop loop;
+ SimpleActionGroup actions;
+ Menu root_menu;
+ Menu menu;
+ Settings settings;
+ VolumeControl volume_control;
+ MediaPlayerList players;
+ uint player_action_update_id;
+
+ void activate_settings (SimpleAction action, Variant? param) {
+ try {
+ Process.spawn_command_line_async ("gnome-control-center sound");
+ } catch (Error e) {
+ warning ("unable to launch sound settings: %s", e.message);
+ }
+ }
+
+ static Menu create_root_menu (Menu submenu) {
+ var root = new MenuItem (null, "indicator.root");
+ root.set_attribute ("x-canonical-type", "s", "com.canonical.indicator.root");
+ root.set_submenu (submenu);
+
+ var menu = new Menu ();
+ menu.append_item (root);
+
+ return menu;
+ }
+
+ static Menu create_menu () {
+ var volume_section = new Menu ();
+ volume_section.append ("Mute", "indicator.mute");
+
+ var slider = new MenuItem (null, "indicator.volume");
+ slider.set_attribute ("x-canonical-type", "s", "com.canonical.unity.slider");
+ slider.set_attribute_value ("min-icon", g_icon_serialize (new ThemedIcon ("audio-volume-low-zero-panel")));
+ slider.set_attribute_value ("max-icon", g_icon_serialize (new ThemedIcon ("audio-volume-high-panel")));
+ slider.set_attribute ("min-value", "d", 0.0);
+ slider.set_attribute ("max-value", "d", 1.0);
+ slider.set_attribute ("step", "d", 0.01);
+ volume_section.append_item (slider);
+
+ var menu = new Menu ();
+ menu.append_section (null, volume_section);
+ menu.append ("Sound Settings…", "indicator.settings");
+
+ return menu;
+ }
+
+ void active_mic_changed () {
+ var volume_section = this.menu.get_item_link (0, "section") as Menu;
+ if (this.volume_control.active_mic) {
+ if (volume_section.get_n_items () < 3) {
+ var slider = new MenuItem (null, "indicator.mic-volume");
+ slider.set_attribute ("x-canonical-type", "s", "com.canonical.unity.slider");
+ slider.set_attribute_value ("min-icon", g_icon_serialize (new ThemedIcon ("audio-input-microphone-low-zero-panel")));
+ slider.set_attribute_value ("max-icon", g_icon_serialize (new ThemedIcon ("audio-input-microphone-high-panel")));
+ slider.set_attribute ("min-value", "d", 0.0);
+ slider.set_attribute ("max-value", "d", 1.0);
+ slider.set_attribute ("step", "d", 0.01);
+ volume_section.append_item (slider);
+ }
+ }
+ else {
+ if (volume_section.get_n_items () > 2)
+ volume_section.remove (2);
+ }
+ }
+
+ void update_root_icon () {
+ double volume = this.volume_control.get_volume ();
+ string icon;
+ if (this.volume_control.mute)
+ icon = "audio-volume-muted-panel";
+ else if (volume <= 0.0)
+ icon = "audio-volume-low-zero-panel";
+ else if (volume <= 0.3)
+ icon = "audio-volume-low-panel";
+ else if (volume <= 0.7)
+ icon = "audio-volume-medium-panel";
+ else
+ icon = "audio-volume-high-panel";
+
+ var root_action = this.actions.lookup ("root") as SimpleAction;
+ root_action.set_state (new Variant.parsed ("{ 'icon': <%s> }", icon));
+ }
+
+ Action create_mute_action () {
+ var mute_action = new SimpleAction.stateful ("mute", null, this.volume_control.mute);
+
+ mute_action.activate.connect ( (action, param) => {
+ action.change_state (!action.get_state ().get_boolean ());
+ });
+
+ mute_action.change_state.connect ( (action, val) => {
+ volume_control.set_mute (val.get_boolean ());
+ });
+
+ this.volume_control.notify["mute"].connect ( () => {
+ mute_action.set_state (this.volume_control.mute);
+ this.update_root_icon ();
+ });
+
+ return mute_action;
+ }
+
+ void volume_changed (double volume) {
+ var volume_action = this.actions.lookup ("volume") as SimpleAction;
+ volume_action.set_state (volume);
+
+ this.update_root_icon ();
+ }
+
+ Action create_volume_action () {
+ var volume_action = new SimpleAction.stateful ("volume", null, this.volume_control.get_volume ());
+
+ volume_action.change_state.connect ( (action, val) => {
+ volume_control.set_volume (val.get_double ());
+ });
+
+ this.volume_control.volume_changed.connect (volume_changed);
+
+ this.volume_control.bind_property ("ready", volume_action, "enabled", BindingFlags.SYNC_CREATE);
+
+ return volume_action;
+ }
+
+ Action create_mic_volume_action () {
+ var volume_action = new SimpleAction.stateful ("mic-volume", null, this.volume_control.get_mic_volume ());
+
+ volume_action.change_state.connect ( (action, val) => {
+ volume_control.set_mic_volume (val.get_double ());
+ });
+
+ this.volume_control.mic_volume_changed.connect ( (volume) => {
+ volume_action.set_state (volume);
+ });
+
+ this.volume_control.bind_property ("ready", volume_action, "enabled", BindingFlags.SYNC_CREATE);
+
+ return volume_action;
+ }
+
+ void bus_acquired (DBusConnection connection, string name) {
+ try {
+ connection.export_action_group ("/com/canonical/indicator/sound", this.actions);
+ connection.export_menu_model ("/com/canonical/indicator/sound/desktop", this.root_menu);
+ } catch (Error e) {
+ critical ("%s", e.message);
+ }
+ }
+
+ void name_lost (DBusConnection connection, string name) {
+ this.loop.quit ();
+ }
+
+ Variant action_state_for_player (MediaPlayer player) {
+ var builder = new VariantBuilder (new VariantType ("a{sv}"));
+ builder.add ("{sv}", "running", new Variant ("b", player.is_running));
+ builder.add ("{sv}", "state", new Variant ("s", player.state));
+ if (player.current_track != null) {
+ builder.add ("{sv}", "title", new Variant ("s", player.current_track.title));
+ builder.add ("{sv}", "artist", new Variant ("s", player.current_track.artist));
+ builder.add ("{sv}", "album", new Variant ("s", player.current_track.album));
+ builder.add ("{sv}", "art-url", new Variant ("s", player.current_track.art_url));
+ }
+ return builder.end ();
+ }
+
+ bool update_player_actions () {
+ foreach (var player in this.players) {
+ SimpleAction? action = this.actions.lookup (player.id) as SimpleAction;
+ if (action != null)
+ action.set_state (this.action_state_for_player (player));
+ }
+
+ this.player_action_update_id = 0;
+ return false;
+ }
+
+ void eventually_update_player_actions () {
+ if (player_action_update_id == 0)
+ this.player_action_update_id = Idle.add (this.update_player_actions);
+ }
+
+ void update_preferred_players () {
+ var builder = new VariantBuilder (VariantType.STRING_ARRAY);
+ foreach (var player in this.players)
+ builder.add ("s", player.id);
+ this.settings.set_value ("preferred-media-players", builder.end ());
+ }
+
+ void player_added (MediaPlayer player) {
+ var player_item = new MenuItem (player.name, "indicator." + player.id);
+ player_item.set_attribute ("x-canonical-type", "s", "com.canonical.unity.media-player");
+ player_item.set_attribute_value ("icon", g_icon_serialize (player.icon));
+
+ var playback_item = new MenuItem (null, null);
+ playback_item.set_attribute ("x-canonical-type", "s", "com.canonical.unity.playback-item");
+ playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id);
+ playback_item.set_attribute ("x-canonical-next-action", "s", "indicator.next." + player.id);
+ playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id);
+
+ var section = new Menu ();
+ section.append_item (player_item);
+ section.append_item (playback_item);
+
+ this.menu.insert_section (this.menu.get_n_items () -1, null, section);
+
+ SimpleAction action = new SimpleAction.stateful (player.id, null, this.action_state_for_player (player));
+ action.activate.connect ( () => { player.launch (); });
+ this.actions.insert (action);
+
+ var play_action = new SimpleAction.stateful ("play." + player.id, null, player.state);
+ play_action.activate.connect ( () => player.play_pause () );
+ this.actions.insert (play_action);
+ player.notify.connect ( (object, pspec) => {
+ if (pspec.name == "state")
+ play_action.set_state (player.state);
+ });
+
+ var next_action = new SimpleAction ("next." + player.id, null);
+ next_action.activate.connect ( () => player.next () );
+ this.actions.insert (next_action);
+
+ var prev_action = new SimpleAction ("previous." + player.id, null);
+ prev_action.activate.connect ( () => player.previous () );
+ this.actions.insert (prev_action);
+
+ player.notify.connect (this.eventually_update_player_actions);
+
+ this.update_preferred_players ();
+ }
+
+ void player_removed (MediaPlayer player) {
+ this.actions.remove (player.id);
+ this.actions.remove ("play." + player.id);
+ this.actions.remove ("next." + player.id);
+ this.actions.remove ("previous." + player.id);
+
+ int n = this.menu.get_n_items ();
+ for (int i = 0; i < n; i++) {
+ var section = this.menu.get_item_link (i, Menu.LINK_SECTION);
+ string action;
+ section.get_item_attribute (0, "action", "s", out action);
+ if (action == player.id) {
+ this.menu.remove (i);
+ break;
+ }
+ }
+
+ this.update_preferred_players ();
+ }
+}
diff --git a/src/settings-manager.vala b/src/settings-manager.vala
deleted file mode 100644
index 458ac21..0000000
--- a/src/settings-manager.vala
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-using Gee;
-
-public class SettingsManager : GLib.Object
-{
- private Settings settings;
- public signal void blacklist_updates ( string[] new_blacklist );
- public signal void preferred_updates (Gee.ArrayList<string> new_preferred);
-
- public SettingsManager ( ){
- }
- construct{
- this.settings = new Settings ("com.canonical.indicator.sound");
- this.settings.changed["blacklisted-media-players"].connect (on_blacklist_event);
- this.settings.changed["preferred-media-players"].connect (on_preferred_event);
- }
-
- public string[] fetch_blacklist()
- {
- return this.settings.get_strv ("blacklisted-media-players");
- }
-
- public ArrayList<string> fetch_preferred()
- {
- var list = new ArrayList<string>();
-
- var preferred = this.settings.get_strv ("preferred-media-players");
- var interested = fetch_interested ();
-
- foreach (var s in preferred) {
- if (!(s in list) && interested.contains (s))
- list.add (s);
- }
-
- return list;
- }
-
- public ArrayList<string> fetch_interested()
- {
- var blacklisted = fetch_blacklist ();
- var interested = this.settings.get_strv ("interested-media-players");
- var list = new ArrayList<string>();
- foreach(var s in interested){
- if (s == "banshee-1"){
- s = "banshee";
- }
- if (s in list) continue;
- if (s in blacklisted) continue;
- list.add(s);
- }
- return list;
- }
-
- public void clear_list()
- {
- this.settings.reset("interested-media-players");
- }
-
- public void remove_interested (string app_desktop_name)
- {
- const string key = "interested-media-players";
- var players = new GLib.VariantBuilder (new VariantType ("as")); // array of strings
-
- foreach (var player in this.settings.get_strv (key)) {
- if (player != app_desktop_name)
- players.add ("s", player);
- }
-
- this.settings.set_value(key, players.end());
- this.settings.apply();
- }
-
- public void add_interested (string app_desktop_name)
- {
- const string key = "interested-media-players";
- var players = new GLib.VariantBuilder (new VariantType ("as")); // array of strings
-
- foreach (var player in this.settings.get_strv (key)) {
- if (player == app_desktop_name)
- return;
- players.add ("s", player);
- }
-
- players.add ("s", app_desktop_name);
- this.settings.set_value(key, players.end());
- this.settings.apply();
- }
-
- private void on_blacklist_event()
- {
- this.blacklist_updates(this.settings.get_strv ("blacklisted-media-players"));
- }
-
- private void on_preferred_event()
- {
- this.preferred_updates (this.fetch_preferred());
- }
-
- // Convenient debug method inorder to provide visability over
- // the contents of both interested and blacklisted containers in its gsettings
-/**
- private void reveal_contents()
- {
- var already_interested = this.settings.get_strv ("interested-media-players");
- foreach (var s in already_interested)
- {
- debug ("client %s is in interested array", s);
- }
- var blacklisted = this.settings.get_strv ("blacklisted-media-players");
- foreach (var s in blacklisted)
- {
- debug ("client %s is in blacklisted array", s);
- }
-
- debug ("interested array size = %i", already_interested.length);
- debug ("blacklisted array size = %i", blacklisted.length);
- }
-**/
-}
diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c
deleted file mode 100644
index dc0671c..0000000
--- a/src/slider-menu-item.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
-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 "slider-menu-item.h"
-#include "common-defs.h"
-#include "pulseaudio-mgr.h"
-
-typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate;
-
-struct _SliderMenuItemPrivate {
- Device* a_sink;
- gint index;
- gchar* name;
- gboolean mute;
- pa_cvolume volume;
- pa_channel_map channel_map;
- pa_volume_t base_volume;
-};
-
-#define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate))
-
-/* Prototypes */
-static void slider_menu_item_class_init (SliderMenuItemClass *klass);
-static void slider_menu_item_init (SliderMenuItem *self);
-static void slider_menu_item_dispose (GObject *object);
-static void slider_menu_item_finalize (GObject *object);
-static void handle_event (DbusmenuMenuitem * mi, const gchar * name,
- GVariant * value, guint timestamp);
-static pa_cvolume slider_menu_item_construct_mono_volume (const pa_cvolume* vol);
-static void slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent);
-
-G_DEFINE_TYPE (SliderMenuItem, slider_menu_item, DBUSMENU_TYPE_MENUITEM);
-
-static void
-slider_menu_item_class_init (SliderMenuItemClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (SliderMenuItemPrivate));
-
- object_class->dispose = slider_menu_item_dispose;
- object_class->finalize = slider_menu_item_finalize;
-
- DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass);
- mclass->handle_event = handle_event;
- return;
-}
-
-static void
-slider_menu_item_init (SliderMenuItem *self)
-{
- dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self),
- DBUSMENU_MENUITEM_PROP_TYPE,
- DBUSMENU_VOLUME_MENUITEM_TYPE );
-
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
-
- priv->index = NOT_ACTIVE;
- priv->name = NULL;
-
- return;
-}
-
-static void
-slider_menu_item_dispose (GObject *object)
-{
- G_OBJECT_CLASS (slider_menu_item_parent_class)->dispose (object);
- return;
-}
-
-static void
-slider_menu_item_finalize (GObject *object)
-{
- G_OBJECT_CLASS (slider_menu_item_parent_class)->finalize (object);
-}
-
-static void
-handle_event (DbusmenuMenuitem * mi,
- const gchar * name,
- GVariant * value,
- guint timestamp)
-{
- g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
- g_return_if_fail (IS_SLIDER_MENU_ITEM (mi));
-
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (SLIDER_MENU_ITEM (mi));
- gdouble volume_input = g_variant_get_double (value);
-
-/*
- g_debug ("slider menu item handle event with value %f on name %s",
- volume_input,
- name);
-*/
-
- slider_menu_item_update_volume (SLIDER_MENU_ITEM (mi), volume_input);
- if (volume_input > 0)
- device_ensure_sink_is_unmuted (priv->a_sink);
-}
-
-
-void
-slider_menu_item_populate (SliderMenuItem* self, const pa_sink_info* update)
-{
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
- priv->name = g_strdup (update->name);
- priv->index = update->index;
- priv->volume = slider_menu_item_construct_mono_volume (&update->volume);
- priv->base_volume = update->base_volume;
- priv->channel_map = update->channel_map;
- priv->mute = update->mute;
-
- pa_volume_t vol = pa_cvolume_max (&update->volume);
- gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
- GVariant* new_volume = g_variant_new_double (volume_percent);
- dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
- DBUSMENU_VOLUME_MENUITEM_LEVEL,
- new_volume);
- GVariant* new_mute_update = g_variant_new_boolean (update->mute == 1);
- dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
- DBUSMENU_VOLUME_MENUITEM_MUTE,
- new_mute_update);
-
- slider_menu_item_enable (self, TRUE);
-}
-
-// From the UI
-static void
-slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent)
-{
- g_return_if_fail (IS_SLIDER_MENU_ITEM (self));
-
- pa_cvolume mono_new_volume;
- pa_cvolume_init(&mono_new_volume);
- mono_new_volume.channels = 1;
- pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
-
- if (new_volume_value == PA_VOLUME_INVALID || new_volume_value >= PA_VOLUME_MAX){
- g_warning ("slider_menu_item_update_volume - volume is out of range !");
- return;
- }
-
- pa_cvolume_set(&mono_new_volume, 1, new_volume_value);
-
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
- if (!pa_cvolume_valid (&mono_new_volume)){
- g_warning ("Invalid volume - ignore it!");
- return;
- }
- if (!pa_channel_map_valid(&priv->channel_map)){
- g_warning ("Invalid channel map - ignore update volume!");
- return;
- }
- pa_cvolume_set(&priv->volume, priv->channel_map.channels, new_volume_value);
- pm_update_volume (priv->index, mono_new_volume);
-}
-
-// To the UI
-void
-slider_menu_item_update (SliderMenuItem* self, const pa_sink_info* update)
-{
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
-
- priv->volume = slider_menu_item_construct_mono_volume (&update->volume);
- priv->base_volume = update->base_volume;
- priv->channel_map = update->channel_map;
-
- pa_volume_t vol = pa_cvolume_max (&update->volume);
- gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
-
- GVariant* new_volume = g_variant_new_double (volume_percent);
-
-/*
- g_debug ("slider menu item update - volume update to ui to %f", volume_percent);
-*/
-
- dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
- DBUSMENU_VOLUME_MENUITEM_LEVEL,
- new_volume);
-
- if (priv->mute != update->mute){
- priv->mute = update->mute;
-/*
- g_debug ("volume menu item - update - mute on ui = %i", update->mute);
-*/
- GVariant* new_mute_update = g_variant_new_boolean (update->mute == 1);
- dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
- DBUSMENU_VOLUME_MENUITEM_MUTE,
- new_mute_update);
- }
-}
-
-/*
- * Enable/Disabled can be considered the equivalent of whether we have an active
- * sink or not, let the widget have inherent state.
- */
-void
-slider_menu_item_enable (SliderMenuItem* self, gboolean active)
-{
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
-
- dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM(self),
- DBUSMENU_MENUITEM_PROP_ENABLED,
- active);
- if(active == FALSE){
- priv->index = NOT_ACTIVE;
- if(priv->name != NULL){
- g_free(priv->name);
- priv->name = NULL;
- }
- }
-}
-
-gint
-slider_menu_item_get_sink_index (SliderMenuItem* self)
-{
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
- return priv->index;
-}
-
-static pa_cvolume
-slider_menu_item_construct_mono_volume (const pa_cvolume* vol)
-{
- pa_cvolume new_volume;
- pa_cvolume_init(&new_volume);
- new_volume.channels = 1;
- pa_volume_t max_vol = pa_cvolume_max(vol);
- pa_cvolume_set(&new_volume, 1, max_vol);
- return new_volume;
-}
-
-SliderMenuItem*
-slider_menu_item_new (Device* sink)
-{
- SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL);
- SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
- priv->a_sink = sink;
- return self;
-}
diff --git a/src/slider-menu-item.h b/src/slider-menu-item.h
deleted file mode 100644
index 4375971..0000000
--- a/src/slider-menu-item.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-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 __SLIDER_MENU_ITEM_H__
-#define __SLIDER_MENU_ITEM_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <libdbusmenu-glib/menuitem.h>
-#include "device.h"
-
-G_BEGIN_DECLS
-
-#define SLIDER_MENU_ITEM_TYPE (slider_menu_item_get_type ())
-#define SLIDER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SLIDER_MENU_ITEM_TYPE, SliderMenuItem))
-#define SLIDER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SLIDER_MENU_ITEM_TYPE, SliderMenuItemClass))
-#define IS_SLIDER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SLIDER_MENU_ITEM_TYPE))
-#define IS_SLIDER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SLIDER_MENU_ITEM_TYPE))
-#define SLIDER_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SLIDER_MENU_ITEM_TYPE, SliderMenuItemClass))
-
-typedef struct _SliderMenuItem SliderMenuItem;
-typedef struct _SliderMenuItemClass SliderMenuItemClass;
-
-struct _SliderMenuItemClass {
- DbusmenuMenuitemClass parent_class;
-};
-
-struct _SliderMenuItem {
- DbusmenuMenuitem parent;
-};
-
-GType slider_menu_item_get_type (void);
-
-void slider_menu_item_update(SliderMenuItem* item, const pa_sink_info* update);
-void slider_menu_item_enable(SliderMenuItem* item, gboolean active);
-void slider_menu_item_populate (SliderMenuItem* self, const pa_sink_info* update);
-//void
-//active_sink_update (ActiveSink* sink,
-// const pa_sink_info* update)
-
-gint slider_menu_item_get_sink_index (SliderMenuItem* self);
-
-SliderMenuItem* slider_menu_item_new (Device* sink);
-
-G_END_DECLS
-
-#endif
-
diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c
deleted file mode 100644
index 5e004cb..0000000
--- a/src/sound-service-dbus.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * 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 <gio/gio.h>
-#include <unistd.h>
-#include <glib/gi18n.h>
-#include <libindicator/indicator-service.h>
-#include <libdbusmenu-glib/server.h>
-#include <libdbusmenu-glib/client.h>
-
-#include "sound-service-dbus.h"
-#include "device.h"
-#include "gen-sound-service.xml.h"
-#include "dbus-shared-names.h"
-#include "sound-service-marshal.h"
-
-// DBUS methods
-static void bus_method_call (GDBusConnection * connection,
- const gchar * sender,
- const gchar * path,
- const gchar * interface,
- const gchar * method,
- GVariant * params,
- GDBusMethodInvocation * invocation,
- gpointer user_data);
-
-static GDBusInterfaceVTable interface_table = {
- method_call: bus_method_call,
- get_property: NULL, /* No properties */
- set_property: NULL /* No properties */
-};
-
-
-typedef struct _SoundServiceDbusPrivate SoundServiceDbusPrivate;
-
-struct _SoundServiceDbusPrivate {
- GDBusConnection* connection;
- DbusmenuMenuitem* root_menuitem;
- Device* device;
- gboolean greeter_mode;
- guint registration_id;
-};
-
-enum {
- TRACK_SPECIFIC_ITEM,
- PLAYER_SPECIFIC_ITEM,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static GDBusNodeInfo * node_info = NULL;
-static GDBusInterfaceInfo * interface_info = NULL;
-
-#define SOUND_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUND_SERVICE_DBUS_TYPE, SoundServiceDbusPrivate))
-
-static void sound_service_dbus_class_init (SoundServiceDbusClass *klass);
-static void sound_service_dbus_init (SoundServiceDbus *self);
-static void sound_service_dbus_dispose (GObject *object);
-static void sound_service_dbus_finalize (GObject *object);
-
-static void show_sound_settings_dialog (DbusmenuMenuitem *mi,
- gpointer user_data);
-static gboolean sound_service_dbus_blacklist_player (SoundServiceDbus* self,
- const gchar* player_name,
- gboolean blacklist);
-
-static gboolean sound_service_dbus_is_blacklisted (SoundServiceDbus* self,
- const gchar* player_name);
-
-G_DEFINE_TYPE (SoundServiceDbus, sound_service_dbus, G_TYPE_OBJECT);
-
-static void
-sound_service_dbus_class_init (SoundServiceDbusClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (object_class, sizeof(SoundServiceDbusPrivate));
-
- object_class->dispose = sound_service_dbus_dispose;
- object_class->finalize = sound_service_dbus_finalize;
-
- g_assert(klass != NULL);
-
- if (node_info == NULL) {
- GError * error = NULL;
-
- node_info = g_dbus_node_info_new_for_xml(_sound_service, &error);
- if (error != NULL) {
- g_critical ("Unable to parse Indicator Service Interface description: %s",
- error->message);
- g_error_free(error);
- }
- }
-
- if (interface_info == NULL) {
- interface_info = g_dbus_node_info_lookup_interface (node_info,
- INDICATOR_SOUND_DBUS_INTERFACE);
-
- if (interface_info == NULL) {
- g_critical("Unable to find interface '" INDICATOR_SOUND_DBUS_INTERFACE "'");
- }
- }
- signals[TRACK_SPECIFIC_ITEM] = g_signal_new("track-specific-item-requested",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- _sound_service_marshal_VOID__STRING_STRING,
- G_TYPE_NONE, 2, G_TYPE_STRING,
- G_TYPE_STRING);
- signals[PLAYER_SPECIFIC_ITEM] = g_signal_new("player-specific-item-requested",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- _sound_service_marshal_VOID__STRING_STRING,
- G_TYPE_NONE, 2, G_TYPE_STRING,
- G_TYPE_STRING);
-}
-
-static void
-sound_service_dbus_init (SoundServiceDbus *self)
-{
- GError *error = NULL;
- SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
-
- priv->connection = NULL;
-
- /* Fetch the session bus */
- priv->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
-
- if (error != NULL) {
- g_critical ("sound-service-dbus:Unable to connect to the session bus when creating indicator sound service : %s", error->message);
- g_error_free (error);
- return;
- }
- /* register the service on it */
- priv->registration_id = g_dbus_connection_register_object (priv->connection,
- INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
- interface_info,
- &interface_table,
- self,
- NULL,
- &error);
- if (error != NULL) {
- g_critical ("Unable to register the sound service on DBus: %s", error->message);
- g_error_free (error);
- }
-}
-
-DbusmenuMenuitem*
-sound_service_dbus_create_root_item (SoundServiceDbus* self, gboolean greeter_mode)
-{
- SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
- priv->greeter_mode = greeter_mode;
- priv->root_menuitem = dbusmenu_menuitem_new();
- DbusmenuServer *server = dbusmenu_server_new (INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH);
- dbusmenu_server_set_root (server, priv->root_menuitem);
- g_object_unref (priv->root_menuitem);
- priv->device = device_new (self);
- return priv->root_menuitem;
-}
-
-void
-sound_service_dbus_build_sound_menu ( SoundServiceDbus* self,
- DbusmenuMenuitem* mute_item,
- DbusmenuMenuitem* slider_item,
- DbusmenuMenuitem* voip_input_menu_item)
-{
- SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self);
-
- // Mute, Volume and Voip widgets
- dbusmenu_menuitem_child_add_position (priv->root_menuitem, mute_item, 0);
- dbusmenu_menuitem_child_add_position (priv->root_menuitem, slider_item, 1);
- dbusmenu_menuitem_child_add_position (priv->root_menuitem, voip_input_menu_item, 2);
-
- if (!priv->greeter_mode) {
- // Separator
- DbusmenuMenuitem* separator = dbusmenu_menuitem_new();
-
- dbusmenu_menuitem_property_set (separator,
- DBUSMENU_MENUITEM_PROP_TYPE,
- DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_add_position (priv->root_menuitem, separator, 3);
- g_object_unref (separator);
-
- // Sound preferences dialog
- DbusmenuMenuitem* settings_mi = dbusmenu_menuitem_new();
-
- dbusmenu_menuitem_property_set( settings_mi,
- DBUSMENU_MENUITEM_PROP_LABEL,
- _("Sound Settings..."));
- dbusmenu_menuitem_child_append(priv->root_menuitem, settings_mi);
- g_object_unref (settings_mi);
- g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- G_CALLBACK(show_sound_settings_dialog), NULL);
- }
-}
-
-/**
-show_sound_settings_dialog:
-Bring up the gnome volume preferences dialog
-**/
-static void
-show_sound_settings_dialog (DbusmenuMenuitem *mi,
- gpointer user_data)
-{
- GError * error = NULL;
- if (!g_spawn_command_line_async("gnome-volume-control --page=applications", &error) &&
- !g_spawn_command_line_async("gnome-control-center sound", &error) &&
- !g_spawn_command_line_async("xfce4-mixer", &error))
- {
- g_warning("Unable to show dialog: %s", error->message);
- g_error_free(error);
- }
-}
-
-static void
-sound_service_dbus_dispose (GObject *object)
-{
- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (object);
-
- if (priv->connection && priv->registration_id) {
- g_dbus_connection_unregister_object (priv->connection, priv->registration_id);
- priv->registration_id = 0;
- }
-
- g_clear_object(&priv->connection);
-
- G_OBJECT_CLASS (sound_service_dbus_parent_class)->dispose (object);
- //TODO dispose of the active sink instance !
- return;
-}
-
-static void
-sound_service_dbus_finalize (GObject *object)
-{
- G_OBJECT_CLASS (sound_service_dbus_parent_class)->finalize (object);
- return;
-}
-
-
-// EMIT STATE SIGNAL
-void
-sound_service_dbus_update_sound_state (SoundServiceDbus* self,
- SoundState new_state)
-{
- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
-
- GVariant* v_output = g_variant_new("(i)", (int)new_state);
-
- GError * error = NULL;
-
- if (priv->connection == NULL ||
- g_dbus_connection_is_closed (priv->connection) == TRUE){
- g_critical ("sound_service_dbus_update_sound_state - dbus connection is %s !!",
- priv->connection == NULL? "NULL" : "closed");
- return;
- }
-
- //g_debug ("emitting state signal with value %i", (int)new_state);
- g_dbus_connection_emit_signal( priv->connection,
- NULL,
- INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
- INDICATOR_SOUND_DBUS_INTERFACE,
- INDICATOR_SOUND_SIGNAL_STATE_UPDATE,
- v_output,
- &error );
- if (error != NULL) {
- g_critical ("Unable to emit signal because : %s", error->message);
- g_error_free(error);
- }
-}
-
-//HANDLE DBUS METHOD CALLS
-static void
-bus_method_call (GDBusConnection * connection,
- const gchar * sender,
- const gchar * path,
- const gchar * interface,
- const gchar * method,
- GVariant * params,
- GDBusMethodInvocation * invocation,
- gpointer user_data)
-{
- SoundServiceDbus* service = SOUND_SERVICE_DBUS(user_data);
- g_return_if_fail ( IS_SOUND_SERVICE_DBUS(service) );
- GVariant * retval = NULL;
- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (service);
-
- if (g_strcmp0(method, "GetSoundState") == 0) {
- g_debug("Get state - %i", device_get_state (priv->device));
- retval = g_variant_new ( "(i)", device_get_state (priv->device));
- }
- else if (g_strcmp0(method, "BlacklistMediaPlayer") == 0) {
- gboolean blacklist;
- const gchar* player_name;
- g_variant_get (params, "(&sb)", &player_name, &blacklist);
-
- g_debug ("BlacklistMediaPlayer - bool %i", blacklist);
- g_debug ("BlacklistMediaPlayer - name %s", player_name);
- gboolean result = sound_service_dbus_blacklist_player (service,
- player_name,
- blacklist);
- retval = g_variant_new ("(b)", result);
- }
- else if (g_strcmp0(method, "IsBlacklisted") == 0) {
- const gchar* player_name;
- g_variant_get (params, "(&s)", &player_name);
-
- g_debug ("IsBlacklisted - name %s", player_name);
- gboolean result = sound_service_dbus_is_blacklisted (service,
- player_name);
- retval = g_variant_new ("(b)", result);
- }
- else if (g_strcmp0(method, "EnableTrackSpecificItems") == 0) {
- g_debug ("EnableTrackSpecificItems");
- gchar* player_object_path;
- gchar* player_id;
- g_variant_get (params, "(os)", &player_object_path, &player_id);
- //g_debug ("object path = %s and id = %s", player_object_path, player_id);
- g_signal_emit (service,
- signals[TRACK_SPECIFIC_ITEM],
- 0,
- player_object_path,
- player_id);
- g_free (player_object_path);
- g_free (player_id);
-
- }
- else if (g_strcmp0(method, "EnablePlayerSpecificItems") == 0) {
- gchar* player_object_path;
- gchar* player_id;
- g_variant_get (params, "(os)", &player_object_path, &player_id);
- g_debug ("PLayer specific item - object path = %s and id = %s",
- player_object_path,
- player_id);
- g_signal_emit (service,
- signals[PLAYER_SPECIFIC_ITEM],
- 0,
- player_object_path,
- player_id);
- g_free (player_object_path);
- g_free (player_id);
- }
- else {
- g_warning("Calling method '%s' on the sound service but it's unknown", method);
- }
- g_dbus_method_invocation_return_value (invocation, retval);
-}
-
-/**
- TODO - Works nicely but refactor into at least two different methods
-**/
-static gboolean sound_service_dbus_blacklist_player (SoundServiceDbus* self,
- const gchar* player_name,
- gboolean blacklist)
-{
- g_return_val_if_fail (player_name != NULL, FALSE);
- g_return_val_if_fail (IS_SOUND_SERVICE_DBUS (self), FALSE);
-
- GVariant* the_black_list;
- gboolean result = FALSE;
- GSettings* our_settings;
- GVariantIter iter;
- gchar *str;
- GVariantBuilder builder;
-
- our_settings = g_settings_new ("com.canonical.indicator.sound");
- the_black_list = g_settings_get_value (our_settings,
- "blacklisted-media-players");
- g_variant_iter_init (&iter, the_black_list);
- g_variant_builder_init(&builder, G_VARIANT_TYPE_STRING_ARRAY);
-
- while (g_variant_iter_loop (&iter, "s", &str)){
- g_variant_builder_add (&builder, "s", str);
- }
- g_variant_iter_init (&iter, the_black_list);
-
- if (blacklist == TRUE){
- while (g_variant_iter_loop (&iter, "s", &str)){
- g_print ("first pass to check if %s is present\n", str);
- if (g_strcmp0 (player_name, str) == 0){
- // Return if its already there
- g_debug ("we have this already blacklisted, no need to do anything");
- g_variant_builder_clear (&builder);
- g_object_unref (our_settings);
- g_variant_unref (the_black_list);
- return result;
- }
- }
- // Otherwise blacklist it !
- g_debug ("about to blacklist %s", player_name);
- g_variant_builder_add (&builder, "s", player_name);
- }
- else{
- gboolean present = FALSE;
- g_variant_iter_init (&iter, the_black_list);
- g_debug ("attempting to UN-blacklist %s", player_name);
-
- while (g_variant_iter_loop (&iter, "s", &str)){
- if (g_strcmp0 (player_name, str) == 0){
- present = TRUE;
- }
- }
- // It was not there anyway, return false
- if (present == FALSE){
- g_debug ("it was not blacklisted ?, no need to do anything");
- g_variant_builder_clear (&builder);
- g_object_unref (our_settings);
- g_variant_unref (the_black_list);
- return result;
- }
-
- // Otherwise free the builder and reconstruct ensuring no duplicates.
- g_variant_builder_clear (&builder);
- g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY);
-
- g_variant_iter_init (&iter, the_black_list);
-
- while (g_variant_iter_loop (&iter, "s", &str)){
- if (g_strcmp0 (player_name, str) != 0){
- g_variant_builder_add (&builder, "s", str);
- }
- }
- }
- GVariant* value = g_variant_builder_end (&builder);
- result = g_settings_set_value (our_settings,
- "blacklisted-media-players",
- value);
-
- g_object_unref (our_settings);
- g_variant_unref (the_black_list);
-
- return result;
-}
-
-static gboolean sound_service_dbus_is_blacklisted (SoundServiceDbus *self,
- const gchar *player_name)
-{
- GSettings *our_settings;
- GVariant *the_black_list;
- GVariantIter iter;
- gchar *str;
- gboolean result = FALSE;
-
- g_return_val_if_fail (player_name != NULL, FALSE);
- g_return_val_if_fail (IS_SOUND_SERVICE_DBUS (self), FALSE);
-
- our_settings = g_settings_new ("com.canonical.indicator.sound");
- the_black_list = g_settings_get_value (our_settings,
- "blacklisted-media-players");
- g_variant_iter_init (&iter, the_black_list);
- while (g_variant_iter_next (&iter, "s", &str)){
- if (g_strcmp0 (player_name, str) == 0) {
- result = TRUE;
- g_free (str);
- break;
- }
- g_free (str);
- }
-
- g_object_unref (our_settings);
- g_variant_unref (the_black_list);
-
- return result;
-}
-
diff --git a/src/sound-service-dbus.h b/src/sound-service-dbus.h
deleted file mode 100644
index 1c15fc7..0000000
--- a/src/sound-service-dbus.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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 __SOUND_SERVICE_DBUS_H__
-#define __SOUND_SERVICE_DBUS_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <libdbusmenu-glib/menuitem.h>
-#include "common-defs.h"
-
-
-G_BEGIN_DECLS
-
-#define SOUND_SERVICE_DBUS_TYPE (sound_service_dbus_get_type ())
-#define SOUND_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SOUND_SERVICE_DBUS_TYPE, SoundServiceDbus))
-#define SOUND_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), SOUND_SERVICE_DBUS_TYPE, SoundServiceDbusClass))
-#define IS_SOUND_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SOUND_SERVICE_DBUS_TYPE))
-#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;
-
-struct _SoundData {
- SoundServiceDbus *service;
-};
-
-struct _SoundServiceDbus {
- GObject parent;
-};
-
-struct _SoundServiceDbusClass {
- GObjectClass parent_class;
-};
-
-GType sound_service_dbus_get_type (void) G_GNUC_CONST;
-
-DbusmenuMenuitem* sound_service_dbus_create_root_item (SoundServiceDbus* self, gboolean greeter_mode);
-void sound_service_dbus_update_sound_state (SoundServiceDbus* self, SoundState new_state);
-void sound_service_dbus_build_sound_menu ( SoundServiceDbus* self,
- DbusmenuMenuitem* mute_item,
- DbusmenuMenuitem* slider_item,
- DbusmenuMenuitem* voip_input_menu_item);
-
-
-G_END_DECLS
-
-#endif
diff --git a/src/sound-service-marshal.list b/src/sound-service-marshal.list
deleted file mode 100644
index 4c756d4..0000000
--- a/src/sound-service-marshal.list
+++ /dev/null
@@ -1,2 +0,0 @@
-VOID:STRING,STRING
-
diff --git a/src/sound-service.c b/src/sound-service.c
deleted file mode 100644
index 66ef7b0..0000000
--- a/src/sound-service.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-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 <locale.h>
-
-#include "sound-service.h"
-#include "pulseaudio-mgr.h"
-#include "sound-service-dbus.h"
-#include "music-player-bridge.h"
-
-static GMainLoop *mainloop = NULL;
-static MusicPlayerBridge* player_bridge = NULL;
-/***********************************************************************************************************/
-// Init and exit functions
-/**********************************************************************************************************************/
-/**
-service_shutdown:
-When the service interface starts to shutdown, we
-should follow it.
-**/
-
-void
-service_shutdown (IndicatorService *service, gpointer user_data)
-{
- if (mainloop != NULL) {
- g_debug("Service shutdown !");
- close_pulse_activites();
- g_main_loop_quit(mainloop);
- }
- return;
-}
-
-static gboolean
-get_greeter_mode (void)
-{
- const gchar *var;
- var = g_getenv("INDICATOR_GREETER_MODE");
- return (g_strcmp0(var, "1") == 0);
-}
-
-void
-on_player_specific_item_requested (SoundServiceDbus* sound_service,
- const gchar* desktop_id,
- const gchar* player_object_path,
- gpointer userdata)
-{
- if (player_bridge != NULL){
- music_player_bridge_enable_player_specific_items_for_client (player_bridge,
- desktop_id,
- player_object_path);
- }
-}
-
-void
-on_track_specific_item_requested (SoundServiceDbus* sound_service,
- const gchar* desktop_id,
- const gchar* player_object_path,
- gpointer userdata)
-{
- if (player_bridge != NULL){
- music_player_bridge_enable_track_specific_items_for_client (player_bridge,
- desktop_id,
- player_object_path);
- }
-}
-
-/**
-main:
-**/
-int
-main (int argc, char ** argv)
-{
- gboolean greeter_mode;
-
- gdk_init(&argc, &argv);
- textdomain (GETTEXT_PACKAGE);
- bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
- setlocale (LC_ALL, "");
-
- IndicatorService *service = indicator_service_new_version (INDICATOR_SOUND_DBUS_NAME,
- INDICATOR_SOUND_DBUS_VERSION);
- g_signal_connect(G_OBJECT(service),
- INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
- G_CALLBACK(service_shutdown), NULL);
-
- SoundServiceDbus* sound_service = g_object_new(SOUND_SERVICE_DBUS_TYPE, NULL);
- g_signal_connect(G_OBJECT(sound_service),
- "track-specific-item-requested",
- G_CALLBACK(on_track_specific_item_requested), NULL);
- g_signal_connect(G_OBJECT(sound_service),
- "player-specific-item-requested",
- G_CALLBACK(on_player_specific_item_requested), NULL);
-
- greeter_mode = get_greeter_mode();
-
- DbusmenuMenuitem* root_menuitem = sound_service_dbus_create_root_item(sound_service, greeter_mode);
- if (!greeter_mode) {
- player_bridge = music_player_bridge_new();
- music_player_bridge_set_root_menu_item(player_bridge, root_menuitem);
- }
-
- // Run the loop
- mainloop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(mainloop);
-
- return 0;
-}
-
-
-
-
diff --git a/src/sound-service.h b/src/sound-service.h
deleted file mode 100644
index 7c5d0c3..0000000
--- a/src/sound-service.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __INCLUDE_SOUND_SERVICE_H__
-#define __INCLUDE_SOUND_SERVICE_H__
-
-/*
-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 <config.h>
-#include <unistd.h>
-#include <glib/gi18n.h>
-
-#include <libindicator/indicator-service.h>
-
-#include "dbus-shared-names.h"
-
-// ENTRY AND EXIT POINTS
-void service_shutdown(IndicatorService * service, gpointer user_data);
-int main (int argc, char ** argv);
-
-#endif
diff --git a/src/sound-service.xml b/src/sound-service.xml
deleted file mode 100644
index cb1d928..0000000
--- a/src/sound-service.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
-<node name="/com/canonical/indicator/sound">
- <interface name="com.canonical.indicator.sound">
- <method name = "BlacklistMediaPlayer">
- <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
- <arg type='s' name='player_desktop_name' direction="in"/>
- <arg type='b' name='blacklist' direction="in"/>
- <arg type='b' name='result' direction="out"/>
- </method>
- <method name = "IsBlacklisted">
- <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
- <arg type='s' name='player_desktop_name' direction="in"/>
- <arg type='b' name='result' direction="out"/>
- </method>
- <method name = "GetSoundState">
- <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
- <arg type='i' name='current_state' direction="out"/>
- </method>
- <method name = "EnableTrackSpecificItems">
- <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
- <arg type='o' name='player_object_path' direction="in"/>
- <arg type='s' name='player_desktop_id' direction="in"/>
- </method>
- <method name = "EnablePlayerSpecificItems">
- <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
- <arg type='o' name='player_object_path' direction="in"/>
- <arg type='s' name='player_desktop_id' direction="in"/>
- </method>
- <signal name="SoundStateUpdate">
- <arg name="new_state" type="i" direction="out"/>
- </signal>
- </interface>
-</node>
-
diff --git a/src/sound-state-manager.c b/src/sound-state-manager.c
deleted file mode 100644
index c6b14ca..0000000
--- a/src/sound-state-manager.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <libindicator/indicator-image-helper.h>
-#include <libnotify/notify.h>
-
-#include "config.h"
-
-#include "sound-state-manager.h"
-#include "dbus-shared-names.h"
-#include "sound-state.h"
-
-typedef struct _SoundStateManagerPrivate SoundStateManagerPrivate;
-
-struct _SoundStateManagerPrivate
-{
- GDBusProxy* dbus_proxy;
- GHashTable* volume_states;
- GList* blocked_animation_list;
- SoundState current_state;
- GtkImage* speaker_image;
- NotifyNotification* notification;
- GSettings *settings_manager;
-};
-
-#define SOUND_STATE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUND_TYPE_STATE_MANAGER, SoundStateManagerPrivate))
-G_DEFINE_TYPE (SoundStateManager, sound_state_manager, G_TYPE_OBJECT);
-
-static GtkIconSize design_team_size;
-static gint blocked_id;
-static gint animation_id;
-static GList* blocked_iter = NULL;
-static gboolean can_animate = FALSE;
-
-//Notifications
-static void sound_state_manager_notification_init (SoundStateManager* self);
-
-//Animation/State related
-static void sound_state_manager_prepare_blocked_animation (SoundStateManager* self);
-static gboolean sound_state_manager_start_animation (gpointer user_data);
-static gboolean sound_state_manager_fade_back_to_mute_image (gpointer user_data);
-static void sound_state_manager_reset_mute_blocking_animation (SoundStateManager* self);
-static void sound_state_manager_free_the_animation_list (SoundStateManager* self);
-static void sound_state_manager_prepare_state_image_names (SoundStateManager* self);
-static void sound_state_signal_cb ( GDBusProxy* proxy,
- gchar* sender_name,
- gchar* signal_name,
- GVariant* parameters,
- gpointer user_data );
-static gboolean sound_state_manager_can_proceed_with_blocking_animation (SoundStateManager* self);
-
-
-static void
-sound_state_manager_init (SoundStateManager* self)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- priv->dbus_proxy = NULL;
- priv->volume_states = NULL;
- priv->speaker_image = NULL;
- priv->blocked_animation_list = NULL;
- priv->notification = NULL;
- priv->settings_manager = NULL;
-
- priv->settings_manager = g_settings_new("com.canonical.indicator.sound");
-
- sound_state_manager_prepare_state_image_names (self);
- sound_state_manager_prepare_blocked_animation (self);
-
- priv->current_state = UNAVAILABLE;
- priv->speaker_image = indicator_image_helper (g_hash_table_lookup (priv->volume_states,
- GINT_TO_POINTER(priv->current_state)));
-}
-
-static void
-sound_state_manager_finalize (GObject *object)
-{
- /* TODO: Add deinitalization code here */
-
- G_OBJECT_CLASS (sound_state_manager_parent_class)->finalize (object);
-}
-
-static void
-sound_state_manager_dispose (GObject *object)
-{
- SoundStateManager* self = SOUND_STATE_MANAGER (object);
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- g_hash_table_destroy (priv->volume_states);
-
- sound_state_manager_free_the_animation_list (self);
-
- if (priv->notification) {
- notify_uninit();
- }
-
- g_object_unref(priv->settings_manager);
-
- G_OBJECT_CLASS (sound_state_manager_parent_class)->dispose (object);
-}
-
-
-static void
-sound_state_manager_class_init (SoundStateManagerClass *klass)
-{
- GObjectClass* object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = sound_state_manager_finalize;
- object_class->dispose = sound_state_manager_dispose;
-
- g_type_class_add_private (klass, sizeof (SoundStateManagerPrivate));
-
- design_team_size = gtk_icon_size_register("design-team-size", 22, 22);
-}
-
-static void
-sound_state_manager_notification_init (SoundStateManager* self)
-{
- static gboolean initialized = FALSE;
-
- /* one-time lazy initialization */
- if (initialized)
- return;
- initialized = TRUE;
-
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- if (!notify_init(PACKAGE_NAME))
- return;
-
- GList* caps = notify_get_server_caps();
- gboolean has_notify_osd = FALSE;
-
- if (caps) {
- if (g_list_find_custom(caps, "x-canonical-private-synchronous",
- (GCompareFunc) g_strcmp0)) {
- has_notify_osd = TRUE;
- }
- g_list_foreach(caps, (GFunc) g_free, NULL);
- g_list_free(caps);
- }
-
- if (has_notify_osd) {
- priv->notification = notify_notification_new(PACKAGE_NAME, NULL, NULL);
- notify_notification_set_hint_string(priv->notification,
- "x-canonical-private-synchronous", PACKAGE_NAME);
- }
-}
-
-void
-sound_state_manager_show_notification (SoundStateManager *self,
- double value)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- sound_state_manager_notification_init (self);
-
- if (priv->notification == NULL ||
- g_settings_get_boolean (priv->settings_manager, "show-notify-osd-on-scroll") == FALSE){
- return;
- }
-
- char *icon;
- const int notify_value = CLAMP((int)value, -1, 101);
-
- SoundState state = sound_state_get_from_volume ((int)value);
-
- if (state == ZERO_LEVEL) {
- // Not available for all the themes
- icon = "notification-audio-volume-off";
- } else if (state == LOW_LEVEL) {
- icon = "notification-audio-volume-low";
- } else if (state == MEDIUM_LEVEL) {
- icon = "notification-audio-volume-medium";
- } else if (state == HIGH_LEVEL) {
- icon = "notification-audio-volume-high";
- } else {
- icon = "notification-audio-volume-muted";
- }
-
- notify_notification_update(priv->notification, PACKAGE_NAME, NULL, icon);
- notify_notification_set_hint_int32(priv->notification, "value", notify_value);
- notify_notification_show(priv->notification, NULL);
-}
-
-
-/*
-Prepare states versus images names hash.
-*/
-static void
-sound_state_manager_prepare_state_image_names (SoundStateManager* self)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
- priv->volume_states = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
-
- g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(MUTED), g_strdup("audio-volume-muted-panel"));
- g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(ZERO_LEVEL), g_strdup("audio-volume-low-zero-panel"));
- g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(LOW_LEVEL), g_strdup("audio-volume-low-panel"));
- g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(MEDIUM_LEVEL), g_strdup("audio-volume-medium-panel"));
- g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(HIGH_LEVEL), g_strdup("audio-volume-high-panel"));
- g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(BLOCKED), g_strdup("audio-volume-muted-blocking-panel"));
- g_hash_table_insert (priv->volume_states, GINT_TO_POINTER(UNAVAILABLE), g_strdup("audio-output-none-panel"));
-}
-
-/*
-prepare_blocked_animation:
-Prepares the array of images to be used in the blocked animation.
-Only called at startup.
-*/
-static void
-sound_state_manager_prepare_blocked_animation (SoundStateManager* self)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- gchar* blocked_name = g_hash_table_lookup(priv->volume_states,
- GINT_TO_POINTER(BLOCKED));
- gchar* muted_name = g_hash_table_lookup(priv->volume_states,
- GINT_TO_POINTER(MUTED));
-
- GtkImage* temp_image = indicator_image_helper(muted_name);
- GdkPixbuf* mute_buf = gtk_image_get_pixbuf(temp_image);
-
- temp_image = indicator_image_helper(blocked_name);
- GdkPixbuf* blocked_buf = gtk_image_get_pixbuf(temp_image);
-
- if (mute_buf == NULL || blocked_buf == NULL) {
- //g_debug("Don bother with the animation, the theme aint got the goods !");
- return;
- }
-
- int i;
-
- // sample 51 snapshots - range : 0-256
- for (i = 0; i < 51; i++) {
- gdk_pixbuf_composite(mute_buf, blocked_buf, 0, 0,
- gdk_pixbuf_get_width(mute_buf),
- gdk_pixbuf_get_height(mute_buf),
- 0, 0, 1, 1, GDK_INTERP_BILINEAR, MIN(255, i * 5));
- priv->blocked_animation_list = g_list_append(priv->blocked_animation_list,
- gdk_pixbuf_copy(blocked_buf));
- }
- can_animate = TRUE;
- g_object_ref_sink(mute_buf);
- g_object_unref(mute_buf);
- g_object_ref_sink(blocked_buf);
- g_object_unref(blocked_buf);
-}
-
-
-GtkImage*
-sound_state_manager_get_current_icon (SoundStateManager* self)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
- return priv->speaker_image;
-}
-
-SoundState
-sound_state_manager_get_current_state (SoundStateManager* self)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
- return priv->current_state;
-}
-
-/**
- * sound_state_manager_connect_to_dbus:
- * @returns: void
- * When ready the indicator-sound calls this method to enable state communication
- * between the indicator and the service.
- **/
-void
-sound_state_manager_connect_to_dbus (SoundStateManager* self, GDBusProxy* proxy)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
- priv->dbus_proxy = proxy;
- g_signal_connect (priv->dbus_proxy, "g-signal",
- G_CALLBACK (sound_state_signal_cb), self);
-
- g_dbus_proxy_call ( priv->dbus_proxy,
- "GetSoundState",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- (GAsyncReadyCallback)sound_state_manager_get_state_cb,
- self);
-}
-
-void
-sound_state_manager_get_state_cb (GObject *object,
- GAsyncResult *res,
- gpointer user_data)
-{
- g_return_if_fail (SOUND_IS_STATE_MANAGER (user_data));
- SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- GVariant *result, *value;
- GError *error = NULL;
- result = g_dbus_proxy_call_finish ( priv->dbus_proxy,
- res,
- &error );
-
- if (error != NULL) {
- g_warning("get_sound_state call failed: %s", error->message);
- g_error_free(error);
- return;
- }
-
- value = g_variant_get_child_value(result, 0);
- priv->current_state = (SoundState)g_variant_get_int32(value);
-
- gchar* image_name = g_hash_table_lookup (priv->volume_states,
- GINT_TO_POINTER(priv->current_state) );
- indicator_image_helper_update (priv->speaker_image, image_name);
-
- g_variant_unref(value);
- g_variant_unref(result);
-}
-
-void
-sound_state_manager_deal_with_disconnect (SoundStateManager* self)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
- priv->current_state = UNAVAILABLE;
-
- gchar* image_name = g_hash_table_lookup (priv->volume_states,
- GINT_TO_POINTER(priv->current_state) );
- indicator_image_helper_update (priv->speaker_image, image_name);
-}
-
-static void
-sound_state_signal_cb ( GDBusProxy* proxy,
- gchar* sender_name,
- gchar* signal_name,
- GVariant* parameters,
- gpointer user_data)
-{
- //g_debug ( "!!! sound state manager signal_cb" );
-
- g_return_if_fail (SOUND_IS_STATE_MANAGER (user_data));
- SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- g_variant_ref (parameters);
- GVariant *value = g_variant_get_child_value (parameters, 0);
- gint update = g_variant_get_int32 (value);
-
- //g_debug ( "!!! signal_cb with value %i", update);
-
- priv->current_state = (SoundState)update;
-
- g_variant_unref (parameters);
-
- if (g_strcmp0(signal_name, INDICATOR_SOUND_SIGNAL_STATE_UPDATE) == 0){
-
- gchar* image_name = g_hash_table_lookup (priv->volume_states,
- GINT_TO_POINTER(priv->current_state) );
- if (priv->current_state == BLOCKED &&
- sound_state_manager_can_proceed_with_blocking_animation (self) == TRUE) {
- blocked_id = g_timeout_add_seconds (4,
- sound_state_manager_start_animation,
- self);
- indicator_image_helper_update (priv->speaker_image, image_name);
- }
- else{
- indicator_image_helper_update (priv->speaker_image, image_name);
- }
- }
- else {
- g_warning ("sorry don't know what signal this is - %s", signal_name);
- }
-}
-
-void
-sound_state_manager_style_changed_cb (GtkWidget *widget,
- GtkStyle *previous_style,
- gpointer user_data)
-{
- g_debug("Just caught a style change event");
- g_return_if_fail (SOUND_IS_STATE_MANAGER (user_data));
- SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
- sound_state_manager_reset_mute_blocking_animation (self);
- sound_state_manager_free_the_animation_list (self);
- sound_state_manager_prepare_blocked_animation (self);
-}
-
-static void
-sound_state_manager_reset_mute_blocking_animation (SoundStateManager* self)
-{
- if (animation_id != 0) {
- //g_debug("about to remove the animation_id callback from the mainloop!!**");
- g_source_remove(animation_id);
- animation_id = 0;
- }
- if (blocked_id != 0) {
- //g_debug("about to remove the blocked_id callback from the mainloop!!**");
- g_source_remove(blocked_id);
- blocked_id = 0;
- }
-}
-
-static void
-sound_state_manager_free_the_animation_list (SoundStateManager* self)
-{
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- if (priv->blocked_animation_list != NULL) {
- g_list_foreach (priv->blocked_animation_list, (GFunc)g_object_unref, NULL);
- g_list_free (priv->blocked_animation_list);
- priv->blocked_animation_list = NULL;
- }
-}
-
-
-static gboolean
-sound_state_manager_start_animation (gpointer userdata)
-{
- g_return_val_if_fail (SOUND_IS_STATE_MANAGER (userdata), FALSE);
- SoundStateManager* self = SOUND_STATE_MANAGER (userdata);
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE(self);
-
- blocked_iter = priv->blocked_animation_list;
- blocked_id = 0;
- animation_id = g_timeout_add (50,
- sound_state_manager_fade_back_to_mute_image,
- self);
- return FALSE;
-}
-
-static gboolean
-sound_state_manager_fade_back_to_mute_image (gpointer user_data)
-{
- g_return_val_if_fail (SOUND_IS_STATE_MANAGER (user_data), FALSE);
- SoundStateManager* self = SOUND_STATE_MANAGER (user_data);
- SoundStateManagerPrivate* priv = SOUND_STATE_MANAGER_GET_PRIVATE (self);
-
- if (blocked_iter != NULL) {
- gtk_image_set_from_pixbuf (priv->speaker_image, blocked_iter->data);
- blocked_iter = blocked_iter->next;
- return TRUE;
- } else {
- animation_id = 0;
- //g_debug("exit from animation now\n");
- g_dbus_proxy_call ( priv->dbus_proxy,
- "GetSoundState",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- (GAsyncReadyCallback)sound_state_manager_get_state_cb,
- self);
-
- return FALSE;
- }
-}
-
-
-// Simple static helper to determine if the coast is clear to animate
-static
-gboolean sound_state_manager_can_proceed_with_blocking_animation (SoundStateManager* self)
-{
- return (can_animate && blocked_id == 0 && animation_id == 0 );
-}
-
diff --git a/src/sound-state-manager.h b/src/sound-state-manager.h
deleted file mode 100644
index 9287897..0000000
--- a/src/sound-state-manager.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _SOUND_STATE_MANAGER_H_
-#define _SOUND_STATE_MANAGER_H_
-
-#include <glib.h>
-#include "common-defs.h"
-
-G_BEGIN_DECLS
-
-#define SOUND_TYPE_STATE_MANAGER (sound_state_manager_get_type ())
-#define SOUND_STATE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUND_TYPE_STATE_MANAGER, SoundStateManager))
-#define SOUND_STATE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUND_TYPE_STATE_MANAGER, SoundStateManagerClass))
-#define SOUND_IS_STATE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUND_TYPE_STATE_MANAGER))
-#define SOUND_IS_STATE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUND_TYPE_STATE_MANAGER))
-#define SOUND_STATE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUND_TYPE_STATE_MANAGER, SoundStateManagerClass))
-
-typedef struct _SoundStateManagerClass SoundStateManagerClass;
-typedef struct _SoundStateManager SoundStateManager;
-
-struct _SoundStateManagerClass
-{
- GObjectClass parent_class;
-};
-
-struct _SoundStateManager
-{
- GObject parent_instance;
-};
-
-GType sound_state_manager_get_type (void) G_GNUC_CONST;
-
-void sound_state_manager_style_changed_cb (GtkWidget *widget,
- GtkStyle *previous_style,
- gpointer user_data);
-GtkImage* sound_state_manager_get_current_icon (SoundStateManager* self);
-SoundState sound_state_manager_get_current_state (SoundStateManager* self);
-void sound_state_manager_connect_to_dbus (SoundStateManager* self,
- GDBusProxy* proxy);
-void sound_state_manager_deal_with_disconnect (SoundStateManager* self);
-void sound_state_manager_get_state_cb (GObject *object,
- GAsyncResult *res,
- gpointer user_data);
-void sound_state_manager_show_notification (SoundStateManager *self,
- double value);
-
-
-G_END_DECLS
-
-#endif /* _SOUND_STATE_MANAGER_H_ */
diff --git a/src/sound-state.c b/src/sound-state.c
deleted file mode 100644
index 72e411a..0000000
--- a/src/sound-state.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-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 "config.h"
-
-#include "sound-state.h"
-
-SoundState
-sound_state_get_from_volume (int volume_percent)
-{
- SoundState state = LOW_LEVEL;
-
- if (volume_percent < 30 && volume_percent > 0) {
- state = LOW_LEVEL;
- }
- else if (volume_percent < 70 && volume_percent >= 30) {
- state = MEDIUM_LEVEL;
- }
- else if (volume_percent >= 70) {
- state = HIGH_LEVEL;
- }
- else if (volume_percent <= 0) {
- state = ZERO_LEVEL;
- }
- return state;
-}
-
diff --git a/src/sound-state.h b/src/sound-state.h
deleted file mode 100644
index 9527c8e..0000000
--- a/src/sound-state.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _SOUND_STATE_H_
-#define _SOUND_STATE_H_
-
-#include <glib.h>
-#include "common-defs.h"
-
-/* Helper functions for determining SOUNDSTATE */
-
-SoundState sound_state_get_from_volume (int volume_percent);
-
-#endif /* _SOUND_STATE_H_ */
-
diff --git a/src/specific-items-manager.vala b/src/specific-items-manager.vala
deleted file mode 100644
index 923cf3f..0000000
--- a/src/specific-items-manager.vala
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using Dbusmenu;
-using Gee;
-
-public class SpecificItemsManager : GLib.Object
-{
- public enum category{
- TRACK,
- PLAYER
- }
-
- private PlayerController owner {get; set;}
- private string dbus_path;
- private Dbusmenu.Client client;
- public Gee.ArrayList<Dbusmenu.MenuitemProxy> proxy_items {get; construct;}
- private int of_type;
-
- public SpecificItemsManager (PlayerController controller,
- string path,
- category which_type)
- {
- this.of_type = which_type;
- this.owner = controller;
- this.dbus_path = path;
- this.client = new Dbusmenu.Client (this.owner.dbus_name, this.dbus_path);
- this.client.root_changed.connect (on_root_changed);
- }
- construct{
- this.proxy_items = new ArrayList<Dbusmenu.MenuitemProxy>();
- }
-
- private int figure_out_positioning()
- {
- int result = 0 ;
- if (this.of_type == category.TRACK){
- result = this.owner.menu_offset + this.owner.WIDGET_QUANTITY + this.proxy_items.size;
- }
- else if (this.of_type == category.PLAYER){
- int pos = this.owner.menu_offset + this.owner.WIDGET_QUANTITY + this.owner.track_specific_count();
- //Surely the playlists item is there whether its visible or not ?
- //TODO test playlists and player specific item positioning.
- pos += this.owner.use_playlists == true ? 1 : 0;
- result = pos;
- }
- debug ("!!!!! Menu pos of type %i is = %i", this.of_type, result);
- return result;
- }
-
- private void on_root_changed (GLib.Object? newroot)
- {
- if (newroot == null){
- debug ("root disappeared -remove proxyitems");
- foreach(var p in proxy_items){
- this.owner.root_menu.child_delete (p);
- }
- this.proxy_items.clear();
- debug ("array list size is now %i", this.proxy_items.size);
- //this.proxy_items = new ArrayList<Dbusmenu.MenuitemProxy>();
- return;
- }
-
- Dbusmenu.Menuitem? root = this.client.get_root();
- root.child_added.connect (on_child_added);
- root.child_removed.connect (on_child_removed);
-
- // Fetch what children are there already.
- GLib.List<weak void*> children = root.get_children().copy();
-
- foreach (void* child in children) {
- int pos = figure_out_positioning();
- unowned Dbusmenu.Menuitem item = (Dbusmenu.Menuitem)child;
- Dbusmenu.MenuitemProxy proxy = new Dbusmenu.MenuitemProxy(item);
- proxy_items.add (proxy);
- debug ("Proxy item of label = %s added to collection",
- item.property_get (MENUITEM_PROP_LABEL));
- this.owner.root_menu.child_add_position (proxy, pos);
-
- }
- }
-
- private void on_child_added (GLib.Object child, uint position)
- {
- debug ("On child added Specific root node");
- }
-
- private void on_child_removed (GLib.Object child)
- {
- debug ("On child removed Specific root node");
- }
-
-}
diff --git a/src/transport-menu-item.vala b/src/transport-menu-item.vala
deleted file mode 100644
index 2a77d5a..0000000
--- a/src/transport-menu-item.vala
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-using Dbusmenu;
-using Gee;
-using DbusmenuTransport;
-using Transport;
-
-public class TransportMenuitem : PlayerItem
-{
- private Transport.Action cached_action;
-
- private bool running {
- get{
- return this.owner.current_state == PlayerController.state.CONNECTED;
- }
- }
-
- public TransportMenuitem(PlayerController parent)
- {
- Object(item_type: MENUITEM_TYPE, owner: parent);
- }
- construct{
- this.property_set_int(MENUITEM_PLAY_STATE, (int)Transport.State.PAUSED);
- this.property_set (MENUITEM_PROP_LABEL, this.owner.app_info.get_name());
- this.cached_action = Transport.Action.NO_ACTION;
- }
-
- /**
- Please remove this timeout when the default player can handle mpris commands
- immediately once it raises its dbus interface
- **/
- public void handle_cached_action()
- {
- if (this.cached_action != Transport.Action.NO_ACTION){
- Timeout.add_seconds (1, send_cached_action);
- }
- }
-
- private bool send_cached_action()
- {
- this.owner.mpris_bridge.transport_update(this.cached_action);
- this.cached_action = Transport.Action.NO_ACTION;
- return false;
- }
-
- public void change_play_state (Transport.State update)
- {
- int temp = (int)update;
- this.property_set_int(MENUITEM_PLAY_STATE, temp);
- }
-
- public override void handle_event(string name,
- Variant input_value,
- uint timestamp)
- {
- if (name != DbusmenuTransport.MENUITEM_STATE_CHANGE)
- return;
-
- Variant v = input_value;
- if ( input_value.is_of_type (VariantType.VARIANT)){
- v = input_value.get_variant();
- }
-
- int32 input = v.get_int32();
-
- if (this.running == true){
- this.owner.mpris_bridge.transport_update((Transport.Action)input);
- }
- else{
- this.cached_action = (Transport.Action)input;
- this.owner.instantiate(timestamp);
- this.property_set_int (MENUITEM_PLAY_STATE, (int)Transport.State.LAUNCHING);
- }
- }
-
- public static HashSet<string> attributes_format()
- {
- HashSet<string> attrs = new HashSet<string>();
- attrs.add(MENUITEM_PLAY_STATE);
- return attrs;
- }
-
-}
diff --git a/src/transport-widget.c b/src/transport-widget.c
deleted file mode 100644
index 7df656e..0000000
--- a/src/transport-widget.c
+++ /dev/null
@@ -1,1886 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
- Mirco Müller <mirco.mueller@canonical.com>
- Andrea Cimitan <andrea.cimitan@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/>.
-
-Uses code from ctk
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <math.h>
-#include "transport-widget.h"
-
-
-#define RECT_WIDTH 130.0f
-#define Y 7.0f
-#define X 70.0f
-#define INNER_RADIUS 12.5
-#define MIDDLE_RADIUS 13.0f
-#define OUTER_RADIUS 14.5f
-#define CIRCLE_RADIUS 21.0f
-#define PREV_WIDTH 25.0f
-#define PREV_HEIGHT 17.0f
-#define NEXT_WIDTH 25.0f //PREV_WIDTH
-#define NEXT_HEIGHT 17.0f //PREV_HEIGHT
-#define TRI_WIDTH 11.0f
-#define TRI_HEIGHT 13.0f
-#define TRI_OFFSET 6.0f
-#define PREV_X 68.0f
-#define PREV_Y 13.0f
-#define NEXT_X 146.0f
-#define NEXT_Y 13.0f //prev_y
-#define PAUSE_WIDTH 21.0f
-#define PAUSE_HEIGHT 27.0f
-#define BAR_WIDTH 4.5f
-#define BAR_HEIGHT 24.0f
-#define BAR_OFFSET 10.0f
-#define PAUSE_X 111.0f
-#define PAUSE_Y 7.0f
-#define PLAY_WIDTH 28.0f
-#define PLAY_HEIGHT 29.0f
-#define PLAY_PADDING 5.0f
-#define INNER_START_SHADE 0.98
-#define INNER_END_SHADE 0.98
-#define MIDDLE_START_SHADE 1.0
-#define MIDDLE_END_SHADE 1.0
-#define OUTER_START_SHADE 0.75
-#define OUTER_END_SHADE 1.3
-#define SHADOW_BUTTON_SHADE 0.8
-#define OUTER_PLAY_START_SHADE 0.7
-#define OUTER_PLAY_END_SHADE 1.38
-#define BUTTON_START_SHADE 1.1
-#define BUTTON_END_SHADE 0.9
-#define BUTTON_SHADOW_SHADE 0.8
-#define INNER_COMPRESSED_START_SHADE 1.0
-#define INNER_COMPRESSED_END_SHADE 1.0
-
-typedef struct _TransportWidgetPrivate TransportWidgetPrivate;
-
-struct _TransportWidgetPrivate
-{
- TransportAction current_command;
- TransportAction key_event;
- TransportAction motion_event;
- TransportState current_state;
- GHashTable* command_coordinates;
- DbusmenuMenuitem* twin_item;
- gboolean has_focus;
- gint hold_timer;
- gint skip_frequency;
-};
-
-#if GTK_CHECK_VERSION(3, 0, 0)
-static GList *transport_widget_list = NULL;
-static GtkStyleContext *spinner_style_context = NULL;
-static GtkWidgetPath *spinner_widget_path = NULL;
-#endif
-
-// TODO refactor the UI handlers, consolidate functionality between key press /release
-// and button press / release.
-#define TRANSPORT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRANSPORT_WIDGET_TYPE, TransportWidgetPrivate))
-
-/* Gobject boiler plate */
-static void transport_widget_class_init (TransportWidgetClass *klass);
-static void transport_widget_init (TransportWidget *self);
-static void transport_widget_dispose (GObject *object);
-static void transport_widget_finalize (GObject *object);
-G_DEFINE_TYPE (TransportWidget, transport_widget, GTK_TYPE_MENU_ITEM);
-
-/* essentials */
-static void transport_widget_set_twin_item ( TransportWidget* self,
- DbusmenuMenuitem* twin_item);
-#if ! GTK_CHECK_VERSION(3, 0, 0)
-static gboolean transport_widget_expose ( GtkWidget *button, GdkEventExpose *event);
-#endif
-static gboolean draw (GtkWidget* button, cairo_t *cr);
-
-/* UI and dbusmenu callbacks */
-static gboolean transport_widget_button_press_event (GtkWidget *menuitem,
- GdkEventButton *event);
-static gboolean transport_widget_button_release_event (GtkWidget *menuitem,
- GdkEventButton *event);
-static gboolean transport_widget_motion_notify_event (GtkWidget *menuitem,
- GdkEventMotion *event);
-static gboolean transport_widget_leave_notify_event (GtkWidget *menuitem,
- GdkEventCrossing *event);
-static void transport_widget_property_update ( DbusmenuMenuitem* item,
- gchar * property,
- GVariant * value,
- gpointer userdata );
-static void transport_widget_menu_hidden ( GtkWidget *menu,
- TransportWidget *transport);
-static void transport_widget_notify ( GObject *item,
- GParamSpec *pspec,
- gpointer user_data );
-static TransportAction transport_widget_determine_button_event ( TransportWidget* button,
- GdkEventButton* event);
-static TransportAction transport_widget_determine_motion_event ( TransportWidget* button,
- GdkEventMotion* event);
-static void transport_widget_react_to_button_release ( TransportWidget* button,
- TransportAction command);
-static void transport_widget_toggle_play_pause ( TransportWidget* button,
- TransportState update);
-static void transport_widget_select (GtkWidget* menu, gpointer Userdata);
-static void transport_widget_deselect (GtkWidget* menu, gpointer Userdata);
-static TransportAction transport_widget_collision_detection (gint x, gint y);
-static void transport_widget_start_timing (TransportWidget* widget);
-static gboolean transport_widget_trigger_seek (gpointer userdata);
-static gboolean transport_widget_seek (gpointer userdata);
-
-
-/// Init functions //////////////////////////////////////////////////////////
-static void
-transport_widget_class_init (TransportWidgetClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (TransportWidgetPrivate));
-
- widget_class->button_press_event = transport_widget_button_press_event;
- widget_class->button_release_event = transport_widget_button_release_event;
- widget_class->motion_notify_event = transport_widget_motion_notify_event;
- widget_class->leave_notify_event = transport_widget_leave_notify_event;
-#if GTK_CHECK_VERSION(3, 0, 0)
- widget_class->draw = draw;
-#else
- widget_class->expose_event = transport_widget_expose;
-#endif
-
- gobject_class->dispose = transport_widget_dispose;
- gobject_class->finalize = transport_widget_finalize;
-}
-
-static void
-transport_widget_init (TransportWidget *self)
-{
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(self);
- #if GTK_CHECK_VERSION(3, 0, 0)
- if (transport_widget_list == NULL){
- /* append the object to the static linked list. */
- transport_widget_list = g_list_append (transport_widget_list, self);
-
- /* create widget path */
- spinner_widget_path = gtk_widget_path_new();
-
- gtk_widget_path_append_type (spinner_widget_path, GTK_TYPE_MENU);
- gtk_widget_path_append_type (spinner_widget_path, GTK_TYPE_MENU_ITEM);
- gint pos = gtk_widget_path_append_type (spinner_widget_path, GTK_TYPE_SPINNER);
- gtk_widget_path_iter_set_name (spinner_widget_path, pos, "IndicatorSoundSpinner");
-
- /* create style context and append path */
- spinner_style_context = gtk_style_context_new();
-
- gtk_style_context_set_path (spinner_style_context, spinner_widget_path);
- gtk_style_context_add_class (spinner_style_context, GTK_STYLE_CLASS_MENU);
- gtk_style_context_add_class (spinner_style_context, GTK_STYLE_CLASS_MENUITEM);
- gtk_style_context_add_class (spinner_style_context, GTK_STYLE_CLASS_SPINNER);
- }
- #endif
- priv->current_command = TRANSPORT_ACTION_NO_ACTION;
- priv->current_state = TRANSPORT_STATE_PAUSED;
- priv->key_event = TRANSPORT_ACTION_NO_ACTION;
- priv->motion_event = TRANSPORT_ACTION_NO_ACTION;
- priv->has_focus = FALSE;
- priv->hold_timer = 0;
- priv->skip_frequency = 0;
- 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(5), 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_ACTION_PREVIOUS),
- previous_list);
-
- GList* play_list = NULL;
- play_list = g_list_insert(play_list, GINT_TO_POINTER(58), 0);
- play_list = g_list_insert(play_list, GINT_TO_POINTER(0), 1);
- play_list = g_list_insert(play_list, GINT_TO_POINTER(50), 2);
- play_list = g_list_insert(play_list, GINT_TO_POINTER(43), 3);
-
- g_hash_table_insert(priv->command_coordinates,
- GINT_TO_POINTER(TRANSPORT_ACTION_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(5), 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_ACTION_NEXT),
- next_list);
- gtk_widget_set_size_request(GTK_WIDGET(self), 200, 43);
- g_signal_connect (G_OBJECT(self),
- "notify",
- G_CALLBACK (transport_widget_notify),
- NULL);
- g_signal_connect (G_OBJECT(self),
- "select",
- G_CALLBACK (transport_widget_select),
- NULL);
- g_signal_connect (G_OBJECT(self),
- "deselect",
- G_CALLBACK (transport_widget_deselect),
- NULL);
- gtk_widget_realize ( GTK_WIDGET (self) );
-
-}
-
-static void
-transport_widget_dispose (GObject *object)
-{
- #if GTK_CHECK_VERSION(3, 0, 0)
- transport_widget_list = g_list_remove (transport_widget_list, object);
-
- if (transport_widget_list == NULL){
- if (spinner_widget_path != NULL){
- gtk_widget_path_free (spinner_widget_path);
- spinner_widget_path = NULL;
- }
-
- if (spinner_style_context != NULL){
- g_object_unref (spinner_style_context);
- spinner_style_context = NULL;
- }
- }
- #endif
-
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(object);
- if (priv->command_coordinates != NULL) {
- g_hash_table_destroy (priv->command_coordinates);
- priv->command_coordinates = NULL;
- }
-
- G_OBJECT_CLASS (transport_widget_parent_class)->dispose (object);
-}
-
-static void
-transport_widget_finalize (GObject *object)
-{
-
-
- G_OBJECT_CLASS (transport_widget_parent_class)->finalize (object);
-}
-
-#if ! GTK_CHECK_VERSION(3, 0, 0)
-static gboolean
-transport_widget_expose (GtkWidget *button, GdkEventExpose *event)
-{
- cairo_t *cr;
- cr = gdk_cairo_create (gtk_widget_get_window (button));
-
- cairo_rectangle (cr,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
-
- cairo_clip(cr);
- draw (button, cr);
-
- cairo_destroy (cr);
- return FALSE;
-}
-#endif
-
-gboolean
-transport_widget_is_selected ( TransportWidget* widget )
-{
- g_return_val_if_fail (IS_TRANSPORT_WIDGET (widget), FALSE);
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(widget);
- return priv->has_focus;
-}
-
-static void
-transport_widget_toggle_play_pause(TransportWidget* button,
- TransportState update)
-{
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button);
- priv->current_state = update;
- gtk_widget_queue_draw (GTK_WIDGET(button));
-}
-
-static void
-transport_widget_notify ( GObject *item,
- GParamSpec *pspec,
- gpointer user_data )
-{
- if (g_strcmp0 (pspec->name, "parent")){
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (item));
- if (parent){
- g_signal_connect ( parent, "hide",
- G_CALLBACK (transport_widget_menu_hidden),
- item );
- }
- }
-}
-
-static void
-transport_widget_menu_hidden ( GtkWidget *menu,
- TransportWidget *transport)
-{
- g_return_if_fail(IS_TRANSPORT_WIDGET(transport));
- transport_widget_react_to_button_release(transport, TRANSPORT_ACTION_NO_ACTION);
-}
-
-static gboolean
-transport_widget_motion_notify_event (GtkWidget *menuitem,
- GdkEventMotion *event)
-{
- //g_debug("transport_widget_motion_notify_event()");
-
- g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE );
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) );
- TransportAction result = transport_widget_determine_motion_event ( TRANSPORT_WIDGET(menuitem),
- event);
- priv->motion_event = result;
- gtk_widget_queue_draw (menuitem);
- if (priv->hold_timer != 0){
- g_source_remove (priv->hold_timer);
- priv->hold_timer = 0;
- }
- if(priv->skip_frequency != 0){
- g_source_remove (priv->skip_frequency);
- priv->skip_frequency = 0;
- }
- return TRUE;
-}
-
-static gboolean
-transport_widget_leave_notify_event (GtkWidget *menuitem,
- GdkEventCrossing *event)
-{
- //g_debug("transport_widget_leave_notify_event()");
-
- g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE );
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) );
-
- priv->motion_event = TRANSPORT_ACTION_NO_ACTION;
- priv->current_command = TRANSPORT_ACTION_NO_ACTION;
- gtk_widget_queue_draw (GTK_WIDGET(menuitem));
-
- return TRUE;
-}
-
-static gboolean
-transport_widget_button_press_event (GtkWidget *menuitem,
- GdkEventButton *event)
-{
- //g_debug("transport_widget_button_press_event()");
-
- g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE );
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) );
- TransportAction result = transport_widget_determine_button_event ( TRANSPORT_WIDGET(menuitem),
- event);
- if(result != TRANSPORT_ACTION_NO_ACTION){
- priv->current_command = result;
- gtk_widget_queue_draw (GTK_WIDGET(menuitem));
- if (priv->current_command == TRANSPORT_ACTION_PREVIOUS ||
- priv->current_command == TRANSPORT_ACTION_NEXT){
- transport_widget_start_timing (TRANSPORT_WIDGET(menuitem));
- }
- }
- return TRUE;
-}
-/**
- * TODO rename or merge
- * @param widget
- */
-static void
-transport_widget_start_timing (TransportWidget* widget)
-{
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE (widget);
- if (priv->hold_timer == 0){
- priv->hold_timer = g_timeout_add (800,
- transport_widget_trigger_seek,
- widget);
- }
-}
-
-static gboolean
-transport_widget_trigger_seek (gpointer userdata)
-{
- g_return_val_if_fail ( IS_TRANSPORT_WIDGET(userdata), FALSE );
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE (TRANSPORT_WIDGET(userdata));
- if (priv->skip_frequency == 0){
- priv->skip_frequency = g_timeout_add (100,
- transport_widget_seek,
- userdata);
- }
- priv->hold_timer = 0;
- return FALSE;
-}
-
-/**
- * This will be called repeatedly until a key/button release is received
- * @param userdata
- * @return
- */
-static gboolean
-transport_widget_seek (gpointer userdata)
-{
- g_return_val_if_fail ( IS_TRANSPORT_WIDGET(userdata), FALSE );
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE (TRANSPORT_WIDGET(userdata));
- GVariant* new_transport_state;
- if(priv->current_command == TRANSPORT_ACTION_NEXT){
- //g_debug ("we should be skipping forward");
- new_transport_state = g_variant_new_int32 ((int)TRANSPORT_ACTION_FORWIND);
-
- dbusmenu_menuitem_handle_event ( priv->twin_item,
- DBUSMENU_TRANSPORT_MENUITEM_STATE_CHANGE,
- new_transport_state,
- 0 );
-
- }
- else if(priv->current_command == TRANSPORT_ACTION_PREVIOUS){
- //g_debug ("we should be skipping back");
- new_transport_state = g_variant_new_int32 ((int)TRANSPORT_ACTION_REWIND);
-
- dbusmenu_menuitem_handle_event ( priv->twin_item,
- DBUSMENU_TRANSPORT_MENUITEM_STATE_CHANGE,
- new_transport_state,
- 0 );
- }
-
- return TRUE;
-}
-
-static gboolean
-transport_widget_button_release_event (GtkWidget *menuitem,
- GdkEventButton *event)
-{
- g_return_val_if_fail(IS_TRANSPORT_WIDGET(menuitem), FALSE);
- TransportWidget* transport = TRANSPORT_WIDGET(menuitem);
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- TransportAction result = transport_widget_determine_button_event ( transport,
- event );
- if (result != TRANSPORT_ACTION_NO_ACTION &&
- priv->current_command == result &&
- priv->skip_frequency == 0){
- GVariant* new_transport_state = g_variant_new_int32 ((int)result);
- dbusmenu_menuitem_handle_event ( priv->twin_item,
- DBUSMENU_TRANSPORT_MENUITEM_STATE_CHANGE,
- new_transport_state,
- 0 );
- }
- transport_widget_react_to_button_release ( transport,
- result );
- return TRUE;
-}
-
-static void
-transport_widget_select (GtkWidget* item, gpointer Userdata)
-{
- TransportWidget* transport = TRANSPORT_WIDGET(item);
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- priv->has_focus = TRUE;
-}
-
-static void
-transport_widget_deselect (GtkWidget* item, gpointer Userdata)
-{
- TransportWidget* transport = TRANSPORT_WIDGET(item);
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- priv->has_focus = FALSE;
-}
-
-void
-transport_widget_react_to_key_press_event ( TransportWidget* transport,
- TransportAction transport_event )
-{
- if(transport_event != TRANSPORT_ACTION_NO_ACTION){
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- priv->current_command = transport_event;
- priv->key_event = transport_event;
- gtk_widget_realize ( GTK_WIDGET(transport) );
- gtk_widget_queue_draw (GTK_WIDGET(transport) );
- if (priv->current_command == TRANSPORT_ACTION_PREVIOUS ||
- priv->current_command == TRANSPORT_ACTION_NEXT){
- transport_widget_start_timing (transport);
- }
- }
-}
-
-void
-transport_widget_react_to_key_release_event ( TransportWidget* transport,
- TransportAction transport_event )
-{
- if(transport_event != TRANSPORT_ACTION_NO_ACTION){
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- GVariant* new_transport_event = g_variant_new_int32((int)transport_event);
- if (priv->skip_frequency == 0){
- dbusmenu_menuitem_handle_event ( priv->twin_item,
- DBUSMENU_TRANSPORT_MENUITEM_STATE_CHANGE,
- new_transport_event,
- 0 );
- }
- }
- transport_widget_react_to_button_release ( transport,
- transport_event );
-}
-
-void
-transport_widget_focus_update ( TransportWidget* transport, gboolean focus )
-{
- TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- priv->has_focus = focus;
-}
-
-static TransportAction
-transport_widget_determine_button_event( TransportWidget* button,
- GdkEventButton* event )
-{
- return transport_widget_collision_detection (event->x, event->y);
-}
-
-static TransportAction
-transport_widget_determine_motion_event( TransportWidget* button,
- GdkEventMotion* event )
-{
- return transport_widget_collision_detection (event->x, event->y);
-}
-
-static TransportAction
-transport_widget_collision_detection ( gint x,
- gint y )
-{
- TransportAction event = TRANSPORT_ACTION_NO_ACTION;
-
- if (x > 57 && x < 102
- && y > 12 && y < 40){
- event = TRANSPORT_ACTION_PREVIOUS;
- }
- else if (x > 101 && x < 143
- && y > 5 && y < 47){
- event = TRANSPORT_ACTION_PLAY_PAUSE;
- }
- else if (x > 142 && x < 187
- && y > 12 && y < 40){
- event = TRANSPORT_ACTION_NEXT;
- }
- return event;
-}
-
-static void
-transport_widget_react_to_button_release ( TransportWidget* button,
- TransportAction command )
-{
- g_return_if_fail(IS_TRANSPORT_WIDGET(button));
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button);
-
- priv->current_command = TRANSPORT_ACTION_NO_ACTION;
- priv->key_event = TRANSPORT_ACTION_NO_ACTION;
-
- gtk_widget_queue_draw (GTK_WIDGET(button));
- if (priv->hold_timer != 0){
- g_source_remove (priv->hold_timer);
- priv->hold_timer = 0;
- }
- if(priv->skip_frequency != 0){
- g_source_remove (priv->skip_frequency);
- priv->skip_frequency = 0;
- }
-}
-
-/// internal helper functions //////////////////////////////////////////////////
-
-static void
-draw_gradient (cairo_t* cr,
- double x,
- double y,
- double w,
- double r,
- double* rgba_start,
- double* rgba_end)
-{
- cairo_pattern_t* pattern = NULL;
-
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x + w - 2.0f * r, y);
- cairo_arc (cr,
- x + w - 2.0f * r,
- y + r,
- r,
- -90.0f * G_PI / 180.0f,
- 90.0f * G_PI / 180.0f);
- cairo_line_to (cr, x, y + 2.0f * r);
- cairo_arc (cr,
- x,
- y + r,
- r,
- 90.0f * G_PI / 180.0f,
- 270.0f * G_PI / 180.0f);
- cairo_close_path (cr);
-
- pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r);
- cairo_pattern_add_color_stop_rgba (pattern,
- 0.0f,
- rgba_start[0],
- rgba_start[1],
- rgba_start[2],
- rgba_start[3]);
- cairo_pattern_add_color_stop_rgba (pattern,
- 1.0f,
- rgba_end[0],
- rgba_end[1],
- rgba_end[2],
- rgba_end[3]);
- cairo_set_source (cr, pattern);
- cairo_fill (cr);
- cairo_pattern_destroy (pattern);
-}
-
-static void
-draw_circle (cairo_t* cr,
- double x,
- double y,
- double r,
- double* rgba_start,
- double* rgba_end)
-{
- cairo_pattern_t* pattern = NULL;
-
- cairo_move_to (cr, x, y);
- cairo_arc (cr,
- x + r,
- y + r,
- r,
- 0.0f * G_PI / 180.0f,
- 360.0f * G_PI / 180.0f);
-
- pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r);
- cairo_pattern_add_color_stop_rgba (pattern,
- 0.0f,
- rgba_start[0],
- rgba_start[1],
- rgba_start[2],
- rgba_start[3]);
- cairo_pattern_add_color_stop_rgba (pattern,
- 1.0f,
- rgba_end[0],
- rgba_end[1],
- rgba_end[2],
- rgba_end[3]);
- cairo_set_source (cr, pattern);
- cairo_fill (cr);
- cairo_pattern_destroy (pattern);
-}
-
-static void
-_setup (cairo_t** cr,
- cairo_surface_t** surf,
- gint width,
- gint height)
-{
- if (!cr || !surf)
- return;
-
- *surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
- *cr = cairo_create (*surf);
- cairo_scale (*cr, 1.0f, 1.0f);
- cairo_set_operator (*cr, CAIRO_OPERATOR_CLEAR);
- cairo_paint (*cr);
- cairo_set_operator (*cr, CAIRO_OPERATOR_OVER);
-}
-
-static void
-_mask_prev (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 + tri_height / 2.0f);
- cairo_line_to (cr, x + tri_width, y);
- cairo_line_to (cr, x + tri_width, y + tri_height);
- x += tri_offset;
- cairo_move_to (cr, x, y + tri_height / 2.0f);
- cairo_line_to (cr, x + tri_width, y);
- cairo_line_to (cr, x + tri_width, y + tri_height);
- x -= tri_offset;
- cairo_rectangle (cr, x, y, 2.5f, tri_height);
- cairo_close_path (cr);
-}
-
-static void
-_mask_next (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);
- x += tri_offset;
- 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);
- x -= tri_offset;
- x += 2.0f * tri_width - tri_offset - 1.0f;
- cairo_rectangle (cr, x, y, 2.5f, tri_height);
-
- cairo_close_path (cr);
-}
-
-static void
-_mask_pause (cairo_t* cr,
- double x,
- double y,
- double bar_width,
- double bar_height,
- double bar_offset)
-{
- if (!cr)
- return;
-
- cairo_set_line_width (cr, bar_width);
- cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
-
- x += bar_width;
- y += bar_width;
- cairo_move_to (cr, x, y);
- cairo_line_to (cr, x, y + bar_height);
- cairo_move_to (cr, x + bar_offset, y);
- cairo_line_to (cr, x + bar_offset, y + bar_height);
-
-}
-
-static void
-_mask_play (cairo_t* cr,
- double x,
- double y,
- double tri_width,
- double tri_height)
-{
- 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,
- double x_end,
- double y_end,
- double* rgba_start,
- double* rgba_end,
- gboolean stroke)
-{
- cairo_pattern_t* pattern = NULL;
-
- if (!cr || !rgba_start || !rgba_end)
- return;
-
- pattern = cairo_pattern_create_linear (x_start, y_start, x_end, y_end);
- cairo_pattern_add_color_stop_rgba (pattern,
- 0.0f,
- rgba_start[0],
- rgba_start[1],
- rgba_start[2],
- rgba_start[3]);
- cairo_pattern_add_color_stop_rgba (pattern,
- 1.0f,
- rgba_end[0],
- rgba_end[1],
- rgba_end[2],
- rgba_end[3]);
- cairo_set_source (cr, pattern);
- if (stroke)
- cairo_stroke (cr);
- else
- cairo_fill (cr);
- cairo_pattern_destroy (pattern);
-}
-
-static void
-_finalize (cairo_t* cr,
- cairo_t** cr_surf,
- cairo_surface_t** surf,
- double x,
- double y)
-{
- if (!cr || !cr_surf || !surf)
- return;
-
- cairo_set_source_surface (cr, *surf, x, y);
- cairo_paint (cr);
- cairo_surface_destroy (*surf);
- cairo_destroy (*cr_surf);
-}
-
-static void
-_finalize_repaint (cairo_t* cr,
- cairo_t** cr_surf,
- cairo_surface_t** surf,
- double x,
- double y,
- int repaints)
-{
- if (!cr || !cr_surf || !surf)
- return;
-
- while (repaints > 0)
- {
- cairo_set_source_surface (cr, *surf, x, y);
- cairo_paint (cr);
- repaints--;
- }
-
- cairo_surface_destroy (*surf);
- cairo_destroy (*cr_surf);
-}
-
-static void
-_color_rgb_to_hls (gdouble *r,
- gdouble *g,
- gdouble *b)
-{
- gdouble min;
- gdouble max;
- gdouble red;
- gdouble green;
- gdouble blue;
- gdouble h = 0;
- gdouble l;
- gdouble s;
- gdouble delta;
-
- red = *r;
- green = *g;
- blue = *b;
-
- if (red > green)
- {
- if (red > blue)
- max = red;
- else
- max = blue;
-
- if (green < blue)
- min = green;
- else
- min = blue;
- }
- else
- {
- if (green > blue)
- max = green;
- else
- max = blue;
-
- if (red < blue)
- min = red;
- else
- min = blue;
- }
- l = (max+min)/2;
- if (fabs (max-min) < 0.0001)
- {
- h = 0;
- s = 0;
- }
- else
- {
- if (l <= 0.5)
- s = (max-min)/(max+min);
- else
- s = (max-min)/(2-max-min);
-
- delta = (max -min) != 0 ? (max -min) : 1;
-
- if(delta == 0)
- delta = 1;
- if (red == max)
- h = (green-blue)/delta;
- else if (green == max)
- h = 2+(blue-red)/delta;
- else if (blue == max)
- h = 4+(red-green)/delta;
-
- h *= 60;
- if (h < 0.0)
- h += 360;
- }
-
- *r = h;
- *g = l;
- *b = s;
-}
-
-static void
-_color_hls_to_rgb (gdouble *h,
- gdouble *l,
- gdouble *s)
-{
- gdouble hue;
- gdouble lightness;
- gdouble saturation;
- gdouble m1, m2;
- gdouble r, g, b;
-
- lightness = *l;
- saturation = *s;
-
- if (lightness <= 0.5)
- m2 = lightness*(1+saturation);
- else
- m2 = lightness+saturation-lightness*saturation;
-
- m1 = 2*lightness-m2;
-
- if (saturation == 0)
- {
- *h = lightness;
- *l = lightness;
- *s = lightness;
- }
- else
- {
- hue = *h+120;
- while (hue > 360)
- hue -= 360;
- while (hue < 0)
- hue += 360;
-
- if (hue < 60)
- r = m1+(m2-m1)*hue/60;
- else if (hue < 180)
- r = m2;
- else if (hue < 240)
- r = m1+(m2-m1)*(240-hue)/60;
- else
- r = m1;
-
- hue = *h;
- while (hue > 360)
- hue -= 360;
- while (hue < 0)
- hue += 360;
-
- if (hue < 60)
- g = m1+(m2-m1)*hue/60;
- else if (hue < 180)
- g = m2;
- else if (hue < 240)
- g = m1+(m2-m1)*(240-hue)/60;
- else
- g = m1;
-
- hue = *h-120;
- while (hue > 360)
- hue -= 360;
- while (hue < 0)
- hue += 360;
-
- if (hue < 60)
- b = m1+(m2-m1)*hue/60;
- else if (hue < 180)
- b = m2;
- else if (hue < 240)
- b = m1+(m2-m1)*(240-hue)/60;
- else
- b = m1;
-
- *h = r;
- *l = g;
- *s = b;
- }
-}
-
-void
-_color_shade (const CairoColorRGB *a, float k, CairoColorRGB *b)
-{
- double red;
- double green;
- double blue;
-
- red = a->r;
- green = a->g;
- blue = a->b;
-
- if (k == 1.0)
- {
- b->r = red;
- b->g = green;
- b->b = blue;
- return;
- }
-
- _color_rgb_to_hls (&red, &green, &blue);
-
- green *= k;
- if (green > 1.0)
- green = 1.0;
- else if (green < 0.0)
- green = 0.0;
-
- blue *= k;
- if (blue > 1.0)
- blue = 1.0;
- else if (blue < 0.0)
- blue = 0.0;
-
- _color_hls_to_rgb (&red, &green, &blue);
-
- b->r = red;
- b->g = green;
- b->b = blue;
-}
-
-static inline void
-_blurinner (guchar* pixel,
- gint* zR,
- gint* zG,
- gint* zB,
- gint* zA,
- gint alpha,
- gint aprec,
- gint zprec)
-{
- gint R;
- gint G;
- gint B;
- guchar A;
-
- R = *pixel;
- G = *(pixel + 1);
- B = *(pixel + 2);
- A = *(pixel + 3);
-
- *zR += (alpha * ((R << zprec) - *zR)) >> aprec;
- *zG += (alpha * ((G << zprec) - *zG)) >> aprec;
- *zB += (alpha * ((B << zprec) - *zB)) >> aprec;
- *zA += (alpha * ((A << zprec) - *zA)) >> aprec;
-
- *pixel = *zR >> zprec;
- *(pixel + 1) = *zG >> zprec;
- *(pixel + 2) = *zB >> zprec;
- *(pixel + 3) = *zA >> zprec;
-}
-
-static inline void
-_blurrow (guchar* pixels,
- gint width,
- gint height,
- gint channels,
- gint line,
- gint alpha,
- gint aprec,
- gint zprec)
-{
- gint zR;
- gint zG;
- gint zB;
- gint zA;
- gint index;
- guchar* scanline;
-
- scanline = &(pixels[line * width * channels]);
-
- zR = *scanline << zprec;
- zG = *(scanline + 1) << zprec;
- zB = *(scanline + 2) << zprec;
- zA = *(scanline + 3) << zprec;
-
- for (index = 0; index < width; index ++)
- _blurinner (&scanline[index * channels],
- &zR,
- &zG,
- &zB,
- &zA,
- alpha,
- aprec,
- zprec);
-
- for (index = width - 2; index >= 0; index--)
- _blurinner (&scanline[index * channels],
- &zR,
- &zG,
- &zB,
- &zA,
- alpha,
- aprec,
- zprec);
-}
-
-static inline void
-_blurcol (guchar* pixels,
- gint width,
- gint height,
- gint channels,
- gint x,
- gint alpha,
- gint aprec,
- gint zprec)
-{
- gint zR;
- gint zG;
- gint zB;
- gint zA;
- gint index;
- guchar* ptr;
-
- ptr = pixels;
-
- ptr += x * channels;
-
- zR = *((guchar*) ptr ) << zprec;
- zG = *((guchar*) ptr + 1) << zprec;
- zB = *((guchar*) ptr + 2) << zprec;
- zA = *((guchar*) ptr + 3) << zprec;
-
- for (index = width; index < (height - 1) * width; index += width)
- _blurinner ((guchar*) &ptr[index * channels],
- &zR,
- &zG,
- &zB,
- &zA,
- alpha,
- aprec,
- zprec);
-
- for (index = (height - 2) * width; index >= 0; index -= width)
- _blurinner ((guchar*) &ptr[index * channels],
- &zR,
- &zG,
- &zB,
- &zA,
- alpha,
- aprec,
- zprec);
-}
-
-void
-_expblur (guchar* pixels,
- gint width,
- gint height,
- gint channels,
- gint radius,
- gint aprec,
- gint zprec)
-{
- gint alpha;
- gint row = 0;
- gint col = 0;
-
- if (radius < 1)
- return;
-
- // calculate the alpha such that 90% of
- // the kernel is within the radius.
- // (Kernel extends to infinity)
- alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f))));
-
- for (; row < height; row++)
- _blurrow (pixels,
- width,
- height,
- channels,
- row,
- alpha,
- aprec,
- zprec);
-
- for(; col < width; col++)
- _blurcol (pixels,
- width,
- height,
- channels,
- col,
- alpha,
- aprec,
- zprec);
-
- return;
-}
-
-void
-_surface_blur (cairo_surface_t* surface,
- guint radius)
-{
- guchar* pixels;
- guint width;
- guint height;
- cairo_format_t format;
-
- // before we mess with the surface execute any pending drawing
- cairo_surface_flush (surface);
-
- pixels = cairo_image_surface_get_data (surface);
- width = cairo_image_surface_get_width (surface);
- height = cairo_image_surface_get_height (surface);
- format = cairo_image_surface_get_format (surface);
-
- switch (format)
- {
- case CAIRO_FORMAT_ARGB32:
- _expblur (pixels, width, height, 4, radius, 16, 7);
- break;
-
- case CAIRO_FORMAT_RGB24:
- _expblur (pixels, width, height, 3, radius, 16, 7);
- break;
-
- case CAIRO_FORMAT_A8:
- _expblur (pixels, width, height, 1, radius, 16, 7);
- break;
-
- default :
- // do nothing
- break;
- }
-
- // inform cairo we altered the surfaces contents
- cairo_surface_mark_dirty (surface);
-}
-
-static gboolean
-draw (GtkWidget* button, cairo_t *cr)
-{
- g_return_val_if_fail(IS_TRANSPORT_WIDGET(button), FALSE);
- g_return_val_if_fail(cr != NULL, FALSE);
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button);
-
- //g_debug("transport-widget draw()");
-
- cairo_surface_t* surf = NULL;
- cairo_t* cr_surf = NULL;
-
-#if ! GTK_CHECK_VERSION(3, 0, 0)
- GtkAllocation allocation;
- gtk_widget_get_allocation (button, &allocation);
- cairo_translate (cr, allocation.x, allocation.y);
-#endif
-
- GtkStyle *style;
-
-#if GTK_CHECK_VERSION(3, 0, 0)
- gtk_style_context_add_class (gtk_widget_get_style_context (button),
- GTK_STYLE_CLASS_MENU);
-#endif
- CairoColorRGB bg_color, fg_color, bg_selected, bg_prelight;
- CairoColorRGB color_middle[2], color_middle_prelight[2], color_outer[2], color_outer_prelight[2],
- color_play_outer[2], color_play_outer_prelight[2],
- color_button[4], color_button_shadow, color_inner[2], color_inner_compressed[2];
-
- /* Use the menu's style instead of that of the menuitem ('button' is a
- * menuitem that is packed in a menu directly). The menuitem's style
- * can't be used due to a change in light-themes (lp #1130183).
- * Menuitems now have a transparent background, which confuses
- * GtkStyle.
- *
- * This is a workaround until this code gets refactored to use
- * GtkStyleContext.
- */
- style = gtk_widget_get_style (gtk_widget_get_parent (button));
-
- bg_color.r = style->bg[0].red/65535.0;
- bg_color.g = style->bg[0].green/65535.0;
- bg_color.b = style->bg[0].blue/65535.0;
-
- bg_prelight.r = style->bg[GTK_STATE_PRELIGHT].red/65535.0;
- bg_prelight.g = style->bg[GTK_STATE_PRELIGHT].green/65535.0;
- bg_prelight.b = style->bg[GTK_STATE_PRELIGHT].blue/65535.0;
-
- bg_selected.r = style->bg[GTK_STATE_SELECTED].red/65535.0;
- bg_selected.g = style->bg[GTK_STATE_SELECTED].green/65535.0;
- bg_selected.b = style->bg[GTK_STATE_SELECTED].blue/65535.0;
-
- fg_color.r = style->fg[0].red/65535.0;
- fg_color.g = style->fg[0].green/65535.0;
- fg_color.b = style->fg[0].blue/65535.0;
-
- _color_shade (&bg_color, MIDDLE_START_SHADE, &color_middle[0]);
- _color_shade (&bg_color, MIDDLE_END_SHADE, &color_middle[1]);
- _color_shade (&bg_prelight, MIDDLE_START_SHADE, &color_middle_prelight[0]);
- _color_shade (&bg_prelight, MIDDLE_END_SHADE, &color_middle_prelight[1]);
- _color_shade (&bg_color, OUTER_START_SHADE, &color_outer[0]);
- _color_shade (&bg_color, OUTER_END_SHADE, &color_outer[1]);
- _color_shade (&bg_prelight, OUTER_START_SHADE, &color_outer_prelight[0]);
- _color_shade (&bg_prelight, OUTER_END_SHADE, &color_outer_prelight[1]);
- _color_shade (&bg_color, OUTER_PLAY_START_SHADE, &color_play_outer[0]);
- _color_shade (&bg_color, OUTER_PLAY_END_SHADE, &color_play_outer[1]);
- _color_shade (&bg_prelight, OUTER_PLAY_START_SHADE, &color_play_outer_prelight[0]);
- _color_shade (&bg_prelight, OUTER_PLAY_END_SHADE, &color_play_outer_prelight[1]);
- _color_shade (&bg_color, INNER_START_SHADE, &color_inner[0]);
- _color_shade (&bg_color, INNER_END_SHADE, &color_inner[1]);
- _color_shade (&fg_color, BUTTON_START_SHADE, &color_button[0]);
- _color_shade (&fg_color, BUTTON_END_SHADE, &color_button[1]);
- _color_shade (&bg_color, BUTTON_SHADOW_SHADE, &color_button[2]);
- _color_shade (&bg_color, SHADOW_BUTTON_SHADE, &color_button_shadow);
- _color_shade (&bg_selected, 1.0, &color_button[3]);
- _color_shade (&bg_color, INNER_COMPRESSED_START_SHADE, &color_inner_compressed[0]);
- _color_shade (&bg_color, INNER_COMPRESSED_END_SHADE, &color_inner_compressed[1]);
-
- double MIDDLE_END[] = {color_middle[0].r, color_middle[0].g, color_middle[0].b, 1.0f};
- double MIDDLE_START[] = {color_middle[1].r, color_middle[1].g, color_middle[1].b, 1.0f};
- double MIDDLE_END_PRELIGHT[] = {color_middle_prelight[0].r, color_middle_prelight[0].g, color_middle_prelight[0].b, 1.0f};
- double MIDDLE_START_PRELIGHT[] = {color_middle_prelight[1].r, color_middle_prelight[1].g, color_middle_prelight[1].b, 1.0f};
- double OUTER_END[] = {color_outer[0].r, color_outer[0].g, color_outer[0].b, 1.0f};
- double OUTER_START[] = {color_outer[1].r, color_outer[1].g, color_outer[1].b, 1.0f};
- double OUTER_END_PRELIGHT[] = {color_outer_prelight[0].r, color_outer_prelight[0].g, color_outer_prelight[0].b, 1.0f};
- double OUTER_START_PRELIGHT[] = {color_outer_prelight[1].r, color_outer_prelight[1].g, color_outer_prelight[1].b, 1.0f};
- double SHADOW_BUTTON[] = {color_button_shadow.r, color_button_shadow.g, color_button_shadow.b, 0.3f};
- double OUTER_PLAY_END[] = {color_play_outer[0].r, color_play_outer[0].g, color_play_outer[0].b, 1.0f};
- double OUTER_PLAY_START[] = {color_play_outer[1].r, color_play_outer[1].g, color_play_outer[1].b, 1.0f};
- double OUTER_PLAY_END_PRELIGHT[] = {color_play_outer_prelight[0].r, color_play_outer_prelight[0].g, color_play_outer_prelight[0].b, 1.0f};
- double OUTER_PLAY_START_PRELIGHT[] = {color_play_outer_prelight[1].r, color_play_outer_prelight[1].g, color_play_outer_prelight[1].b, 1.0f};
- double BUTTON_END[] = {color_button[0].r, color_button[0].g, color_button[0].b, 1.0f};
- double BUTTON_START[] = {color_button[1].r, color_button[1].g, color_button[1].b, 1.0f};
- double BUTTON_SHADOW[] = {color_button[2].r, color_button[2].g, color_button[2].b, 0.75f};
- double BUTTON_SHADOW_FOCUS[] = {color_button[3].r, color_button[3].g, color_button[3].b, 1.0f};
- double INNER_COMPRESSED_END[] = {color_inner_compressed[1].r, color_inner_compressed[1].g, color_inner_compressed[1].b, 1.0f};
- double INNER_COMPRESSED_START[] = {color_inner_compressed[0].r, color_inner_compressed[0].g, color_inner_compressed[0].b, 1.0f};
-
-
- draw_gradient (cr,
- X,
- Y,
- RECT_WIDTH,
- OUTER_RADIUS,
- OUTER_START,
- OUTER_END);
-
- draw_gradient (cr,
- X,
- Y + 1,
- RECT_WIDTH - 2,
- MIDDLE_RADIUS,
- MIDDLE_START,
- MIDDLE_END);
-
- draw_gradient (cr,
- X,
- Y + 2,
- RECT_WIDTH - 4,
- MIDDLE_RADIUS,
- MIDDLE_START,
- MIDDLE_END);
-
- //prev/next button
- if(priv->current_command == TRANSPORT_ACTION_PREVIOUS)
- {
- draw_gradient (cr,
- X,
- Y,
- RECT_WIDTH/2,
- OUTER_RADIUS,
- OUTER_END,
- OUTER_START);
-
- draw_gradient (cr,
- X,
- Y + 1,
- RECT_WIDTH/2,
- MIDDLE_RADIUS,
- INNER_COMPRESSED_START,
- INNER_COMPRESSED_END);
-
- draw_gradient (cr,
- X,
- Y + 2,
- RECT_WIDTH/2,
- MIDDLE_RADIUS,
- INNER_COMPRESSED_START,
- INNER_COMPRESSED_END);
- }
- else if(priv->current_command == TRANSPORT_ACTION_NEXT)
- {
- draw_gradient (cr,
- RECT_WIDTH / 2 + X,
- Y,
- RECT_WIDTH/2,
- OUTER_RADIUS,
- OUTER_END,
- OUTER_START);
-
- draw_gradient (cr,
- RECT_WIDTH / 2 + X,
- Y + 1,
- (RECT_WIDTH - 4.5)/2,
- MIDDLE_RADIUS,
- INNER_COMPRESSED_START,
- INNER_COMPRESSED_END);
-
- draw_gradient (cr,
- RECT_WIDTH / 2 + X,
- Y + 2,
- (RECT_WIDTH - 7)/2,
- MIDDLE_RADIUS,
- INNER_COMPRESSED_START,
- INNER_COMPRESSED_END);
- }
- else if (priv->motion_event == TRANSPORT_ACTION_PREVIOUS)
- {
- draw_gradient (cr,
- X,
- Y,
- RECT_WIDTH/2,
- OUTER_RADIUS,
- OUTER_START_PRELIGHT,
- OUTER_END_PRELIGHT);
-
- draw_gradient (cr,
- X,
- Y + 1,
- RECT_WIDTH/2,
- MIDDLE_RADIUS,
- MIDDLE_START_PRELIGHT,
- MIDDLE_END_PRELIGHT);
-
- draw_gradient (cr,
- X,
- Y + 2,
- RECT_WIDTH/2,
- MIDDLE_RADIUS,
- MIDDLE_START_PRELIGHT,
- MIDDLE_END_PRELIGHT);
- }
- else if (priv->motion_event == TRANSPORT_ACTION_NEXT)
- {
- draw_gradient (cr,
- RECT_WIDTH / 2 + X,
- Y,
- RECT_WIDTH/2,
- OUTER_RADIUS,
- OUTER_START_PRELIGHT,
- OUTER_END_PRELIGHT);
-
- draw_gradient (cr,
- RECT_WIDTH / 2 + X,
- Y + 1,
- (RECT_WIDTH - 4.5)/2,
- MIDDLE_RADIUS,
- MIDDLE_START_PRELIGHT,
- MIDDLE_END_PRELIGHT);
-
- draw_gradient (cr,
- RECT_WIDTH / 2 + X,
- Y + 2,
- (RECT_WIDTH - 7)/2,
- MIDDLE_RADIUS,
- MIDDLE_START_PRELIGHT,
- MIDDLE_END_PRELIGHT);
- }
-
- // play/pause shadow
- if(priv->current_command != TRANSPORT_ACTION_PLAY_PAUSE)
- {
- cairo_save (cr);
- cairo_rectangle (cr, X, Y, RECT_WIDTH, MIDDLE_RADIUS*2);
- cairo_clip (cr);
-
- draw_circle (cr,
- X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f - 1.0f,
- Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) - 1.0f,
- CIRCLE_RADIUS + 1.0f,
- SHADOW_BUTTON,
- SHADOW_BUTTON);
-
- cairo_restore (cr);
- }
-
- // play/pause button
- if(priv->current_command == TRANSPORT_ACTION_PLAY_PAUSE)
- {
- draw_circle (cr,
- X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f,
- Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) ,
- CIRCLE_RADIUS,
- OUTER_PLAY_END,
- OUTER_PLAY_START);
-
- draw_circle (cr,
- X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f,
- Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f,
- CIRCLE_RADIUS - 1.25,
- INNER_COMPRESSED_START,
- INNER_COMPRESSED_END);
- }
- else if (priv->motion_event == TRANSPORT_ACTION_PLAY_PAUSE)
- {
- /* this subtle offset is to fix alpha borders, should be removed once this draw routine will be refactored */
- draw_circle (cr,
- X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 0.1,
- Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 0.1,
- CIRCLE_RADIUS - 0.1,
- OUTER_PLAY_START_PRELIGHT,
- OUTER_PLAY_END_PRELIGHT);
-
- draw_circle (cr,
- X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f,
- Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f,
- CIRCLE_RADIUS - 1.25,
- MIDDLE_START_PRELIGHT,
- MIDDLE_END_PRELIGHT);
- }
- else
- {
- draw_circle (cr,
- X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f,
- Y - ((CIRCLE_RADIUS - OUTER_RADIUS)),
- CIRCLE_RADIUS,
- OUTER_PLAY_START,
- OUTER_PLAY_END);
-
- draw_circle (cr,
- X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f,
- Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f,
- CIRCLE_RADIUS - 1.25,
- MIDDLE_START,
- MIDDLE_END);
- }
-
- // draw previous-button drop-shadow
- if (priv->has_focus && priv->key_event == TRANSPORT_ACTION_PREVIOUS)
- {
- _setup (&cr_surf, &surf, PREV_WIDTH+6, PREV_HEIGHT+6);
- _mask_prev (cr_surf,
- (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (PREV_HEIGHT - TRI_HEIGHT) / 2.0f,
- TRI_WIDTH,
- 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_SHADOW_FOCUS,
- BUTTON_SHADOW_FOCUS,
- FALSE);
- _surface_blur (surf, 3);
- _finalize_repaint (cr, &cr_surf, &surf, PREV_X, PREV_Y + 0.5f, 3);
- }
- else
- {
- _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT);
- _mask_prev (cr_surf,
- (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (PREV_HEIGHT - TRI_HEIGHT) / 2.0f,
- TRI_WIDTH,
- 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_SHADOW,
- BUTTON_SHADOW,
- FALSE);
- _surface_blur (surf, 1);
- _finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y + 1.0f);
- }
-
- // draw previous-button
- _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT);
- _mask_prev (cr_surf,
- (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (PREV_HEIGHT - TRI_HEIGHT) / 2.0f,
- TRI_WIDTH,
- 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);
- _finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y);
-
- // draw next-button drop-shadow
- if (priv->has_focus && priv->key_event == TRANSPORT_ACTION_NEXT)
- {
- _setup (&cr_surf, &surf, NEXT_WIDTH+6, NEXT_HEIGHT+6);
- _mask_next (cr_surf,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
- TRI_WIDTH,
- TRI_HEIGHT,
- TRI_OFFSET);
- _fill (cr_surf,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (double) TRI_HEIGHT,
- BUTTON_SHADOW_FOCUS,
- BUTTON_SHADOW_FOCUS,
- FALSE);
- _surface_blur (surf, 3);
- _finalize_repaint (cr, &cr_surf, &surf, NEXT_X, NEXT_Y + 0.5f, 3);
- }
- else
- {
- _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT);
- _mask_next (cr_surf,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
- TRI_WIDTH,
- TRI_HEIGHT,
- TRI_OFFSET);
- _fill (cr_surf,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (double) TRI_HEIGHT,
- BUTTON_SHADOW,
- BUTTON_SHADOW,
- FALSE);
- _surface_blur (surf, 1);
- _finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y + 1.0f);
- }
-
- // draw next-button
- _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT);
- _mask_next (cr_surf,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
- TRI_WIDTH,
- TRI_HEIGHT,
- TRI_OFFSET);
- _fill (cr_surf,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f,
- (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f,
- (double) TRI_HEIGHT,
- BUTTON_START,
- BUTTON_END,
- FALSE);
- _finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y);
-
- // draw pause-button drop-shadow
- if(priv->current_state == TRANSPORT_STATE_PLAYING)
- {
- if (priv->has_focus && (priv->key_event == TRANSPORT_ACTION_NO_ACTION ||
- priv->key_event == TRANSPORT_ACTION_PLAY_PAUSE))
- {
- _setup (&cr_surf, &surf, PAUSE_WIDTH+6, PAUSE_HEIGHT+6);
- _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_FOCUS,
- BUTTON_SHADOW_FOCUS,
- TRUE);
- _surface_blur (surf, 3);
- _finalize_repaint (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y + 0.5f, 3);
- }
- else
- {
- _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 == TRANSPORT_STATE_PAUSED)
- {
- if (priv->has_focus && (priv->key_event == TRANSPORT_ACTION_NO_ACTION ||
- priv->key_event == TRANSPORT_ACTION_PLAY_PAUSE))
- {
- _setup (&cr_surf, &surf, PLAY_WIDTH+6, PLAY_HEIGHT+6);
- _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_FOCUS,
- BUTTON_SHADOW_FOCUS,
- FALSE);
- _surface_blur (surf, 3);
- _finalize_repaint (cr, &cr_surf, &surf, PAUSE_X-0.5f, PAUSE_Y + 0.5f, 3);
- }
- else
- {
- _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-0.75f, 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-0.5f, PAUSE_Y);
- }
- #if GTK_CHECK_VERSION(3, 0, 0)
- else if(priv->current_state == TRANSPORT_STATE_LAUNCHING)
- {
- // the spinner is not aligned, why? because the play button has odd width/height numbers
- gtk_render_activity (spinner_style_context, cr, 106, 6, 30, 30);
- }
- #endif
- return FALSE;
-}
-
-static void
-transport_widget_set_twin_item(TransportWidget* self,
- DbusmenuMenuitem* twin_item)
-{
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(self);
- priv->twin_item = twin_item;
- g_signal_connect(G_OBJECT(priv->twin_item), "property-changed",
- G_CALLBACK(transport_widget_property_update), self);
- gint initial_state = dbusmenu_menuitem_property_get_int (twin_item,
- DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE );
- //g_debug("TRANSPORT WIDGET - INITIAL UPDATE = %i", initial_state);
- transport_widget_toggle_play_pause (self,
- (TransportState)initial_state);
-}
-
-/**
-* transport_widget_update_state()
-* Callback for updates from the other side of dbus
-**/
-static void
-transport_widget_property_update(DbusmenuMenuitem* item, gchar* property,
- GVariant* value, gpointer userdata)
-{
- //g_debug("transport_widget_update_state - with property %s", property);
- TransportWidget* bar = (TransportWidget*)userdata;
- g_return_if_fail(IS_TRANSPORT_WIDGET(bar));
- TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(bar);
-
- if(g_ascii_strcasecmp(DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE, property) == 0)
- {
- TransportState new_state = (TransportState)g_variant_get_int32(value);
- //g_debug("transport_widget_update_state - with value %i", new_state);
- if (new_state == TRANSPORT_STATE_LAUNCHING){
- #if GTK_CHECK_VERSION(3, 0, 0)
- gtk_style_context_set_state (spinner_style_context, GTK_STATE_FLAG_ACTIVE);
- #endif
-
- priv->current_state = TRANSPORT_STATE_LAUNCHING;
- g_debug("TransportWidget::toggle play state : %i", priv->current_state);
- }
- else{
- transport_widget_toggle_play_pause(bar, new_state);
- }
- }
-}
-
-
-/**
-* transport_widget_new:
-* @returns: a new #TransportWidget.
-**/
-GtkWidget*
-transport_widget_new ( DbusmenuMenuitem *item )
-{
- GtkWidget* widget = g_object_new(TRANSPORT_WIDGET_TYPE, NULL);
- gtk_widget_set_app_paintable (widget, TRUE);
- transport_widget_set_twin_item((TransportWidget*)widget, item);
- return widget;
-}
-
diff --git a/src/transport-widget.h b/src/transport-widget.h
deleted file mode 100644
index b68845f..0000000
--- a/src/transport-widget.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-Copyright 2010 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef __TRANSPORT_WIDGET_H__
-#define __TRANSPORT_WIDGET_H__
-
-#include <gtk/gtk.h>
-#include <libdbusmenu-gtk/menuitem.h>
-
-#include "common-defs.h"
-
-G_BEGIN_DECLS
-
-#define TRANSPORT_WIDGET_TYPE (transport_widget_get_type ())
-#define TRANSPORT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRANSPORT_WIDGET_TYPE, TransportWidget))
-#define TRANSPORT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRANSPORT_WIDGET_TYPE, TransportWidgetClass))
-#define IS_TRANSPORT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRANSPORT_WIDGET_TYPE))
-#define IS_TRANSPORT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRANSPORT_WIDGET_TYPE))
-#define TRANSPORT_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRANSPORT_WIDGET_TYPE, TransportWidgetClass))
-
-typedef struct _TransportWidget TransportWidget;
-typedef struct _TransportWidgetClass TransportWidgetClass;
-
-
-struct _TransportWidgetClass {
- GtkMenuItemClass parent_class;
-};
-
-struct _TransportWidget {
- GtkMenuItem parent;
-};
-
-typedef struct
-{
- double r;
- double g;
- double b;
-} CairoColorRGB;
-
-
-void _color_shade (const CairoColorRGB *a, float k, CairoColorRGB *b);
-GType transport_widget_get_type (void);
-GtkWidget* transport_widget_new (DbusmenuMenuitem *item);
-void transport_widget_react_to_key_press_event (TransportWidget* widget,
- TransportAction transport_event);
-void transport_widget_react_to_key_release_event (TransportWidget* widget,
- TransportAction transport_event);
-gboolean transport_widget_is_selected (TransportWidget* widget);
-G_END_DECLS
-
-#endif
-
diff --git a/src/voip-input-menu-item.c b/src/voip-input-menu-item.c
deleted file mode 100644
index 7cbdd45..0000000
--- a/src/voip-input-menu-item.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib/gi18n.h>
-#include "voip-input-menu-item.h"
-#include "common-defs.h"
-#include "pulseaudio-mgr.h"
-
-typedef struct _VoipInputMenuItemPrivate VoipInputMenuItemPrivate;
-
-struct _VoipInputMenuItemPrivate {
- Device* a_sink;
- pa_cvolume volume;
- gint mute;
- guint32 volume_steps;
- pa_channel_map channel_map;
- pa_volume_t base_volume;
- gint source_index;
- gint source_output_index;
- gint client_index;
-};
-
-#define VOIP_INPUT_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemPrivate))
-
-/* Prototypes */
-static void voip_input_menu_item_class_init (VoipInputMenuItemClass *klass);
-static void voip_input_menu_item_init (VoipInputMenuItem *self);
-static void voip_input_menu_item_dispose (GObject *object);
-static void voip_input_menu_item_finalize (GObject *object);
-static void handle_event (DbusmenuMenuitem * mi, const gchar * name,
- GVariant * value, guint timestamp);
-// TODO:
-// This method should really be shared between this and the volume slider obj
-// perfectly static - wait until the device mgr wrapper is properly sorted and
-// then consolidate
-static pa_cvolume voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol);
-
-G_DEFINE_TYPE (VoipInputMenuItem, voip_input_menu_item, DBUSMENU_TYPE_MENUITEM);
-
-static void
-voip_input_menu_item_class_init (VoipInputMenuItemClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (VoipInputMenuItemPrivate));
-
- object_class->dispose = voip_input_menu_item_dispose;
- object_class->finalize = voip_input_menu_item_finalize;
-
- DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass);
- mclass->handle_event = handle_event;
-}
-
-static void
-voip_input_menu_item_init (VoipInputMenuItem *self)
-{
- dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self),
- DBUSMENU_MENUITEM_PROP_TYPE,
- DBUSMENU_VOIP_INPUT_MENUITEM_TYPE );
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self);
- dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(self),
- DBUSMENU_MENUITEM_PROP_VISIBLE,
- FALSE );
-
- priv->source_index = NOT_ACTIVE;
- priv->source_output_index = NOT_ACTIVE;
- priv->client_index = NOT_ACTIVE;
- priv->mute = NOT_ACTIVE;
-}
-
-static void
-voip_input_menu_item_dispose (GObject *object)
-{
- G_OBJECT_CLASS (voip_input_menu_item_parent_class)->dispose (object);
- return;
-}
-
-static void
-voip_input_menu_item_finalize (GObject *object)
-{
- G_OBJECT_CLASS (voip_input_menu_item_parent_class)->finalize (object);
-}
-
-static void
-handle_event (DbusmenuMenuitem * mi,
- const gchar * name,
- GVariant * value,
- guint timestamp)
-{
- GVariant* input = NULL;
- input = value;
- if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARIANT) == TRUE) {
- input = g_variant_get_variant(value);
- }
-
- gdouble percent = g_variant_get_double(input);
- if (value != NULL){
- if (IS_VOIP_INPUT_MENU_ITEM (mi)) {
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (VOIP_INPUT_MENU_ITEM (mi));
-/*
- g_debug ("Handle event in the voip input level backend instance - %f", percent);
-*/
- pa_cvolume new_volume;
- pa_cvolume_init(&new_volume);
- new_volume.channels = 1;
- pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
- pa_cvolume_set(&new_volume, 1, new_volume_value);
-
- pm_update_mic_gain (priv->source_index, new_volume);
- // finally unmute if needed
- if (priv->mute == 1) {
- pm_update_mic_mute (priv->source_index, 0);
- }
- }
- }
-}
-
-static pa_cvolume
-voip_input_menu_item_construct_mono_volume (const pa_cvolume* vol)
-{
- pa_cvolume new_volume;
- pa_cvolume_init(&new_volume);
- new_volume.channels = 1;
- pa_volume_t max_vol = pa_cvolume_max(vol);
- pa_cvolume_set(&new_volume, 1, max_vol);
- return new_volume;
-}
-
-void
-voip_input_menu_item_update (VoipInputMenuItem* item,
- const pa_source_info* source)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- // only overwrite the constants of each source if the device has changed
- if (priv->source_index == NOT_ACTIVE){
- priv->base_volume = source->base_volume;
- priv->volume_steps = source->n_volume_steps;
- priv->channel_map = source->channel_map;
- priv->source_index = source->index;
- }
- priv->volume = voip_input_menu_item_construct_mono_volume (&source->volume);
- pa_volume_t vol = pa_cvolume_max (&source->volume);
- gdouble update = ((gdouble) vol * 100) / PA_VOLUME_NORM;
-
- GVariant* new_volume = g_variant_new_double(update);
- dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item),
- DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL,
- new_volume);
- // Only send over the mute updates if the state has changed.
- // in this order - volume first mute last!!
- if (priv->mute != source->mute){
-/*
- g_debug ("voip menu item - update - mute = %i", priv->mute);
-*/
- GVariant* new_mute_update = g_variant_new_int32 (source->mute);
- dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(item),
- DBUSMENU_VOIP_INPUT_MENUITEM_MUTE,
- new_mute_update);
- }
-
- priv->mute = source->mute;
-
-}
-
-gboolean
-voip_input_menu_item_is_interested (VoipInputMenuItem* item,
- gint source_output_index,
- gint client_index)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- // Check to make sure we are not handling another voip beforehand and that we
- // have an active sink (might need to match up at start up)
- if (priv->source_output_index != NOT_ACTIVE &&
- priv->source_index != NOT_ACTIVE){
- return FALSE;
- }
-
- priv->source_output_index = source_output_index;
- priv->client_index = client_index;
-
- return TRUE;
-}
-
-gboolean
-voip_input_menu_item_is_active (VoipInputMenuItem* item)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- return (priv->source_output_index != NOT_ACTIVE && priv->client_index != NOT_ACTIVE);
-}
-
-
-gboolean
-voip_input_menu_item_is_populated (VoipInputMenuItem* item)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- return priv->source_index != NOT_ACTIVE;
-}
-
-gint
-voip_input_menu_item_get_index (VoipInputMenuItem* item)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- return priv->source_index;
-}
-
-gint
-voip_input_menu_item_get_source_output_index (VoipInputMenuItem* item)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
-
- return priv->source_output_index;
-}
-
-/**
- * If the pulse server informs of a default source change
- * or the source in question is removed.
- * @param item
- */
-void
-voip_input_menu_item_deactivate_source (VoipInputMenuItem* item, gboolean visible)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- priv->source_index = NOT_ACTIVE;
- dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item),
- DBUSMENU_MENUITEM_PROP_VISIBLE,
- visible );
-}
-
-void
-voip_input_menu_item_deactivate_voip_client (VoipInputMenuItem* item)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- priv->client_index = NOT_ACTIVE;
- priv->source_output_index = NOT_ACTIVE;
- voip_input_menu_item_enable (item, FALSE);
-}
-
-void
-voip_input_menu_item_enable (VoipInputMenuItem* item,
- gboolean active)
-{
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item);
- if (priv->source_index == NOT_ACTIVE && active == TRUE) {
- g_warning ("Tried to enable the VOIP menuitem but we don't have an active source ??");
- active = FALSE;
- }
- dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item),
- DBUSMENU_MENUITEM_PROP_VISIBLE,
- active );
-}
-
-VoipInputMenuItem*
-voip_input_menu_item_new (Device* sink)
-{
- VoipInputMenuItem *self = g_object_new(VOIP_INPUT_MENU_ITEM_TYPE, NULL);
- VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self);
- priv->a_sink = sink;
- return self;
-} \ No newline at end of file
diff --git a/src/voip-input-widget.c b/src/voip-input-widget.c
deleted file mode 100644
index 03879e7..0000000
--- a/src/voip-input-widget.c
+++ /dev/null
@@ -1,284 +0,0 @@
-
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib/gi18n-lib.h>
-#include <math.h>
-#include <glib.h>
-#include "voip-input-widget.h"
-#include "common-defs.h"
-#include <libido/idoscalemenuitem.h>
-
-typedef struct _VoipInputWidgetPrivate VoipInputWidgetPrivate;
-
-struct _VoipInputWidgetPrivate
-{
- DbusmenuMenuitem* twin_item;
- GtkWidget* ido_voip_input_slider;
- gboolean grabbed;
-};
-
-#define VOIP_INPUT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetPrivate))
-
-/* Prototypes */
-static void voip_input_widget_class_init (VoipInputWidgetClass *klass);
-static void voip_input_widget_init (VoipInputWidget *self);
-static void voip_input_widget_dispose (GObject *object);
-static void voip_input_widget_finalize (GObject *object);
-static void voip_input_widget_set_twin_item( VoipInputWidget* self,
- DbusmenuMenuitem* twin_item);
-static void voip_input_widget_property_update( DbusmenuMenuitem* item, gchar* property,
- GVariant* value, gpointer userdata );
-
-static gboolean voip_input_widget_change_value_cb (GtkRange *range,
- GtkScrollType scroll,
- gdouble value,
- gpointer user_data);
-static gboolean voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data);
-static void voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data);
-static void voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data);
-static void voip_input_widget_parent_changed (GtkWidget *widget, gpointer user_data);
-
-G_DEFINE_TYPE (VoipInputWidget, voip_input_widget, G_TYPE_OBJECT);
-
-
-static void
-voip_input_widget_class_init (VoipInputWidgetClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (VoipInputWidgetPrivate));
-
- gobject_class->dispose = voip_input_widget_dispose;
- gobject_class->finalize = voip_input_widget_finalize;
-}
-
-static void
-voip_input_widget_init (VoipInputWidget *self)
-{
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
-
- priv->ido_voip_input_slider = ido_scale_menu_item_new_with_range ("VOLUME", IDO_RANGE_STYLE_DEFAULT, 0, 0, 100, 1);
- g_object_ref (priv->ido_voip_input_slider);
- ido_scale_menu_item_set_primary_label (IDO_SCALE_MENU_ITEM(priv->ido_voip_input_slider), "VOIP");
-
- ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (priv->ido_voip_input_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE);
- g_object_set(priv->ido_voip_input_slider, "reverse-scroll-events", TRUE, NULL);
-
- g_signal_connect (priv->ido_voip_input_slider,
- "notify::parent", G_CALLBACK (voip_input_widget_parent_changed),
- NULL);
-
- GtkWidget* voip_input_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
-
- g_signal_connect(voip_input_widget, "change-value", G_CALLBACK(voip_input_widget_change_value_cb), self);
- g_signal_connect(voip_input_widget, "value-changed", G_CALLBACK(voip_input_widget_value_changed_cb), self);
- g_signal_connect(priv->ido_voip_input_slider, "slider-grabbed", G_CALLBACK(voip_input_widget_slider_grabbed), self);
- g_signal_connect(priv->ido_voip_input_slider, "slider-released", G_CALLBACK(voip_input_widget_slider_released), self);
-
- GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider);
- GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone-low-zero-panel");
- gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU);
- g_object_unref(primary_gicon);
-
- GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_voip_input_slider);
- GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-input-microphone-high-panel");
- gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU);
- g_object_unref(secondary_gicon);
-
- GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (voip_input_widget));
- gtk_adjustment_set_step_increment(adj, 4);
-}
-
-static void
-voip_input_widget_dispose (GObject *object)
-{
- G_OBJECT_CLASS (voip_input_widget_parent_class)->dispose (object);
-}
-
-static void
-voip_input_widget_finalize (GObject *object)
-{
- G_OBJECT_CLASS (voip_input_widget_parent_class)->finalize (object);
-}
-
-static void
-voip_input_widget_property_update (DbusmenuMenuitem* item, gchar* property,
- GVariant* value, gpointer userdata)
-{
- g_return_if_fail (IS_VOIP_INPUT_WIDGET (userdata));
- VoipInputWidget* mitem = VOIP_INPUT_WIDGET(userdata);
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
- if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, property) == 0){
- g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
- if (priv->grabbed == FALSE){
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
- GtkRange *range = (GtkRange*)slider;
- gdouble update = g_variant_get_double (value);
- //g_debug("volume-widget - update level with value %f", update);
- gtk_range_set_value(range, update);
- }
- }
- if(g_ascii_strcasecmp(DBUSMENU_VOIP_INPUT_MENUITEM_MUTE, property) == 0){
- if(priv->grabbed == FALSE){
- g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32));
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
- GtkRange *range = (GtkRange*)slider;
- gint update = g_variant_get_int32 (value);
- gdouble level;
- if (update == 1){
- level = 0;
- }
- else{
- GVariant* variant = dbusmenu_menuitem_property_get_variant (priv->twin_item,
- DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL);
- g_return_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE));
- level = g_variant_get_double (variant);
- }
- gtk_range_set_value(range, level);
-
- g_debug ("voip-item-widget - update mute with value %i", update);
- }
- }
-}
-
-static void
-voip_input_widget_set_twin_item (VoipInputWidget* self,
- DbusmenuMenuitem* twin_item)
-{
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
- priv->twin_item = twin_item;
- g_object_ref(priv->twin_item);
- g_signal_connect(G_OBJECT(twin_item), "property-changed",
- G_CALLBACK(voip_input_widget_property_update), self);
- gdouble initial_level = g_variant_get_double (dbusmenu_menuitem_property_get_variant(twin_item,
- DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL));
- //g_debug("voip_input_widget_set_twin_item initial level = %f", initial_level);
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
- GtkRange *range = (GtkRange*)slider;
- gtk_range_set_value(range, initial_level);
-
- gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item,
- DBUSMENU_VOIP_INPUT_MENUITEM_MUTE));
- if (mute == 1){
- gtk_range_set_value (range, 0.0);
- }
-}
-
-static gboolean
-voip_input_widget_change_value_cb (GtkRange *range,
- GtkScrollType scroll,
- gdouble new_value,
- gpointer user_data)
-{
- g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE);
- VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
- voip_input_widget_update(mitem, new_value);
- return FALSE;
-}
-
-
-/**
- * We only want this callback to catch mouse icon press events which set the
- * slider to 0 or 100. Ignore all other events including the new Mute behaviour
- * (slider to go to 0 on mute without setting the level to 0 and return to
- * previous level on unmute)
- **/
-static gboolean
-voip_input_widget_value_changed_cb(GtkRange *range, gpointer user_data)
-{
- g_return_val_if_fail (IS_VOIP_INPUT_WIDGET (user_data), FALSE);
- VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_voip_input_slider);
- gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100);
-
- gint mute = g_variant_get_int32 (dbusmenu_menuitem_property_get_variant (priv->twin_item,
- DBUSMENU_VOIP_INPUT_MENUITEM_MUTE));
- if ((current_value == 0 && mute != 1) || current_value == 100 ){
- voip_input_widget_update(mitem, current_value);
- }
- return FALSE;
-}
-
-void
-voip_input_widget_update(VoipInputWidget* self, gdouble update)
-{
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
- gdouble clamped = CLAMP(update, 0, 100);
- GVariant* new_volume = g_variant_new_double(clamped);
- dbusmenu_menuitem_handle_event (priv->twin_item, "update", new_volume, 0);
-}
-
-GtkWidget*
-voip_input_widget_get_ido_slider(VoipInputWidget* self)
-{
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
- return priv->ido_voip_input_slider;
-}
-
-static void
-voip_input_widget_parent_changed (GtkWidget *widget,
- gpointer user_data)
-{
- gtk_widget_set_size_request (widget, 200, -1);
- //g_debug("voip_input_widget_parent_changed");
-}
-
-static void
-voip_input_widget_slider_grabbed(GtkWidget *widget, gpointer user_data)
-{
- VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
- priv->grabbed = TRUE;
-}
-
-static void
-voip_input_widget_slider_released(GtkWidget *widget, gpointer user_data)
-{
- VoipInputWidget* mitem = VOIP_INPUT_WIDGET(user_data);
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
- priv->grabbed = FALSE;
-}
-
-void
-voip_input_widget_tidy_up (GtkWidget *widget)
-{
- VoipInputWidget* mitem = VOIP_INPUT_WIDGET(widget);
- VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(mitem);
- gtk_widget_destroy (priv->ido_voip_input_slider);
-}
-
-/**
- * voip_input_widget_new:
- * @returns: a new #VoipInputWidget.
- **/
-GtkWidget*
-voip_input_widget_new(DbusmenuMenuitem *item)
-{
- GtkWidget* widget = g_object_new(VOIP_INPUT_WIDGET_TYPE, NULL);
- voip_input_widget_set_twin_item((VoipInputWidget*)widget, item);
- return widget;
-}
-
-
diff --git a/src/voip-input-widget.h b/src/voip-input-widget.h
deleted file mode 100644
index 72da80c..0000000
--- a/src/voip-input-widget.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef __VOIP_INPUT_WIDGET_H__
-#define __VOIP_INPUT_WIDGET_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
-#include <libdbusmenu-gtk/menuitem.h>
-
-G_BEGIN_DECLS
-
-#define VOIP_INPUT_WIDGET_TYPE (voip_input_widget_get_type ())
-#define VOIP_INPUT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VOIP_INPUT_WIDGET_TYPE, VoipInputWidget))
-#define VOIP_INPUT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetClass))
-#define IS_VOIP_INPUT_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VOIP_INPUT_WIDGET_TYPE))
-#define IS_VOIP_INPUT_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VOIP_INPUT_WIDGET_TYPE))
-#define VOIP_INPUT_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VOIP_INPUT_WIDGET_TYPE, VoipInputWidgetClass))
-
-typedef struct _VoipInputWidget VoipInputWidget;
-typedef struct _VoipInputWidgetClass VoipInputWidgetClass;
-
-struct _VoipInputWidgetClass {
- GObjectClass parent_class;
-};
-
-struct _VoipInputWidget {
- GObject parent;
-};
-
-GType voip_input_widget_get_type (void) G_GNUC_CONST;
-GtkWidget* voip_input_widget_new(DbusmenuMenuitem* twin_item);
-GtkWidget* voip_input_widget_get_ido_slider(VoipInputWidget* self);
-void voip_input_widget_update(VoipInputWidget* self, gdouble update);
-void voip_input_widget_tidy_up (GtkWidget *widget);
-
-G_END_DECLS
-
-#endif
-
diff --git a/src/volume-control.vala b/src/volume-control.vala
new file mode 100644
index 0000000..9475f53
--- /dev/null
+++ b/src/volume-control.vala
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2013 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Alberto Ruiz <alberto.ruiz@canonical.com>
+ */
+
+using PulseAudio;
+
+[CCode(cname="pa_cvolume_set", cheader_filename = "pulse/volume.h")]
+extern unowned PulseAudio.CVolume? vol_set (PulseAudio.CVolume? cv, uint channels, PulseAudio.Volume v);
+
+public class VolumeControl : Object
+{
+ /* this is static to ensure it being freed after @context (loop does not have ref counting) */
+ private static PulseAudio.GLibMainLoop loop;
+
+ private PulseAudio.Context context;
+ private bool _mute = true;
+ private double _volume = 0.0;
+ private double _mic_volume = 0.0;
+
+ public signal void volume_changed (double v);
+ public signal void mic_volume_changed (double v);
+
+ /** true when connected to the pulse server */
+ public bool ready { get; set; }
+
+ /** true when a microphone is active **/
+ public bool active_mic { get; private set; default = false; }
+
+ public VolumeControl ()
+ {
+ if (loop == null)
+ loop = new PulseAudio.GLibMainLoop ();
+
+ var props = new Proplist ();
+ props.sets (Proplist.PROP_APPLICATION_NAME, "Ubuntu Audio Settings");
+ props.sets (Proplist.PROP_APPLICATION_ID, "com.canonical.settings.sound");
+ props.sets (Proplist.PROP_APPLICATION_ICON_NAME, "multimedia-volume-control");
+ props.sets (Proplist.PROP_APPLICATION_VERSION, "0.1");
+
+ context = new PulseAudio.Context (loop.get_api(), null, props);
+
+ context.set_state_callback (context_state_callback);
+
+ if (context.connect(null, Context.Flags.NOFAIL, null) < 0)
+ {
+ warning( "pa_context_connect() failed: %s\n", PulseAudio.strerror(context.errno()));
+ return;
+ }
+ }
+
+ /* PulseAudio logic*/
+ private void context_events_cb (Context c, Context.SubscriptionEventType t, uint32 index)
+ {
+ switch (t & Context.SubscriptionEventType.FACILITY_MASK)
+ {
+ case Context.SubscriptionEventType.SINK:
+ update_sink ();
+ break;
+
+ case Context.SubscriptionEventType.SOURCE:
+ update_source ();
+ break;
+
+ case Context.SubscriptionEventType.SOURCE_OUTPUT:
+ switch (t & Context.SubscriptionEventType.TYPE_MASK)
+ {
+ case Context.SubscriptionEventType.NEW:
+ c.get_source_output_info (index, source_output_info_cb);
+ break;
+
+ case Context.SubscriptionEventType.REMOVE:
+ this.active_mic = false;
+ break;
+ }
+ break;
+ }
+ }
+
+ private void sink_info_cb_for_props (Context c, SinkInfo? i, int eol)
+ {
+ if (i == null)
+ return;
+
+ if (_mute != (bool)i.mute)
+ {
+ _mute = (bool)i.mute;
+ this.notify_property ("mute");
+ }
+
+ if (_volume != volume_to_double (i.volume.values[0]))
+ {
+ _volume = volume_to_double (i.volume.values[0]);
+ volume_changed (_volume);
+ }
+ }
+
+ private void source_info_cb (Context c, SourceInfo? i, int eol)
+ {
+ if (i == null)
+ return;
+
+ if (_mic_volume != volume_to_double (i.volume.values[0]))
+ {
+ _mic_volume = volume_to_double (i.volume.values[0]);
+ mic_volume_changed (_mic_volume);
+ }
+ }
+
+ private void server_info_cb_for_props (Context c, ServerInfo? i)
+ {
+ if (i == null)
+ return;
+ context.get_sink_info_by_name (i.default_sink_name, sink_info_cb_for_props);
+ }
+
+ private void update_sink ()
+ {
+ context.get_server_info (server_info_cb_for_props);
+ }
+
+ private void update_source ()
+ {
+ context.get_server_info ( (c, i) => {
+ if (i != null)
+ context.get_source_info_by_name (i.default_source_name, source_info_cb);
+ });
+ }
+
+ private void source_output_info_cb (Context c, SourceOutputInfo? i, int eol)
+ {
+ if (i == null)
+ return;
+
+ var role = i.proplist.gets (PulseAudio.Proplist.PROP_MEDIA_ROLE);
+ if (role == "phone" || role == "production")
+ this.active_mic = true;
+ }
+
+ private void context_state_callback (Context c)
+ {
+ if (c.get_state () == Context.State.READY)
+ {
+ c.subscribe (PulseAudio.Context.SubscriptionMask.SINK |
+ PulseAudio.Context.SubscriptionMask.SOURCE |
+ PulseAudio.Context.SubscriptionMask.SOURCE_OUTPUT);
+ c.set_subscribe_callback (context_events_cb);
+ update_sink ();
+ update_source ();
+ this.ready = true;
+ }
+ else
+ this.ready = false;
+ }
+
+ /* Mute operations */
+ public void set_mute (bool mute)
+ {
+ return_if_fail (context.get_state () == Context.State.READY);
+
+ context.get_sink_info_list ((context, sink, eol) => {
+ if (sink != null)
+ context.set_sink_mute_by_index (sink.index, mute, null);
+ });
+ }
+
+ public void toggle_mute ()
+ {
+ this.set_mute (!this._mute);
+ }
+
+ public bool mute
+ {
+ get
+ {
+ return this._mute;
+ }
+ }
+
+ /* Volume operations */
+ private static PulseAudio.Volume double_to_volume (double vol)
+ {
+ double tmp = (double)(PulseAudio.Volume.NORM - PulseAudio.Volume.MUTED) * vol;
+ return (PulseAudio.Volume)tmp + PulseAudio.Volume.MUTED;
+ }
+
+ private static double volume_to_double (PulseAudio.Volume vol)
+ {
+ double tmp = (double)(vol - PulseAudio.Volume.MUTED);
+ return tmp / (double)(PulseAudio.Volume.NORM - PulseAudio.Volume.MUTED);
+ }
+
+ private void set_volume_success_cb (Context c, int success)
+ {
+ if ((bool)success)
+ volume_changed (_volume);
+ }
+
+ private void sink_info_set_volume_cb (Context c, SinkInfo? i, int eol)
+ {
+ if (i == null)
+ return;
+
+ unowned CVolume cvol = vol_set (i.volume, 1, double_to_volume (_volume));
+ c.set_sink_volume_by_index (i.index, cvol, set_volume_success_cb);
+ }
+
+ private void server_info_cb_for_set_volume (Context c, ServerInfo? i)
+ {
+ if (i == null)
+ {
+ warning ("Could not get PulseAudio server info");
+ return;
+ }
+
+ context.get_sink_info_by_name (i.default_sink_name, sink_info_set_volume_cb);
+ }
+
+ public void set_volume (double volume)
+ {
+ return_if_fail (context.get_state () == Context.State.READY);
+
+ _volume = volume;
+
+ context.get_server_info (server_info_cb_for_set_volume);
+ }
+
+ void set_mic_volume_success_cb (Context c, int success)
+ {
+ if ((bool)success)
+ mic_volume_changed (_mic_volume);
+ }
+
+ public void set_mic_volume (double volume)
+ {
+ return_if_fail (context.get_state () == Context.State.READY);
+
+ _mic_volume = volume;
+
+ context.get_server_info ( (c, i) => {
+ if (i != null) {
+ unowned CVolume cvol = CVolume ();
+ cvol = vol_set (cvol, 1, double_to_volume (_mic_volume));
+ c.set_source_volume_by_name (i.default_source_name, cvol, set_mic_volume_success_cb);
+ }
+ });
+ }
+
+ public double get_volume ()
+ {
+ return _volume;
+ }
+
+ public double get_mic_volume ()
+ {
+ return _mic_volume;
+ }
+}
diff --git a/src/volume-widget.c b/src/volume-widget.c
deleted file mode 100644
index 1258c20..0000000
--- a/src/volume-widget.c
+++ /dev/null
@@ -1,338 +0,0 @@
-
-/*
-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-lib.h>
-#include <math.h>
-#include <glib.h>
-#include "volume-widget.h"
-#include "common-defs.h"
-#include <libido/idoscalemenuitem.h>
-#include "indicator-sound.h"
-
-typedef struct _VolumeWidgetPrivate VolumeWidgetPrivate;
-
-struct _VolumeWidgetPrivate
-{
- DbusmenuMenuitem* twin_item;
- GtkWidget* ido_volume_slider;
- gboolean grabbed;
- IndicatorObject* indicator;
-};
-
-#define VOLUME_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOLUME_WIDGET_TYPE, VolumeWidgetPrivate))
-
-/* Prototypes */
-static void volume_widget_class_init (VolumeWidgetClass *klass);
-static void volume_widget_init (VolumeWidget *self);
-static void volume_widget_dispose (GObject *object);
-static void volume_widget_finalize (GObject *object);
-static void volume_widget_set_twin_item( VolumeWidget* self,
- DbusmenuMenuitem* twin_item);
-static void volume_widget_property_update( DbusmenuMenuitem* item, gchar* property,
- GVariant* value, gpointer userdata );
-
-static gboolean volume_widget_change_value_cb (GtkRange *range,
- GtkScrollType scroll,
- gdouble value,
- gpointer user_data);
-static void volume_widget_primary_clicked(GtkWidget *widget, gpointer user_data);
-static void volume_widget_secondary_clicked(GtkWidget *widget, gpointer user_data);
-static void volume_widget_slider_grabbed(GtkWidget *widget, gpointer user_data);
-static void volume_widget_slider_released(GtkWidget *widget, gpointer user_data);
-static void volume_widget_parent_changed (GtkWidget *widget, gpointer user_data);
-
-G_DEFINE_TYPE (VolumeWidget, volume_widget, G_TYPE_OBJECT);
-
-
-static void
-volume_widget_class_init (VolumeWidgetClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (VolumeWidgetPrivate));
-
- gobject_class->dispose = volume_widget_dispose;
- gobject_class->finalize = volume_widget_finalize;
-}
-
-static void
-volume_widget_init (VolumeWidget *self)
-{
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
-
- priv->ido_volume_slider = ido_scale_menu_item_new_with_range ("VOLUME", IDO_RANGE_STYLE_DEFAULT, 0, 0, 100, 1);
- g_object_ref (priv->ido_volume_slider);
- ido_scale_menu_item_set_primary_label (IDO_SCALE_MENU_ITEM(priv->ido_volume_slider), "VOLUME");
- ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (priv->ido_volume_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE);
- g_object_set(priv->ido_volume_slider, "reverse-scroll-events", TRUE, NULL);
-
- g_signal_connect (priv->ido_volume_slider,
- "notify::parent", G_CALLBACK (volume_widget_parent_changed),
- NULL);
-
- GtkWidget* volume_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
-
- g_signal_connect(volume_widget, "change-value", G_CALLBACK(volume_widget_change_value_cb), self);
- g_signal_connect(priv->ido_volume_slider, "primary-clicked", G_CALLBACK(volume_widget_primary_clicked), self);
- g_signal_connect(priv->ido_volume_slider, "secondary-clicked", G_CALLBACK(volume_widget_secondary_clicked), self);
- g_signal_connect(priv->ido_volume_slider, "slider-grabbed", G_CALLBACK(volume_widget_slider_grabbed), self);
- g_signal_connect(priv->ido_volume_slider, "slider-released", G_CALLBACK(volume_widget_slider_released), self);
-
- GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)priv->ido_volume_slider);
- GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-low-zero-panel");
- gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU);
- g_object_unref(primary_gicon);
-
- GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_volume_slider);
- GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-high-panel");
- gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU);
- g_object_unref(secondary_gicon);
-
- GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (volume_widget));
- gtk_adjustment_set_step_increment(adj, 4);
-}
-
-static void
-volume_widget_dispose (GObject *object)
-{
- G_OBJECT_CLASS (volume_widget_parent_class)->dispose (object);
-}
-
-static void
-volume_widget_finalize (GObject *object)
-{
- G_OBJECT_CLASS (volume_widget_parent_class)->finalize (object);
-}
-
-static void
-volume_widget_property_update( DbusmenuMenuitem* item, gchar* property,
- GVariant* value, gpointer userdata)
-{
- g_return_if_fail (IS_VOLUME_WIDGET(userdata));
- VolumeWidget* mitem = VOLUME_WIDGET(userdata);
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
-
- if(g_ascii_strcasecmp(DBUSMENU_VOLUME_MENUITEM_LEVEL, property) == 0){
- g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE) );
- gdouble update = g_variant_get_double (value);
-
- if(priv->grabbed == FALSE){
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
- GtkRange *range = (GtkRange*)slider;
- gtk_range_set_value(range, update);
-/*
- g_debug ("volume-widget::volume_widget_property_update - volume - value %f", update);
- AtkObject* atk_object;
- atk_object = gtk_widget_get_accessible (priv->ido_volume_slider);
- if (atk_object != NULL){
- atk_object_set_name (atk_object, desc);
-
- }*/
- }
- gchar* desc = g_strdup_printf(_("Volume (%'.0f%%)"),
- update);
- dbusmenu_menuitem_property_set (priv->twin_item,
- DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC,
- desc);
- g_free (desc);
- update_accessible_desc(priv->indicator);
- }
- else if(g_ascii_strcasecmp(DBUSMENU_VOLUME_MENUITEM_MUTE, property) == 0){
- g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN));
- if(priv->grabbed == FALSE){
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
- GtkRange *range = (GtkRange*)slider;
- gboolean update = g_variant_get_boolean (value);
- gdouble level;
-
- if (update == TRUE){
- level = 0;
- }
- else{
- GVariant* variant = dbusmenu_menuitem_property_get_variant (priv->twin_item,
- DBUSMENU_VOLUME_MENUITEM_LEVEL);
-/*
- g_debug ("variant for the volume - is it null = %i", variant == NULL);
-*/
- g_return_if_fail (g_variant_is_of_type (variant, G_VARIANT_TYPE_DOUBLE) );
-
- level = g_variant_get_double (variant);
- }
-/*
- g_debug ("volume-widget::volume_widget_property_update - mute - value %i and level = %f", update, level);
-*/
- gtk_range_set_value(range, level);
- }
- }
-}
-
-static void
-volume_widget_set_twin_item(VolumeWidget* self,
- DbusmenuMenuitem* twin_item)
-{
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
- priv->twin_item = twin_item;
- g_object_ref(priv->twin_item);
- g_signal_connect(G_OBJECT(twin_item), "property-changed",
- G_CALLBACK(volume_widget_property_update), self);
- gdouble initial_level = g_variant_get_double (dbusmenu_menuitem_property_get_variant(twin_item,
- DBUSMENU_VOLUME_MENUITEM_LEVEL));
- gboolean initial_mute = g_variant_get_boolean (dbusmenu_menuitem_property_get_variant(twin_item,
- DBUSMENU_VOLUME_MENUITEM_MUTE));
-
- //g_debug("volume_widget_set_twin_item initial level = %f", initial_level);
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
- GtkRange *range = (GtkRange*)slider;
- if(initial_mute == TRUE){
- initial_level = 0;
- }
- gtk_range_set_value(range, initial_level);
- gchar* desc = g_strdup_printf(_("Volume (%'.0f%%)"),
- initial_level);
- dbusmenu_menuitem_property_set (priv->twin_item,
- DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC,
- desc);
- g_free (desc);
-
-}
-
-static gboolean
-volume_widget_change_value_cb (GtkRange *range,
- GtkScrollType scroll,
- gdouble new_value,
- gpointer user_data)
-{
- g_return_val_if_fail (IS_VOLUME_WIDGET (user_data), FALSE);
- VolumeWidget* mitem = VOLUME_WIDGET(user_data);
-
-/*
- g_debug ("changed value %f", new_value);
-*/
-
- volume_widget_update(mitem, new_value, "change-value");
- return FALSE;
-}
-
-void
-volume_widget_update(VolumeWidget* self, gdouble update, gchar* label)
-{
- gchar* source = NULL;
- source = label;
- if (label == NULL){
- source = "v widget update";
- }
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
- gdouble clamped = CLAMP(update, 0, 100);
- GVariant* new_volume = g_variant_new_double(clamped);
- dbusmenu_menuitem_handle_event (priv->twin_item, source, new_volume, 0);
-}
-
-static void
-volume_widget_update_from_scale (VolumeWidget *self)
-{
- g_return_if_fail (IS_VOLUME_WIDGET (self));
-
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
- GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
- const gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100);
- g_debug ("%s - setting value to %.0f", G_STRFUNC, current_value);
- volume_widget_update (self, current_value, "value-changed");
-}
-
-static void
-volume_widget_primary_clicked (GtkWidget *widget G_GNUC_UNUSED, gpointer user_data)
-{
- volume_widget_update_from_scale (VOLUME_WIDGET(user_data));
-}
-
-static void
-volume_widget_secondary_clicked(GtkWidget *widget, gpointer user_data)
-{
- volume_widget_update_from_scale (VOLUME_WIDGET(user_data));
-}
-
-GtkWidget*
-volume_widget_get_ido_slider(VolumeWidget* self)
-{
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
- return priv->ido_volume_slider;
-}
-
-static void
-volume_widget_parent_changed (GtkWidget *widget,
- gpointer user_data)
-{
- gtk_widget_set_size_request (widget, 200, -1);
- //g_debug("volume_widget_parent_changed");
-}
-
-static void
-volume_widget_slider_grabbed(GtkWidget *widget, gpointer user_data)
-{
- VolumeWidget* mitem = VOLUME_WIDGET(user_data);
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
- priv->grabbed = TRUE;
-}
-
-static void
-volume_widget_slider_released(GtkWidget *widget, gpointer user_data)
-{
- VolumeWidget* mitem = VOLUME_WIDGET(user_data);
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
- priv->grabbed = FALSE;
-}
-
-void
-volume_widget_tidy_up (GtkWidget *widget)
-{
- VolumeWidget* mitem = VOLUME_WIDGET(widget);
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
- gtk_widget_destroy (priv->ido_volume_slider);
-}
-
-gdouble
-volume_widget_get_current_volume ( GtkWidget *widget )
-{
- VolumeWidget* mitem = VOLUME_WIDGET(widget);
- VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
- gdouble vol = g_variant_get_double( dbusmenu_menuitem_property_get_variant( priv->twin_item,
- DBUSMENU_VOLUME_MENUITEM_LEVEL));
- return vol;
-}
-
-/**
- * volume_widget_new:
- * @returns: a new #VolumeWidget.
- **/
-GtkWidget*
-volume_widget_new(DbusmenuMenuitem *item, IndicatorObject* io)
-{
- GtkWidget* widget = g_object_new(VOLUME_WIDGET_TYPE, NULL);
- VolumeWidgetPrivate* priv = VOLUME_WIDGET_GET_PRIVATE(VOLUME_WIDGET(widget));
- priv->indicator = io;
- volume_widget_set_twin_item((VolumeWidget*)widget, item);
- return widget;
-}
-
-
diff --git a/src/volume-widget.h b/src/volume-widget.h
deleted file mode 100644
index 665f39b..0000000
--- a/src/volume-widget.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-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 __VOLUME_WIDGET_H__
-#define __VOLUME_WIDGET_H__
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
-#include <libdbusmenu-gtk/menuitem.h>
-#include <libindicator/indicator-object.h>
-
-G_BEGIN_DECLS
-
-#define VOLUME_WIDGET_TYPE (volume_widget_get_type ())
-#define VOLUME_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VOLUME_WIDGET_TYPE, VolumeWidget))
-#define VOLUME_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VOLUME_WIDGET_TYPE, VolumeWidgetClass))
-#define IS_VOLUME_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VOLUME_WIDGET_TYPE))
-#define IS_VOLUME_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VOLUME_WIDGET_TYPE))
-#define VOLUME_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VOLUME_WIDGET_TYPE, VolumeWidgetClass))
-
-typedef struct _VolumeWidget VolumeWidget;
-typedef struct _VolumeWidgetClass VolumeWidgetClass;
-
-struct _VolumeWidgetClass {
- GObjectClass parent_class;
-};
-
-struct _VolumeWidget {
- GObject parent;
-};
-
-GType volume_widget_get_type (void) G_GNUC_CONST;
-GtkWidget* volume_widget_new(DbusmenuMenuitem *item, IndicatorObject* io);
-GtkWidget* volume_widget_get_ido_slider(VolumeWidget* self);
-void volume_widget_update(VolumeWidget* self, gdouble update, gchar* label);
-void volume_widget_tidy_up (GtkWidget *widget);
-gdouble volume_widget_get_current_volume ( GtkWidget *widget );
-
-G_END_DECLS
-
-#endif
-