cairo-dock-plugins-3.3.2/alsaMixer/src/applet-struct.h 000775 001750 001750 00000006257 12225027055 024060 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __CD_APPLET_STRUCT__
#define __CD_APPLET_STRUCT__
#include
#include
#define _STRUCT_TIMEVAL
#include
#ifdef INDICATOR_SOUNDMENU_WITH_IND3
#include "indicator-applet3.h"
#elif defined SOUND_SERVICE_SUPPORT // OLD
#include "indicator-applet.h"
#include "mute-widget.h"
#endif
// Info display types
typedef enum {
VOLUME_NO_DISPLAY = 0,
VOLUME_ON_LABEL,
VOLUME_ON_ICON,
VOLUME_NB_DISPLAYS
} VolumeTypeDisplay;
// Icon display types
typedef enum {
VOLUME_EFFECT_NONE = 0,
VOLUME_EFFECT_BAR,
VOLUME_EFFECT_GAUGE,
VOLUME_NB_EFFECTS
} VolumeTypeEffect;
struct _AppletConfig {
// alsa options
gchar *card_id;
gchar *cMixerElementName;
gchar *cMixerElementName2;
gchar *cShowAdvancedMixerCommand;
// display
VolumeTypeDisplay iVolumeDisplay;
VolumeTypeEffect iVolumeEffect;
gchar *cDefaultIcon;
gchar *cBrokenIcon;
gchar *cMuteIcon;
gchar *cGThemePath;
RendererRotateTheme iRotateTheme;
// accesibility
gchar *cShortcut;
gint iScrollVariation;
gboolean bHideScaleOnLeave;
#ifdef INDICATOR_SOUNDMENU_WITH_IND3
gchar *cIndicatorName;
#endif
} ;
// Interface of a Sound Controler
typedef struct {
int (*get_volume) (void);
void (*set_volume) (int iVolume);
void (*toggle_mute) (void);
void (*show_hide) (void);
void (*stop) (void);
void (*reload) (void);
} CDSoundCtl;
struct _AppletData {
// generic interface
CDSoundCtl ctl;
// alsa data
snd_mixer_t *mixer_handle;
gchar *mixer_card_name;
gchar *mixer_device_name;
gchar *cErrorMessage;
snd_mixer_elem_t *pControledElement;
snd_mixer_elem_t *pControledElement2; // des fois un element ne controle qu'une sortie (droite ou gauche).
snd_mixer_selem_id_t *pControledID;
gboolean bHasMuteSwitch;
long iVolumeMin, iVolumeMax; // volumes min et max en unites de la carte son.
guint iSidCheckVolume;
CairoDialog *pDialog;
int iCurrentVolume; // current volume in [0-100]
// sound service data
#ifdef INDICATOR_SOUNDMENU_WITH_IND3
IndicatorObject *pIndicator;
IndicatorObjectEntry *pEntry;
#elif defined SOUND_SERVICE_SUPPORT // OLD
CDAppletIndicator *pIndicator;
GtkWidget* volume_widget;
GList *transport_widgets_list;
GtkWidget* voip_widget;
MuteWidget* mute_widget;
gint iCurrentState;
#endif
// other
gboolean bIsMute;
gint bMuteImage; // 1 if the "mute" image is currently displayed, 0 if the normal icon is set, -1 if no image is set
GtkWidget *pScale;
GldiShortkey *cKeyBinding;
} ;
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/voip-input-widget.h 000664 001750 001750 00000004162 12223247501 024630 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2011 Canonical Ltd.
Authors:
Conor Curran
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 .
*/
#ifndef __VOIP_INPUT_WIDGET_H__
#define __VOIP_INPUT_WIDGET_H__
#include
#include
#include
#if (GTK_MAJOR_VERSION < 3) || defined (DBUSMENU_GTK3_NEW)
#include
#else
#include
#endif
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
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-generic.h 000775 001750 001750 00000002241 12223247501 024133 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_GENERIC__
#define __APPLET_GENERIC__
#include
int cd_get_volume (void);
void cd_set_volume (int iVolume);
void cd_toggle_mute (void);
void cd_show_hide (void);
void cd_stop (void);
void cd_reload (void);
void cd_start (void);
GtkWidget *mixer_build_widget (gboolean bHorizontal);
void cd_mixer_set_volume_with_no_callback (GtkWidget *pScale, int iVolume);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/mute-widget.c 000664 001750 001750 00000007263 12223247501 023470 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2011 Canonical Ltd.
Authors:
Marco Trevisan (Treviño)
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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#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;
}
cairo-dock-plugins-3.3.2/alsaMixer/src/metadata-widget.h 000664 001750 001750 00000003545 12223247501 024302 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2010 Canonical Ltd.
Authors:
Conor Curran
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 .
*/
#ifndef __METADATA_WIDGET_H__
#define __METADATA_WIDGET_H__
#include
#if (GTK_MAJOR_VERSION < 3) || defined (DBUSMENU_GTK3_NEW)
#include
#else
#include
#endif
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
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-generic.c 000775 001750 001750 00000006634 12223247501 024140 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* based on indicator-messages.c written by :
* Ted Gould
* Cody Russell
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include
#include "applet-struct.h"
#include "applet-backend-alsamixer.h"
#ifdef INDICATOR_SOUNDMENU_WITH_IND3
#include "applet-backend-sound-menu.h"
#elif defined SOUND_SERVICE_SUPPORT // OLD
#include "applet-backend-sound-menu-old.h"
#endif
#include "applet-generic.h"
int cd_get_volume (void)
{
if (myData.ctl.get_volume)
return myData.ctl.get_volume ();
return 0;
}
void cd_set_volume (int iVolume)
{
if (myData.ctl.set_volume)
myData.ctl.set_volume (iVolume);
}
void cd_toggle_mute (void)
{
if (myData.ctl.toggle_mute)
myData.ctl.toggle_mute ();
}
void cd_show_hide (void)
{
if (myData.ctl.show_hide)
myData.ctl.show_hide ();
}
void cd_stop (void)
{
if (myData.ctl.stop)
myData.ctl.stop ();
}
void cd_reload (void)
{
if (myData.ctl.reload)
myData.ctl.reload ();
}
void cd_start (void)
{
#if defined INDICATOR_SOUNDMENU_WITH_IND3 || defined SOUND_SERVICE_SUPPORT
cd_mixer_connect_to_sound_service (); // connect to the sound service, it will fall back to alsa if it's not available.
#else
cd_mixer_init_alsa ();
#endif
}
/// SCALE ///
static void on_change_volume (GtkRange *range, gpointer data)
{
CD_APPLET_ENTER;
int iNewVolume = (int) gtk_range_get_value (GTK_RANGE (range));
cd_debug ("%s (%d)", __func__, iNewVolume);
cd_set_volume (iNewVolume);
CD_APPLET_LEAVE();
}
GtkWidget *mixer_build_widget (gboolean bHorizontal)
{
g_return_val_if_fail (myData.pControledElement != NULL, NULL);
#if (GTK_MAJOR_VERSION < 3)
GtkWidget *pScale = (bHorizontal ? gtk_hscale_new_with_range (0., 100., .5*myConfig.iScrollVariation) : gtk_vscale_new_with_range (0., 100., .5*myConfig.iScrollVariation));
#else
GtkWidget *pScale = gtk_scale_new_with_range (bHorizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, 0., 100., .5*myConfig.iScrollVariation);
#endif
if (! bHorizontal)
gtk_range_set_inverted (GTK_RANGE (pScale), TRUE); // de bas en haut.
myData.iCurrentVolume = cd_get_volume ();
gtk_range_set_value (GTK_RANGE (pScale), myData.iCurrentVolume);
g_signal_connect (G_OBJECT (pScale),
"value-changed",
G_CALLBACK (on_change_volume),
NULL);
gldi_dialog_set_widget_text_color (pScale);
return pScale;
}
void cd_mixer_set_volume_with_no_callback (GtkWidget *pScale, int iVolume)
{
g_signal_handlers_block_matched (GTK_WIDGET(pScale),
G_SIGNAL_MATCH_FUNC,
0, 0, NULL, (void*)on_change_volume, NULL);
gtk_range_set_value (GTK_RANGE (pScale), (double) iVolume);
g_signal_handlers_unblock_matched (GTK_WIDGET(pScale),
G_SIGNAL_MATCH_FUNC,
0, 0, NULL, (void*)on_change_volume, NULL);
}
cairo-dock-plugins-3.3.2/alsaMixer/src/dbus-shared-names.h 000664 001750 001750 00000002520 12223247501 024533 0 ustar 00mbaerts mbaerts 000000 000000 /*
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
Ted Gould
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 .
*/
#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__ */
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-init.h 000775 001750 001750 00000001553 12223247501 023467 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_INIT__
#define __APPLET_INIT__
#include
CD_APPLET_H
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/volume-widget.h 000664 001750 001750 00000004242 12223247501 024024 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2010 Canonical Ltd.
Authors:
Conor Curran
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 .
*/
#ifndef __VOLUME_WIDGET_H__
#define __VOLUME_WIDGET_H__
#include
#include
#include
#if (GTK_MAJOR_VERSION < 3) || defined (DBUSMENU_GTK3_NEW)
#include
#else
#include
#endif
///#include
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, const gchar* label);
void volume_widget_tidy_up (GtkWidget *widget);
gdouble volume_widget_get_current_volume ( GtkWidget *widget );
G_END_DECLS
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-notifications.h 000775 001750 001750 00000002076 12223247501 025376 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_NOTIFICATIONS__
#define __APPLET_NOTIFICATIONS__
#include
CD_APPLET_ON_CLICK_H
CD_APPLET_ON_MIDDLE_CLICK_H
CD_APPLET_ON_BUILD_MENU_H
CD_APPLET_ON_SCROLL_H
CD_APPLET_ON_DOUBLE_CLICK_H
void mixer_on_keybinding_pull (const char *keystring, gpointer user_data);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-backend-alsamixer.h 000775 001750 001750 00000001713 12223247501 026074 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_MIXER__
#define __APPLET_MIXER__
#include
GList *mixer_get_cards_list (void);
GList *mixer_get_elements_list (void);
void cd_mixer_init_alsa (void);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/transport-widget.c 000664 001750 001750 00000163103 12223247501 024546 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2010 Canonical Ltd.
Authors:
Conor Curran
Mirco Müller
Andrea Cimitan
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 .
Uses code from ctk
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#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 )
{
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,
"Transport 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,
"Transport 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,
"Transport 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,
"Transport 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
#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];
#if (GTK_MAJOR_VERSION < 3)
GtkStyle *style = gtk_widget_get_style (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;
#else
GtkStyleContext *style = gtk_widget_get_style_context (button);
gtk_style_context_get_background_color (style, 0, (GdkRGBA*)&bg_color);
gtk_style_context_get_background_color (style, GTK_STATE_PRELIGHT, (GdkRGBA*)&bg_prelight);
gtk_style_context_get_background_color (style, GTK_STATE_SELECTED, (GdkRGBA*)&bg_selected);
gtk_style_context_get_color (style, 0, (GdkRGBA*)&fg_color);
#endif
_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); // triggers the notification
#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;
}
cairo-dock-plugins-3.3.2/alsaMixer/src/mute-widget.h 000664 001750 001750 00000004127 12223247501 023471 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2011 Canonical Ltd.
Authors:
Marco Trevisan (Treviño)
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 .
*/
#ifndef __MUTE_WIDGET_H__
#define __MUTE_WIDGET_H__
#include
#include
#include
#if (GTK_MAJOR_VERSION < 3) || defined (DBUSMENU_GTK3_NEW)
#include
#else
#include
#endif
#include
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
cairo-dock-plugins-3.3.2/alsaMixer/src/CMakeLists.txt 000664 001750 001750 00000006032 12223247501 023622 0 ustar 00mbaerts mbaerts 000000 000000
########### sources ###############
set (cd-AlsaMixer_LIB_SRCS
applet-init.c applet-init.h
applet-config.c applet-config.h
applet-notifications.c applet-notifications.h
applet-draw.c applet-draw.h
applet-generic.c applet-generic.h
# alsa backend
applet-backend-alsamixer.c applet-backend-alsamixer.h
applet-struct.h)
# Sound service backend (optionnal)
if (INDICATOR_SOUNDMENU_WITH_IND3)
list (APPEND cd-AlsaMixer_LIB_SRCS
applet-backend-sound-menu.c applet-backend-sound-menu.h)
elseif (with_soundmenu)
list (APPEND cd-AlsaMixer_LIB_SRCS
applet-backend-sound-menu-old.c applet-backend-sound-menu-old.h
applet-menu.c applet-menu.h
volume-widget.c volume-widget.h
voip-input-widget.c voip-input-widget.h
transport-widget.c transport-widget.h
mute-widget.c mute-widget.h
metadata-widget.c metadata-widget.h)
endif()
add_library (${PACKAGE_ALSA_MIXER} SHARED ${cd-AlsaMixer_LIB_SRCS})
########### compil ###############
add_definitions (-DMY_APPLET_SHARE_DATA_DIR="${alsa_mixerdatadir}")
add_definitions (-DMY_APPLET_PREVIEW_FILE="preview.jpg")
add_definitions (-DMY_APPLET_CONF_FILE="AlsaMixer.conf")
add_definitions (-DMY_APPLET_USER_DATA_DIR="AlsaMixer")
add_definitions (-DMY_APPLET_VERSION="${VERSION_ALSA_MIXER}")
add_definitions (-DMY_APPLET_GETTEXT_DOMAIN="${GETTEXT_ALSA_MIXER}")
add_definitions (-DMY_APPLET_DOCK_VERSION="${dock_version}")
add_definitions (-DMY_APPLET_ICON_FILE="icon.png")
if (INDICATOR_SOUNDMENU_WITH_IND3)
message (STATUS " With Indicator-Applet3")
add_definitions (-DINDICATOR_SOUNDMENU_WITH_IND3=1)
if (INDICATOR_NG)
add_definitions (-DIS_INDICATOR_NG=1)
endif()
set (EXTRAS_INCLUDE_DIRS ${INDICATOR_APPLET_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/Indicator-applet3)
set (EXTRAS_LIBRARY_DIRS ${INDICATOR_APPLET_LIBRARY_DIRS}
${CMAKE_SOURCE_DIR}/Indicator-applet3)
set (EXTRAS_LIBRARIES ${INDICATOR_APPLET_LIBRARIES} indicator-applet3)
elseif (with_soundmenu)
add_definitions (-DSOUND_SERVICE_SUPPORT="1")
add_definitions (-DSOUND_SERVICE_VERSION=${SOUND_SERVICE_VERSION})
if (${DBUSMENU_GTK3_NEW})
add_definitions (-DDBUSMENU_GTK3_NEW=1)
endif()
set (EXTRAS_INCLUDE_DIRS ${DBUSMENU_INCLUDE_DIRS}
${DBUSMENU_GTK_INCLUDE_DIRS} ${INDICATOR_APPLET_INCLUDE_DIRS}
${IDO_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/Indicator-applet)
set (EXTRAS_LIBRARY_DIRS ${DBUSMENU_LIBRARY_DIRS}
${DBUSMENU_GTK_LIBRARY_DIRS} ${INDICATOR_APPLET_LIBRARY_DIRS}
${IDO_LIBRARY_DIRS} ${CMAKE_SOURCE_DIR}/Indicator-applet)
set (EXTRAS_LIBRARIES ${DBUSMENU_LIBRARIES} ${DBUSMENU_GTK_LIBRARIES}
${INDICATOR_APPLET_LIBRARIES} ${IDO_LIBRARIES} indicator-applet)
endif()
include_directories (
${PACKAGE_INCLUDE_DIRS}
${ALSA_MIXER_PACKAGE_INCLUDE_DIRS}
${EXTRAS_INCLUDE_DIRS})
link_directories (
${PACKAGE_LIBRARY_DIRS}
${ALSA_MIXER_PACKAGE_LIBRARY_DIRS}
${EXTRAS_LIBRARY_DIRS})
target_link_libraries (${PACKAGE_ALSA_MIXER}
${PACKAGE_LIBRARIES}
${ALSA_MIXER_PACKAGE_LIBRARIES}
${EXTRAS_LIBRARIES})
########### install files ###############
install(TARGETS ${PACKAGE_ALSA_MIXER} DESTINATION ${pluginsdir})
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-menu.c 000775 001750 001750 00000036575 12223247501 023477 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* based on indicator-messages.c written by :
* Ted Gould
* Cody Russell
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
/// This file is essentially indicator-sound.c, adapted to Cairo-Dock.
#include
#include
#include
#include "applet-struct.h"
#include "applet-backend-sound-menu-old.h" // update_accessible_desc
#include "transport-widget.h"
#include "volume-widget.h"
#include "voip-input-widget.h"
#include "mute-widget.h"
#include "metadata-widget.h"
#include "applet-menu.h"
#if (GTK_MAJOR_VERSION < 3) || defined (DBUSMENU_GTK3_NEW)
#include
#include
#else
#include
#include
#endif
#include
#if (GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 20)
#include
#endif
#include
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 );*/
myData.transport_widgets_list = g_list_append ( myData.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));*/
AppletData *priv = myDataPtr;
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.
/// TODO: check that it's not needed...
update_accessible_desc (-1/**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));*/
AppletData *priv = myDataPtr;
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));*/
AppletData *priv = myDataPtr;
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);
AppletData *priv = myDataPtr;
GtkWidget *menuitem;
///menuitem = get_current_item (GTK_CONTAINER (widget));
#if (GTK_MAJOR_VERSION < 3)
menuitem = GTK_MENU_SHELL (widget)->active_menu_item;
#else
menuitem = gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (widget));
#endif
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);
AppletData *priv = myDataPtr;
GtkWidget *menuitem;
///menuitem = get_current_item (GTK_CONTAINER (widget));
#if (GTK_MAJOR_VERSION < 3)
menuitem = GTK_MENU_SHELL (widget)->active_menu_item;
#else
menuitem = gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (widget));
#endif
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;
}
///////////////
// MAKE MENU //
///////////////
void cd_sound_add_menu_handler (DbusmenuGtkClient * client)
{
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 (myData.pIndicator->pMenu, "key-press-event", G_CALLBACK(key_press_cb), myApplet);
g_signal_connect (myData.pIndicator->pMenu, "key-release-event", G_CALLBACK(key_release_cb), myApplet);
}
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-init.c 000775 001750 001750 00000017555 12225027055 023475 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include "applet-struct.h"
#include "applet-config.h"
#include "applet-notifications.h"
#include "applet-draw.h"
#include "applet-generic.h"
#include "applet-init.h"
CD_APPLET_DEFINE_BEGIN ("AlsaMixer",
2, 0, 0,
CAIRO_DOCK_CATEGORY_APPLET_SYSTEM,
N_("This applet lets you control the sound volume from the dock.\n"
"Scroll up/down on the icon to increase/decrease the volume.\n"
"Click on icon to show/hide the volume control (you can bind a keyboard shortcut for it)\n"
"Middle-click to set or unset to mute, double-click to raise the channels mixer.\n"
"The applet can either use the Ubuntu Sound-menu or the Alsa driver."),
"Fabounet (Fabrice Rey)")
CD_APPLET_DEFINE_COMMON_APPLET_INTERFACE
CD_APPLET_ALLOW_EMPTY_TITLE
CD_APPLET_REDEFINE_TITLE (N_("Sound Control"))
pInterface->load_custom_widget = cd_mixer_load_custom_widget;
CD_APPLET_DEFINE_END
static gboolean _cd_mixer_on_enter (GtkWidget* pWidget,
GdkEventCrossing* pEvent,
gpointer data)
{
if (myData.pScale && myDesklet && myDesklet->container.iHeight > 64)
{
gtk_widget_show (myData.pScale);
}
return GLDI_NOTIFICATION_LET_PASS;
}
gboolean _cd_mixer_on_leave (GtkWidget* pWidget,
GdkEventCrossing* pEvent,
gpointer data)
{
if (myData.pScale && myDesklet && myDesklet->container.iHeight > 64)
{
if (! myDesklet->container.bInside)
gtk_widget_hide (myData.pScale);
}
return GLDI_NOTIFICATION_LET_PASS;
}
static void _set_data_renderer (void)
{
switch (myConfig.iVolumeEffect)
{
case VOLUME_EFFECT_GAUGE:
{
CairoDataRendererAttribute *pRenderAttr; // les attributs du data-renderer global.
CairoGaugeAttribute attr; // les attributs de la jauge.
memset (&attr, 0, sizeof (CairoGaugeAttribute));
pRenderAttr = CAIRO_DATA_RENDERER_ATTRIBUTE (&attr);
pRenderAttr->cModelName = "gauge";
pRenderAttr->iRotateTheme = myConfig.iRotateTheme;
attr.cThemePath = myConfig.cGThemePath;
CD_APPLET_ADD_DATA_RENDERER_ON_MY_ICON (pRenderAttr);
}
break;
case VOLUME_EFFECT_BAR:
{
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cDefaultIcon, "default.svg");
CairoDataRendererAttribute *pRenderAttr; // les attributs du data-renderer global.
CairoProgressBarAttribute attr;
memset (&attr, 0, sizeof (CairoProgressBarAttribute));
pRenderAttr = CAIRO_DATA_RENDERER_ATTRIBUTE (&attr);
pRenderAttr->cModelName = "progressbar";
pRenderAttr->iRotateTheme = myConfig.iRotateTheme;
CD_APPLET_ADD_DATA_RENDERER_ON_MY_ICON (pRenderAttr);
}
break;
case VOLUME_EFFECT_NONE:
case VOLUME_NB_EFFECTS:
break;
}
}
CD_APPLET_INIT_BEGIN
// set a desklet renderer
if (myDesklet)
{
int iScaleWidth = (myDesklet->container.iHeight > 64 ? 15 : 0);
gpointer pConfig[4] = {GINT_TO_POINTER (0), GINT_TO_POINTER (0), GINT_TO_POINTER (iScaleWidth), GINT_TO_POINTER (iScaleWidth)};
CD_APPLET_SET_DESKLET_RENDERER_WITH_DATA ("Simple", pConfig);
// scale widget visibility in desklet
if (myConfig.bHideScaleOnLeave)
{
g_signal_connect (G_OBJECT (myDesklet->container.pWidget),
"enter-notify-event",
G_CALLBACK (_cd_mixer_on_enter),
NULL);
g_signal_connect (G_OBJECT (myDesklet->container.pWidget),
"leave-notify-event",
G_CALLBACK (_cd_mixer_on_leave),
NULL);
}
}
// data renderer
_set_data_renderer ();
myData.bMuteImage = -1; // no image is set on the icon
// start the sound controler
cd_start ();
// mouse events
CD_APPLET_REGISTER_FOR_CLICK_EVENT;
CD_APPLET_REGISTER_FOR_MIDDLE_CLICK_EVENT;
CD_APPLET_REGISTER_FOR_BUILD_MENU_EVENT;
CD_APPLET_REGISTER_FOR_SCROLL_EVENT;
CD_APPLET_REGISTER_FOR_DOUBLE_CLICK_EVENT;
// keyboard events
myData.cKeyBinding = CD_APPLET_BIND_KEY (myConfig.cShortcut,
D_("Show/hide the Sound menu"), // if no sound service, it's just a dialog though ...
"Configuration", "shortkey",
(CDBindkeyHandler) mixer_on_keybinding_pull);
CD_APPLET_INIT_END
CD_APPLET_STOP_BEGIN
//\_______________ mouse events.
CD_APPLET_UNREGISTER_FOR_CLICK_EVENT;
CD_APPLET_UNREGISTER_FOR_MIDDLE_CLICK_EVENT;
CD_APPLET_UNREGISTER_FOR_BUILD_MENU_EVENT;
CD_APPLET_UNREGISTER_FOR_SCROLL_EVENT;
CD_APPLET_UNREGISTER_FOR_DOUBLE_CLICK_EVENT;
// keyboard events
gldi_object_unref (GLDI_OBJECT(myData.cKeyBinding));
// stop the current controler.
cd_stop ();
CD_APPLET_STOP_END
CD_APPLET_RELOAD_BEGIN
//\_______________ On recharge le mixer si necessaire.
if (CD_APPLET_MY_CONFIG_CHANGED)
{
if (myDesklet)
{
int iScaleWidth = (myDesklet->container.iHeight > 64 ? 15 : 0);
gpointer pConfig[4] = {GINT_TO_POINTER (0), GINT_TO_POINTER (0), GINT_TO_POINTER (iScaleWidth), GINT_TO_POINTER (iScaleWidth)};
CD_APPLET_SET_DESKLET_RENDERER_WITH_DATA ("Simple", pConfig);
}
if (myConfig.iVolumeDisplay != VOLUME_ON_ICON)
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON_PRINTF (NULL);
// reload or remove the data renderer
if (myConfig.iVolumeEffect == VOLUME_EFFECT_NONE)
{
CD_APPLET_REMOVE_MY_DATA_RENDERER;
}
else
{
_set_data_renderer ();
}
myData.bMuteImage = -1; // to re-apply the image on the icon
// reload the controler
cd_reload ();
// shortkey
gldi_shortkey_rebind (myData.cKeyBinding, myConfig.cShortcut, NULL);
// scale
if (myDesklet)
{
if (CD_APPLET_MY_CONTAINER_TYPE_CHANGED)
{
gldi_object_unref (GLDI_OBJECT(myData.pDialog));
myData.pDialog = NULL;
GtkWidget *box = _gtk_hbox_new (0);
myData.pScale = mixer_build_widget (FALSE);
gtk_box_pack_end (GTK_BOX (box), myData.pScale, FALSE, FALSE, 0);
gtk_widget_show_all (box);
gtk_container_add (GTK_CONTAINER (myDesklet->container.pWidget), box);
if (myConfig.bHideScaleOnLeave && ! myDesklet->container.bInside)
gtk_widget_hide (myData.pScale);
}
gulong iOnEnterCallbackID = g_signal_handler_find (myDesklet->container.pWidget,
G_SIGNAL_MATCH_FUNC,
0,
0,
NULL,
_cd_mixer_on_enter,
NULL);
if (myConfig.bHideScaleOnLeave && iOnEnterCallbackID <= 0)
{
g_signal_connect (G_OBJECT (myDesklet->container.pWidget),
"enter-notify-event",
G_CALLBACK (_cd_mixer_on_enter),
NULL);
g_signal_connect (G_OBJECT (myDesklet->container.pWidget),
"leave-notify-event",
G_CALLBACK (_cd_mixer_on_leave),
NULL);
}
else if (! myConfig.bHideScaleOnLeave && iOnEnterCallbackID > 0)
{
g_signal_handler_disconnect (G_OBJECT (myDesklet->container.pWidget), iOnEnterCallbackID);
gulong iOnLeaveCallbackID = g_signal_handler_find (myDesklet->container.pWidget,
G_SIGNAL_MATCH_FUNC,
0,
0,
NULL,
_cd_mixer_on_leave,
NULL);
g_signal_handler_disconnect (G_OBJECT (myDesklet->container.pWidget), iOnLeaveCallbackID);
}
}
else
{
if (CD_APPLET_MY_CONTAINER_TYPE_CHANGED && myData.pScale)
{
gtk_widget_destroy (myData.pScale);
myData.pScale = NULL;
}
if (myIcon->cName == NULL)
{
CD_APPLET_SET_NAME_FOR_MY_ICON (myData.mixer_card_name);
}
}
}
else
{
///\_______________ On redessine notre icone.
if (myDesklet && myDesklet->container.iHeight <= 64)
gtk_widget_hide (myData.pScale);
/**if (myConfig.iVolumeEffect != VOLUME_EFFECT_NONE)
CD_APPLET_RELOAD_MY_DATA_RENDERER (NULL);
cd_update_icon ();*/
}
CD_APPLET_RELOAD_END
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-backend-sound-menu-old.c 000775 001750 001750 00000014243 12223247501 026752 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* based on indicator-messages.c written by :
* Ted Gould
* Cody Russell
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include
#if (SOUND_SERVICE_VERSION < 1)
#include "dbus-shared-names-old.h"
#else
#include "dbus-shared-names.h"
#endif
#include "applet-struct.h"
#include "common-defs.h"
#include "volume-widget.h"
#include "mute-widget.h"
#include "applet-menu.h"
#include "applet-backend-alsamixer.h" // cd_mixer_init_alsa (fallback alsa backend)
#include "applet-generic.h"
#include "applet-draw.h"
#include "applet-backend-sound-menu-old.h"
/*
// we can use icons designed for Unity, or more common icons that we are likely to find in icons themes.
static const gchar *_get_icon_from_state_unity (gint iState)
{
switch (iState)
{
case MUTED: return "audio-volume-muted-panel";
case ZERO_LEVEL: return "audio-volume-low-zero-panel";
case LOW_LEVEL: return "audio-volume-low-panel";
case MEDIUM_LEVEL: return "audio-volume-medium-panel";
case HIGH_LEVEL: return "audio-volume-high-panel";
case BLOCKED: return "audio-volume-muted-blocking-panel";
default: return "audio-output-none-panel";
}
}
static const gchar *_get_icon_from_state (gint iState)
{
switch (iState)
{
case ZERO_LEVEL: return "audio-volume-off";
case LOW_LEVEL: return "audio-volume-low";
case MEDIUM_LEVEL: return "audio-volume-medium";
case HIGH_LEVEL: return "audio-volume-high";
default: return "audio-volume-muted";
}
}*/
///////////
// PROXY //
///////////
static void
on_sound_state_updated (DBusGProxy * proxy, gint iNewState, GldiModuleInstance *myApplet)
{
cd_debug ("%s (iNewState : %d)", __func__, iNewState);
CD_APPLET_ENTER;
if (iNewState != myData.iCurrentState)
{
myData.iCurrentState = iNewState;
gboolean bIsMute = (iNewState == MUTED
|| iNewState == UNAVAILABLE
|| iNewState == BLOCKED);
if (myData.bIsMute != bIsMute)
{
myData.bIsMute = bIsMute;
cd_update_icon ();
}
}
CD_APPLET_LEAVE();
}
static int _get_volume (void)
{
if (myData.volume_widget)
return (int)volume_widget_get_current_volume (myData.volume_widget);
else
return 0;
}
static void _set_volume (int iVolume)
{
if (myData.volume_widget)
volume_widget_update (VOLUME_WIDGET(myData.volume_widget), (gdouble)iVolume, "scroll updates");
}
static void _toggle_mute (void)
{
if (myData.mute_widget)
mute_widget_toggle (MUTE_WIDGET (myData.mute_widget));
}
static void _show_menu (void)
{
cd_indicator_show_menu (myData.pIndicator);
}
static void _stop (void)
{
cd_indicator_destroy (myData.pIndicator);
g_list_free (myData.transport_widgets_list);
}
static void cd_sound_on_connect (GldiModuleInstance *myApplet)
{
cd_debug ("%s ()", __func__);
// the sound service is up and running, stop the alsa mixer if ever we initialized it before.
cd_stop ();
// and set the interface
myData.ctl.get_volume = _get_volume;
myData.ctl.set_volume = _set_volume;
myData.ctl.toggle_mute = _toggle_mute;
myData.ctl.show_hide = _show_menu;
myData.ctl.stop = _stop;
myData.ctl.reload = cd_update_icon;
// connect to the service signals.
dbus_g_proxy_add_signal(myData.pIndicator->pServiceProxy, INDICATOR_SOUND_SIGNAL_STATE_UPDATE, G_TYPE_INT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal(myData.pIndicator->pServiceProxy,
INDICATOR_SOUND_SIGNAL_STATE_UPDATE,
G_CALLBACK(on_sound_state_updated),
myApplet,
NULL);
}
static void cd_sound_on_disconnect (GldiModuleInstance *myApplet)
{
CD_APPLET_ENTER;
cd_debug ("%s", __func__);
if (myData.ctl.get_volume == _get_volume) // the backend was set, unset it
{
memset (&myData.ctl, 0, sizeof (CDSoundCtl));
cd_debug ("clean");
myData.volume_widget = NULL;
myData.transport_widgets_list = NULL;
myData.voip_widget = NULL;
myData.mute_widget = NULL;
}
// no (more) sound service, now rely on alsa.
cd_mixer_init_alsa ();
CD_APPLET_LEAVE();
}
static void _on_got_sound_state (DBusGProxy *proxy, DBusGProxyCall *call_id, GldiModuleInstance *myApplet)
{
CD_APPLET_ENTER;
int iCurrentState = 0;
gboolean bSuccess = dbus_g_proxy_end_call (proxy,
call_id,
NULL,
G_TYPE_INT,
&iCurrentState,
G_TYPE_INVALID);
cd_debug ("got sound state: %d", iCurrentState);
// update the icon.
if (bSuccess)
{
myData.iCurrentState = iCurrentState;
myData.bIsMute = (iCurrentState == MUTED
|| iCurrentState == UNAVAILABLE
|| iCurrentState == BLOCKED);
myData.iCurrentVolume = _get_volume ();
cd_update_icon ();
}
CD_APPLET_LEAVE();
}
static void cd_sound_get_initial_values (GldiModuleInstance *myApplet)
{
// query the service to display initial values.
dbus_g_proxy_begin_call (myData.pIndicator->pServiceProxy, "GetSoundState",
(DBusGProxyCallNotify)_on_got_sound_state,
myApplet,
(GDestroyNotify) NULL,
G_TYPE_INVALID);
}
void update_accessible_desc (double new_value)
{
cd_debug ("%s (%p)", __func__, myData.volume_widget);
if (!myData.volume_widget)
return;
myData.iCurrentVolume = (new_value < 0 ? _get_volume() : new_value);
cd_update_icon ();
}
void cd_mixer_connect_to_sound_service (void)
{
myData.pIndicator = cd_indicator_new (myApplet,
INDICATOR_SOUND_DBUS_NAME,
INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
INDICATOR_SOUND_DBUS_INTERFACE,
INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH,
0);
myData.pIndicator->on_connect = cd_sound_on_connect;
myData.pIndicator->on_disconnect = cd_sound_on_disconnect;
myData.pIndicator->get_initial_values = cd_sound_get_initial_values;
myData.pIndicator->add_menu_handler = cd_sound_add_menu_handler;
}
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-draw.c 000775 001750 001750 00000004630 12225027055 023455 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include
#include
#include
#include "applet-struct.h"
#include "applet-generic.h"
#include "applet-draw.h"
void cd_update_icon (void)
{
gboolean bNeedRedraw = FALSE;
// update the volume info
switch (myConfig.iVolumeDisplay)
{
case VOLUME_ON_LABEL :
CD_APPLET_SET_NAME_FOR_MY_ICON_PRINTF ("%s: %d%%", myData.mixer_card_name?myData.mixer_card_name:D_("Volume"), myData.iCurrentVolume);
break;
case VOLUME_ON_ICON :
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON_PRINTF ("%d%%", myData.iCurrentVolume);
bNeedRedraw = TRUE;
break;
default :
break;
}
// update the icon representation
switch (myConfig.iVolumeEffect) // set the icon if needed
{
case VOLUME_EFFECT_NONE :
case VOLUME_EFFECT_BAR :
if (myData.bMuteImage < 0 || (myData.bIsMute != myData.bMuteImage))
{
if (myData.bIsMute)
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cMuteIcon, "mute.svg");
else
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cDefaultIcon, "default.svg");
myData.bMuteImage = myData.bIsMute;
bNeedRedraw = FALSE;
}
break;
default :
break;
}
switch (myConfig.iVolumeEffect) // render the value
{
case VOLUME_EFFECT_BAR :
case VOLUME_EFFECT_GAUGE :
{
double fPercent;
if (myData.bIsMute)
fPercent = CAIRO_DATA_RENDERER_UNDEF_VALUE;
else
fPercent = (double) myData.iCurrentVolume / 100.;
CD_APPLET_RENDER_NEW_DATA_ON_MY_ICON (&fPercent);
bNeedRedraw = FALSE;
}
break;
default :
break;
}
if (bNeedRedraw)
CD_APPLET_REDRAW_MY_ICON;
if (myData.pScale)
{
cd_mixer_set_volume_with_no_callback (myData.pScale, myData.iCurrentVolume);
}
}
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-draw.h 000775 001750 001750 00000001571 12223247501 023461 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_DRAW__
#define __APPLET_DRAW__
#include
void cd_update_icon (void);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-backend-sound-menu-old.h 000775 001750 001750 00000001710 12223247501 026752 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_SOUND_OLD__
#define __APPLET_SOUND_OLD__
#include
void update_accessible_desc (double new_value);
void cd_mixer_connect_to_sound_service (void);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-notifications.c 000775 001750 001750 00000007242 12223247501 025371 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include
#include "applet-struct.h"
#include "applet-generic.h"
#include "applet-notifications.h"
static const gchar *s_cMixerCmd = NULL;
static gboolean bMixerChecked = FALSE;
CD_APPLET_ON_CLICK_BEGIN
cd_show_hide ();
CD_APPLET_ON_CLICK_END
static void _check_mixer_cmd (void)
{
// check for Gnome2 before Gnome3, since during the transition, both were present, and "gnome-control-center sound" didn't work (and it was anyway just a shortcut to gnome-volume-control).
gchar *cResult = cairo_dock_launch_command_sync ("which gnome-volume-control"); // Gnome2
if (cResult != NULL && *cResult == '/')
s_cMixerCmd = "gnome-volume-control -p applications";
else
{
g_free (cResult);
cResult = cairo_dock_launch_command_sync ("which gnome-control-center"); // Gnome3
if (cResult != NULL && *cResult == '/') /// TODO: other DE...
s_cMixerCmd = "gnome-control-center sound";
} /// TODO: handle other DE ...
g_free (cResult);
}
static void _mixer_show_advanced_mixer (GtkMenuItem *menu_item, gpointer data)
{
CD_APPLET_ENTER;
GError *erreur = NULL;
if (myConfig.cShowAdvancedMixerCommand != NULL)
{
g_spawn_command_line_async (myConfig.cShowAdvancedMixerCommand, &erreur);
}
else if (s_cMixerCmd != NULL)
{
g_spawn_command_line_async (s_cMixerCmd, &erreur);
}
if (erreur != NULL)
{
cd_warning ("Attention : when trying to execute '%s' : %s", myConfig.cShowAdvancedMixerCommand, erreur->message);
g_error_free (erreur);
}
CD_APPLET_LEAVE();
}
CD_APPLET_ON_BUILD_MENU_BEGIN
gchar *cLabel;
if (!myConfig.cShowAdvancedMixerCommand && !bMixerChecked)
{
bMixerChecked = TRUE;
_check_mixer_cmd ();
}
if (myConfig.cShowAdvancedMixerCommand || s_cMixerCmd)
{
cLabel = g_strdup_printf ("%s (%s)", D_("Adjust channels"), D_("double-click"));
CD_APPLET_ADD_IN_MENU_WITH_STOCK (cLabel, GTK_STOCK_PREFERENCES, _mixer_show_advanced_mixer, CD_APPLET_MY_MENU);
g_free (cLabel);
}
cLabel = g_strdup_printf ("%s (%s)", (myData.bIsMute ? D_("Unmute") : D_("Mute")), D_("middle-click"));
CD_APPLET_ADD_IN_MENU_WITH_STOCK (cLabel, MY_APPLET_SHARE_DATA_DIR"/emblem-mute.svg", cd_toggle_mute, CD_APPLET_MY_MENU);
g_free (cLabel);
CD_APPLET_ON_BUILD_MENU_END
CD_APPLET_ON_MIDDLE_CLICK_BEGIN
cd_toggle_mute ();
CD_APPLET_ON_MIDDLE_CLICK_END
CD_APPLET_ON_DOUBLE_CLICK_BEGIN
if (!myConfig.cShowAdvancedMixerCommand && !bMixerChecked)
{
bMixerChecked = TRUE;
_check_mixer_cmd (); // looking for s_cMixerCmd
}
_mixer_show_advanced_mixer (NULL, NULL);
CD_APPLET_ON_DOUBLE_CLICK_END
CD_APPLET_ON_SCROLL_BEGIN
double delta;
if (CD_APPLET_SCROLL_UP)
delta = myConfig.iScrollVariation;
else
delta = - myConfig.iScrollVariation;
int iVolume = cd_get_volume ();
iVolume = MAX (0, MIN (iVolume + delta, 100));
cd_set_volume (iVolume);
CD_APPLET_ON_SCROLL_END
void mixer_on_keybinding_pull (const char *keystring, gpointer user_data)
{
CD_APPLET_ENTER;
cd_show_hide ();
CD_APPLET_LEAVE();
}
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-backend-sound-menu.c 000775 001750 001750 00000006026 12223247501 026176 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include "applet-struct.h"
#include "applet-generic.h"
#include "applet-backend-alsamixer.h" // cd_mixer_init_alsa
#include "applet-backend-sound-menu.h"
static void _show_menu (void);
static void (*_stop_parent) (void) = NULL;
static void (*_show_menu_parent) (void) = NULL;
static void _entry_added (IndicatorObject *pIndicator, IndicatorObjectEntry *pEntry, GldiModuleInstance *myApplet)
{
cd_debug ("Entry Added: %p", pEntry);
g_return_if_fail (myData.pEntry == NULL && pEntry != NULL); // should not happen... only one entry
myData.pEntry = pEntry;
}
static void _entry_removed (IndicatorObject *pIndicator, IndicatorObjectEntry *pEntry, GldiModuleInstance *myApplet)
{
// should not happen... except at the end.
cd_debug ("Entry Removed");
// no (more) sound service... now rely on alsa to display the menu/dialog.
if (myData.pEntry == pEntry) // the same entry as before, we can remove the previous one
{
myData.pEntry = NULL;
}
}
static void _show_menu (void)
{
GtkMenu *pMenu = NULL;
if (myData.pEntry)
pMenu = cd_indicator3_get_menu (myData.pEntry);
if (pMenu)
{
GList *entries = gtk_container_get_children (GTK_CONTAINER (pMenu));
if (entries) // if the menu is ok
{
CD_APPLET_POPUP_MENU_ON_MY_ICON (GTK_WIDGET (pMenu));
g_list_free (entries);
}
else // else, the daemon was probaby not launched.
pMenu = NULL;
}
if (!pMenu) // if no menu, it's maybe because the daemon has not started, or has stopped (the entry is not removed).
{
if (_show_menu_parent) _show_menu_parent ();
}
}
static void _stop (void)
{
_entry_removed (myData.pIndicator, myData.pEntry, myApplet);
if (_stop_parent)
_stop_parent ();
}
void cd_mixer_connect_to_sound_service (void)
{
// load the indicator (we only want its menu, label and image are set by us).
myData.pIndicator = cd_indicator3_load (myConfig.cIndicatorName,
_entry_added,
_entry_removed,
NULL,
NULL,
myApplet);
// init the backend. we'll use the alsa backend (to get the exact volume and volume changes), and we'll override only the functions we need.
cd_mixer_init_alsa (); // alsa backend
if (myData.pIndicator)
{
_stop_parent = myData.ctl.stop;
myData.ctl.stop = _stop;
_show_menu_parent = myData.ctl.show_hide;
myData.ctl.show_hide = _show_menu; // but with our menu
}
}
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-backend-alsamixer.c 000775 001750 001750 00000031741 12223247501 026073 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include
#include
#include
#include
#include "applet-struct.h"
#include "applet-draw.h"
#include "applet-generic.h"
#include "applet-backend-alsamixer.h"
static int mixer_level = 0;
static struct snd_mixer_selem_regopt mixer_options;
static gboolean mixer_is_mute (void);
static int mixer_get_mean_volume (void);
static gchar *_mixer_get_card_id_from_name (const gchar *cName)
{
if (cName == NULL)
return g_strdup ("default");
int iCardID = -1;
char *cName2;
while (snd_card_next (&iCardID) == 0 && iCardID != -1)
{
snd_card_get_name (iCardID, &cName2);
cd_debug ("+ card %d: %s", iCardID, cName2);
if (! cName2)
continue;
if (strcmp (cName2, cName) == 0)
{
free (cName2);
return g_strdup_printf ("hw:%d", iCardID);
}
free (cName2);
}
return g_strdup ("default");
}
static void mixer_init (const gchar *cCardName) // this function is taken from AlsaMixer.
{
snd_ctl_card_info_t *hw_info = NULL; // ne pas liberer.
snd_ctl_t *ctl_handle = NULL;
int err;
snd_ctl_card_info_alloca (&hw_info);
// get the card ID
gchar *cCardID = _mixer_get_card_id_from_name (cCardName);
// get the card info
if ((err = snd_ctl_open (&ctl_handle, cCardID, 0)) < 0)
{
myData.cErrorMessage = g_strdup_printf (D_("I couldn't open card '%s'"), cCardID);
g_free (cCardID);
return ;
}
if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0)
{
myData.cErrorMessage = g_strdup_printf (D_("Card '%s' opened but I couldn't get any info"), cCardID);
g_free (cCardID);
return ;
}
snd_ctl_close (ctl_handle);
// open mixer device
if ((err = snd_mixer_open (&myData.mixer_handle, 0)) < 0)
{
myData.cErrorMessage = g_strdup (D_("I couldn't open the mixer"));
g_free (cCardID);
return ;
}
if (mixer_level == 0 && (err = snd_mixer_attach (myData.mixer_handle, cCardID)) < 0)
{
snd_mixer_free (myData.mixer_handle);
myData.mixer_handle = NULL;
g_free (cCardID);
myData.cErrorMessage = g_strdup (D_("I couldn't attach the mixer to the card"));
return ;
}
if ((err = snd_mixer_selem_register (myData.mixer_handle, mixer_level > 0 ? &mixer_options : NULL, NULL)) < 0)
{
snd_mixer_free (myData.mixer_handle);
myData.mixer_handle = NULL;
g_free (cCardID);
myData.cErrorMessage = g_strdup (D_("I couldn't register options"));
return ;
}
if ((err = snd_mixer_load (myData.mixer_handle)) < 0)
{
snd_mixer_free (myData.mixer_handle);
myData.mixer_handle = NULL;
g_free (cCardID);
myData.cErrorMessage = g_strdup (D_("I couldn't load the mixer"));
return ;
}
myData.mixer_card_name = g_strdup (snd_ctl_card_info_get_name(hw_info));
myData.mixer_device_name = g_strdup (snd_ctl_card_info_get_mixername(hw_info));
cd_debug ("myData.mixer_card_name : %s ; myData.mixer_device_name : %s", myData.mixer_card_name, myData.mixer_device_name);
g_free (cCardID);
}
void mixer_stop (void)
{
if (myData.mixer_handle != NULL)
{
gchar *cCardID = _mixer_get_card_id_from_name (myConfig.card_id);
snd_mixer_detach (myData.mixer_handle, cCardID);
g_free (cCardID);
snd_mixer_close (myData.mixer_handle);
myData.mixer_handle = NULL;
myData.pControledElement = NULL;
myData.pControledElement2 = NULL;
g_free (myData.cErrorMessage);
myData.cErrorMessage = NULL;
g_free (myData.mixer_card_name);
myData.mixer_card_name = NULL;
g_free (myData.mixer_device_name);
myData.mixer_device_name= NULL;
}
}
GList *mixer_get_cards_list (void)
{
int iCardID;
char *cName;
GList *pList = NULL;
pList = g_list_append (pList, (gpointer) g_strdup(""));
for (iCardID = 0; snd_card_get_name (iCardID, &cName) >= 0; iCardID ++)
{
pList = g_list_append (pList, (gpointer) cName);
}
return pList;
}
GList *mixer_get_elements_list (void)
{
snd_mixer_elem_t *elem;
if (myData.mixer_handle == NULL)
return NULL;
cd_message ("");
GList *pList = NULL;
for (elem = snd_mixer_first_elem(myData.mixer_handle); elem; elem = snd_mixer_elem_next(elem))
{
if (snd_mixer_selem_is_active (elem) && snd_mixer_selem_has_playback_volume (elem))
pList = g_list_prepend (pList, (gpointer)snd_mixer_selem_get_name (elem)); // la liste ne contiendra que des const, on ne supprimera pas ses elements lors du g_list_free.
}
return pList;
}
static snd_mixer_elem_t *_mixer_get_element_by_name (const gchar *cName)
{
if (myData.mixer_handle == NULL)
return NULL;
if (cName != NULL)
{
snd_mixer_elem_t *elem;
for (elem = snd_mixer_first_elem(myData.mixer_handle); elem; elem = snd_mixer_elem_next(elem))
{
if (strcmp (cName, snd_mixer_selem_get_name (elem)) == 0)
return elem;
}
}
cd_debug ("no channel matches '%s', we take the first available channel by default", cName);
return snd_mixer_first_elem(myData.mixer_handle);
/**myData.cErrorMessage = g_strdup_printf (D_("I couldn't find any audio channel named '%s'\nYou should try to open the configuration panel of the applet,\n and select the proper audio channel you want to control."), cName);
return NULL;*/
}
static int mixer_element_update_with_event (snd_mixer_elem_t *elem, unsigned int mask)
{
CD_APPLET_ENTER;
cd_debug ("%s (%d)", __func__, mask);
if (mask != SND_CTL_EVENT_MASK_REMOVE && (mask & SND_CTL_EVENT_MASK_VALUE)) // filter calls that can occur when we really don't want, like when closing the applet.
{
myData.iCurrentVolume = mixer_get_mean_volume ();
myData.bIsMute = mixer_is_mute ();
cd_debug (" iCurrentVolume <- %d bIsMute <- %d", myData.iCurrentVolume, myData.bIsMute);
cd_update_icon ();
}
CD_APPLET_LEAVE(0);
}
static void mixer_get_controlled_element (void)
{
myData.pControledElement = _mixer_get_element_by_name (myConfig.cMixerElementName);
if (myData.pControledElement != NULL)
{
myData.bHasMuteSwitch = snd_mixer_selem_has_playback_switch (myData.pControledElement);
snd_mixer_selem_get_playback_volume_range (myData.pControledElement, &myData.iVolumeMin, &myData.iVolumeMax);
cd_debug ("volume range : %d - %d", myData.iVolumeMin, myData.iVolumeMax);
snd_mixer_elem_set_callback (myData.pControledElement, mixer_element_update_with_event);
}
if (myConfig.cMixerElementName2 != NULL)
{
myData.pControledElement2 = _mixer_get_element_by_name (myConfig.cMixerElementName2);
}
}
static int mixer_get_mean_volume (void)
{
g_return_val_if_fail (myData.pControledElement != NULL, 0);
long iVolumeLeft=0, iVolumeRight=0;
gboolean bHasLeft = snd_mixer_selem_has_playback_channel (myData.pControledElement, SND_MIXER_SCHN_FRONT_LEFT);
gboolean bHasRight = snd_mixer_selem_has_playback_channel (myData.pControledElement, SND_MIXER_SCHN_FRONT_RIGHT);
g_return_val_if_fail (bHasLeft || bHasRight, 0);
if (bHasLeft)
snd_mixer_selem_get_playback_volume (myData.pControledElement, SND_MIXER_SCHN_FRONT_LEFT, &iVolumeLeft);
if (bHasRight)
snd_mixer_selem_get_playback_volume (myData.pControledElement, SND_MIXER_SCHN_FRONT_RIGHT, &iVolumeRight);
cd_debug ("volume : %d;%d", iVolumeLeft, iVolumeRight);
int iMeanVolume = (iVolumeLeft + iVolumeRight) / (bHasLeft + bHasRight);
cd_debug ("myData.iVolumeMin : %d ; myData.iVolumeMax : %d ; iMeanVolume : %d", myData.iVolumeMin, myData.iVolumeMax, iMeanVolume);
return (100. * (iMeanVolume - myData.iVolumeMin) / (myData.iVolumeMax - myData.iVolumeMin));
}
static void _set_mute (gboolean bMute)
{
snd_mixer_selem_set_playback_switch_all (myData.pControledElement, !bMute);
if (myData.pControledElement2 != NULL)
snd_mixer_selem_set_playback_switch_all (myData.pControledElement2, !bMute);
myData.bIsMute = bMute;
}
static void mixer_set_volume (int iNewVolume)
{
g_return_if_fail (myData.pControledElement != NULL);
cd_debug ("%s (%d)", __func__, iNewVolume);
int iVolume = ceil (myData.iVolumeMin + (myData.iVolumeMax - myData.iVolumeMin) * iNewVolume / 100.);
snd_mixer_selem_set_playback_volume_all (myData.pControledElement, iVolume);
if (myData.pControledElement2 != NULL)
snd_mixer_selem_set_playback_volume_all (myData.pControledElement2, iVolume);
myData.iCurrentVolume = iNewVolume;
if (myData.bIsMute)
{
_set_mute (FALSE);
}
cd_update_icon (); // on ne recoit pas d'evenements pour nos actions.
}
static gboolean mixer_is_mute (void)
{
cd_debug ("");
g_return_val_if_fail (myData.pControledElement != NULL, FALSE);
if (snd_mixer_selem_has_playback_switch (myData.pControledElement))
{
int iSwitchLeft, iSwitchRight;
snd_mixer_selem_get_playback_switch (myData.pControledElement, SND_MIXER_SCHN_FRONT_LEFT, &iSwitchLeft);
snd_mixer_selem_get_playback_switch (myData.pControledElement, SND_MIXER_SCHN_FRONT_RIGHT, &iSwitchRight);
cd_debug ("%d;%d", iSwitchLeft, iSwitchRight);
return (iSwitchLeft == 0 && iSwitchRight == 0);
}
else
return FALSE;
}
static void mixer_switch_mute (void)
{
g_return_if_fail (myData.pControledElement != NULL);
gboolean bIsMute = mixer_is_mute ();
_set_mute (! bIsMute);
cd_update_icon (); // on ne recoit pas d'evenements pour nos actions.
}
static void _on_dialog_destroyed (GldiModuleInstance *myApplet)
{
myData.pDialog = NULL;
}
static void mixer_show_hide_dialog (void)
{
if (myDesklet)
return ;
if (myData.pDialog == NULL)
{
const gchar *cMessage;
GtkWidget *pScale = NULL;
if (myData.cErrorMessage != NULL)
cMessage = myData.cErrorMessage;
else
{
cMessage = D_("Set up volume:");
pScale = mixer_build_widget (TRUE);
}
CairoDialogAttr attr;
memset (&attr, 0, sizeof (CairoDialogAttr));
attr.cText = cMessage;
attr.cImageFilePath = MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE;
attr.pInteractiveWidget = pScale;
attr.pUserData = myApplet;
attr.pFreeDataFunc = (GFreeFunc)_on_dialog_destroyed;
attr.pIcon = myIcon;
attr.pContainer = myContainer;
myData.pDialog = gldi_dialog_new (&attr);
}
else
{
gldi_object_unref (GLDI_OBJECT(myData.pDialog));
myData.pDialog = NULL;
}
}
static void cd_mixer_stop_alsa (void)
{
if (myData.mixer_handle != NULL)
{
mixer_stop ();
g_free (myData.cErrorMessage);
myData.cErrorMessage = NULL;
g_free (myData.mixer_card_name);
myData.mixer_card_name = NULL;
g_free (myData.mixer_device_name);
myData.mixer_device_name= NULL;
if (myData.iSidCheckVolume != 0)
{
g_source_remove (myData.iSidCheckVolume);
myData.iSidCheckVolume = 0;
}
}
}
static gboolean mixer_check_events (gpointer data)
{
CD_APPLET_ENTER;
CD_APPLET_LEAVE_IF_FAIL (myData.mixer_handle, FALSE);
snd_mixer_handle_events (myData.mixer_handle); // ne renvoie pas d'evenements pour nos actions !
CD_APPLET_LEAVE(TRUE);
}
static void cd_mixer_reload_alsa (void)
{
myData.ctl.stop ();
mixer_init (myConfig.card_id);
mixer_get_controlled_element ();
if (myData.pControledElement == NULL)
{
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cBrokenIcon, "broken.svg");
}
else
{
mixer_element_update_with_event (myData.pControledElement, 1); // 1 => get the current state (card may have changed).
myData.iSidCheckVolume = g_timeout_add (1000, (GSourceFunc) mixer_check_events, (gpointer) NULL);
}
}
void cd_mixer_init_alsa (void)
{
// connect to the sound card
mixer_init (myConfig.card_id);
// get the mixer element
mixer_get_controlled_element ();
// update the icon
if (myData.pControledElement == NULL) // no luck
{
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cBrokenIcon, "broken.svg");
}
else // mixer aquired
{
// set the interface
myData.ctl.get_volume = mixer_get_mean_volume;
myData.ctl.set_volume = mixer_set_volume;
myData.ctl.toggle_mute = mixer_switch_mute;
myData.ctl.show_hide = mixer_show_hide_dialog;
myData.ctl.stop = cd_mixer_stop_alsa;
myData.ctl.reload = cd_mixer_reload_alsa;
// build the scale now if we're in a desklet
if (myDesklet)
{
GtkWidget *box = _gtk_hbox_new (0);
myData.pScale = mixer_build_widget (FALSE);
gtk_box_pack_end (GTK_BOX (box), myData.pScale, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (myDesklet->container.pWidget), box);
gtk_widget_show_all (box);
if (myConfig.bHideScaleOnLeave && ! myDesklet->container.bInside)
gtk_widget_hide (myData.pScale);
}
else if (myIcon->cName == NULL) // in dock, set the label
{
CD_APPLET_SET_NAME_FOR_MY_ICON (myData.mixer_card_name);
}
// trigger the callback to update the icon
mixer_element_update_with_event (myData.pControledElement, 1); // 1 => get the current state.
myData.iSidCheckVolume = g_timeout_add (1000, (GSourceFunc) mixer_check_events, (gpointer) NULL);
}
}
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-config.c 000775 001750 001750 00000013627 12223247501 023771 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#include "applet-struct.h"
#include "applet-backend-alsamixer.h" // mixer_get_elements_list
#include "applet-notifications.h"
#include "applet-config.h"
CD_APPLET_GET_CONFIG_BEGIN
//\_________________ On recupere toutes les valeurs de notre fichier de conf.
myConfig.card_id = CD_CONFIG_GET_STRING ("Configuration", "card id");
gchar *cMixerElementName = CD_CONFIG_GET_STRING ("Configuration", "mixer element");
gchar *cMixerElementName2 = CD_CONFIG_GET_STRING ("Configuration", "mixer element 2");
if (cMixerElementName != NULL && cMixerElementName2 != NULL && strcmp (cMixerElementName, cMixerElementName2) == 0)
{
myConfig.cMixerElementName = g_strconcat (cMixerElementName, ",0", NULL);
myConfig.cMixerElementName2 = g_strconcat (cMixerElementName, ",1", NULL);
g_free (cMixerElementName);
}
else
{
myConfig.cMixerElementName = cMixerElementName;
myConfig.cMixerElementName2 = cMixerElementName2;
}
myConfig.cShowAdvancedMixerCommand = CD_CONFIG_GET_STRING ("Configuration", "show mixer");
myConfig.cShortcut = CD_CONFIG_GET_STRING ("Configuration", "shortkey");
myConfig.iScrollVariation = CD_CONFIG_GET_INTEGER ("Configuration", "scroll variation");
myConfig.bHideScaleOnLeave = CD_CONFIG_GET_BOOLEAN ("Configuration", "hide on leave");
myConfig.iVolumeDisplay = CD_CONFIG_GET_INTEGER ("Configuration", "display volume");
myConfig.iVolumeEffect = CD_CONFIG_GET_INTEGER_WITH_DEFAULT ("Configuration", "display icon", -1);
if (myConfig.iVolumeEffect >= VOLUME_NB_EFFECTS) // new option (iVolumeEffect is an unsigned int)
{
myConfig.iVolumeEffect = CD_CONFIG_GET_INTEGER ("Configuration", "effect");
if (myConfig.iVolumeEffect == 1 || myConfig.iVolumeEffect == 2) // old "zoom" and "transparency" effects
myConfig.iVolumeEffect = VOLUME_EFFECT_BAR;
else if (myConfig.iVolumeEffect >= 3) // other options are offseted by 2
myConfig.iVolumeEffect -= 2;
g_key_file_set_integer (CD_APPLET_MY_KEY_FILE, "Configuration", "display icon", myConfig.iVolumeEffect);
}
if (myConfig.iVolumeEffect == VOLUME_EFFECT_GAUGE)
{
myConfig.cGThemePath = CD_CONFIG_GET_GAUGE_THEME ("Configuration", "theme");
myConfig.iRotateTheme = CD_CONFIG_GET_INTEGER ("Configuration", "rotate theme");
}
myConfig.cDefaultIcon = CD_CONFIG_GET_STRING ("Configuration", "default icon");
myConfig.cBrokenIcon = CD_CONFIG_GET_STRING ("Configuration", "broken icon");
myConfig.cMuteIcon = CD_CONFIG_GET_STRING ("Configuration", "mute icon");
#ifdef INDICATOR_SOUNDMENU_WITH_IND3
myConfig.cIndicatorName = CD_CONFIG_GET_STRING ("Configuration", "indicator name"); // we take it from the config just in case the name changes, it's not a visible option.
if (myConfig.cIndicatorName == NULL)
#ifdef IS_INDICATOR_NG
myConfig.cIndicatorName = g_strdup ("com.canonical.indicator.sound");
#else
myConfig.cIndicatorName = g_strdup ("libsoundmenu.so");
#endif
#endif
CD_APPLET_GET_CONFIG_END
CD_APPLET_RESET_CONFIG_BEGIN
g_free (myConfig.card_id);
g_free (myConfig.cMixerElementName);
g_free (myConfig.cMixerElementName2);
g_free (myConfig.cShowAdvancedMixerCommand);
g_free (myConfig.cShortcut);
g_free (myConfig.cDefaultIcon);
g_free (myConfig.cBrokenIcon);
g_free (myConfig.cMuteIcon);
g_free (myConfig.cGThemePath);
#ifdef INDICATOR_SOUNDMENU_WITH_IND3
g_free (myConfig.cIndicatorName);
#endif
CD_APPLET_RESET_CONFIG_END
CD_APPLET_RESET_DATA_BEGIN
if (myData.pScale != NULL)
{
gtk_widget_destroy (myData.pScale);
myData.pScale = NULL;
}
gldi_object_unref (GLDI_OBJECT(myData.pDialog));
CD_APPLET_RESET_DATA_END
void cd_mixer_load_custom_widget (GldiModuleInstance *myApplet, GKeyFile* pKeyFile, GSList *pWidgetList) // myApplet can be NULL
{
//\____________ build the list of available sound cards.
GList *pList = mixer_get_cards_list ();
//\____________ get the combo
CairoDockGroupKeyWidget *pGroupKeyWidget = cairo_dock_gui_find_group_key_widget_in_list (pWidgetList, "Configuration", "card id");
GtkWidget *pCombo = cairo_dock_gui_get_first_widget (pGroupKeyWidget);
g_return_if_fail (pCombo != NULL);
cairo_dock_fill_combo_with_list (pCombo, pList, myApplet?myConfig.card_id:NULL);
g_list_foreach (pList, (GFunc)free, NULL);
g_list_free (pList);
//\____________ On construit la liste des canaux a controler.
if (myApplet)
{
pList = mixer_get_elements_list ();
//\____________ On recupere la combo.
pGroupKeyWidget = cairo_dock_gui_find_group_key_widget_in_list (pWidgetList, "Configuration", "mixer element");
pCombo = cairo_dock_gui_get_first_widget (pGroupKeyWidget);
g_return_if_fail (pCombo != NULL);
cairo_dock_fill_combo_with_list (pCombo, pList, myConfig.cMixerElementName);
//\____________ Idem pour la 2eme, avec une entree vide au debut.
pGroupKeyWidget = cairo_dock_gui_find_group_key_widget_in_list (pWidgetList, "Configuration", "mixer element 2");
pCombo = cairo_dock_gui_get_first_widget (pGroupKeyWidget);
g_return_if_fail (pCombo != NULL);
pList = g_list_prepend (pList, (gpointer)""); // on peut caster ici car tous les elements sont des const pour nous.
cairo_dock_fill_combo_with_list (pCombo, pList, myConfig.cMixerElementName2);
g_list_free (pList); // les elements appartiennent au mixer_handle.
}
}
cairo-dock-plugins-3.3.2/alsaMixer/src/common-defs.h 000664 001750 001750 00000007720 12223247501 023447 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2010 Canonical Ltd.
Authors:
Conor Curran
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 .
*/
#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_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
cairo-dock-plugins-3.3.2/alsaMixer/src/metadata-widget.c 000664 001750 001750 00000105654 12223247501 024301 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2010 Canonical Ltd.
Authors:
Conor Curran
Mirco Müller
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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include "metadata-widget.h"
#include "common-defs.h"
#include
#include
#include "transport-widget.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;
GdkPixbuf* icon_buf;
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 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 void draw_album_art_placeholder_gtk_3 (GtkWidget *metadata, cairo_t* cr);
static void draw_album_border_gtk_3 (GtkWidget *metadata, gboolean selected, cairo_t* cr);
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 void draw_album_art_placeholder (GtkWidget *metadata);
static void draw_album_border (GtkWidget *metadata, gboolean selected);
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;
priv->icon_buf = NULL;
outer_v_box = _gtk_vbox_new (0);
hbox = _gtk_hbox_new(0);
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;
GtkWidget* vbox = _gtk_vbox_new(0);
// 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));
// player label
GtkWidget* player_label;
player_label = gtk_label_new("");
gtk_misc_set_alignment(GTK_MISC(player_label), (gfloat)0, (gfloat)0);
gtk_misc_set_padding (GTK_MISC(player_label), (gfloat)1, (gfloat)4);
gtk_widget_set_size_request (player_label, 150, 24);
priv->player_label = player_label;
gtk_box_pack_start (GTK_BOX(outer_v_box), priv->player_label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX(outer_v_box), priv->meta_data_h_box, 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)
{
MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(METADATA_WIDGET(object));
if (priv->icon_buf != NULL){
g_object_unref (priv->icon_buf);
priv->icon_buf = NULL;
}
g_string_free (priv->image_path, TRUE);
priv->image_path = NULL;
g_string_free (priv->old_image_path, TRUE);
priv->old_image_path = NULL;
G_OBJECT_CLASS (metadata_widget_parent_class)->dispose (object);
}
static void
metadata_widget_finalize (GObject *object)
{
G_OBJECT_CLASS (metadata_widget_parent_class)->finalize (object);
}
#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;
}
static void
draw_album_border_gtk_3(GtkWidget *metadata, gboolean selected, cairo_t *cr)
{
gtk_style_context_add_class (gtk_widget_get_style_context (metadata),
"menu");
int x, y, width, height;
x = 0;
y = 0;
width = gtk_widget_get_allocated_width (metadata);
height = gtk_widget_get_allocated_height (metadata);
gint offset = 1;
width = width + (offset * 2);
height = height + (offset * 2) - 7;
x = x - offset;
y = y - offset + 3;
gint state = selected ? 5 : 0;
CairoColorRGB bg_normal, fg_normal;
GtkStyleContext *style = gtk_widget_get_style_context (metadata);
gtk_style_context_get_background_color (style, 0, (GdkRGBA*)&bg_normal);
gtk_style_context_get_color (style, state, (GdkRGBA*)&fg_normal);
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,
x, y,
width, height);
cairo_set_line_width (cr, 1.0);
cairo_clip ( cr ); /// seems redundant here ...
cairo_move_to (cr, x, y );
cairo_line_to (cr, x + width,
y );
cairo_line_to ( cr, x + width,
y + height );
cairo_line_to ( cr, x, y + height );
cairo_line_to ( cr, x, 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, x, y );
cairo_line_to (cr, x + width,
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, x + width,
y + height );
cairo_line_to ( cr, x, y + 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 );
}
static void
draw_album_art_placeholder_gtk_3(GtkWidget *metadata, cairo_t *cr)
{
int x, y, width;
x = 0;
y = 0;
width = gtk_widget_get_allocated_width (metadata);
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;
GtkStyleContext *style = gtk_widget_get_style_context (metadata);
gtk_style_context_get_color (style, 0, (GdkRGBA*)&fg_normal);
_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, x + width/6, y + 3);
pango_cairo_show_layout(cr, layout);
g_object_unref(layout);
g_object_unref(pcontext);
g_string_free (string, TRUE);
}
/**
* We override the expose method to enable primitive drawing of the
* empty album art image and rounded rectangles on the album art.
*/
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(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){
gtk_image_clear ( GTK_IMAGE(priv->album_art));
gtk_widget_set_size_request(GTK_WIDGET(priv->album_art), 60, 60);
draw_album_border_gtk_3 (metadata, FALSE, cr);
draw_album_art_placeholder_gtk_3(metadata, cr);
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_gtk_3 (metadata, FALSE, cr);
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;
}
gtk_image_clear (GTK_IMAGE(priv->album_art));
gtk_widget_set_size_request(GTK_WIDGET(priv->album_art), 60, 60);
draw_album_border_gtk_3 (metadata, FALSE, cr);
draw_album_art_placeholder_gtk_3(metadata, cr);
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);
int x, y, height, arrow_width, arrow_height;
arrow_width = 5;
arrow_height = 9;
x = 0;
y = 0;
height = gtk_widget_get_allocated_height (widget);
gint offset = (height - gdk_pixbuf_get_height (priv->icon_buf)) / 2;
// Draw player icon
if (priv->icon_buf != NULL){
gdk_cairo_set_source_pixbuf (cr,
priv->icon_buf,
x + arrow_width + 1,
y + offset);
cairo_paint (cr);
}
// Draw triangle but only if the player is running.
if (dbusmenu_menuitem_property_get_bool (priv->twin_item,
DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING)){
y += 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);
CairoColorRGB fg_normal;
GtkStyleContext *style = gtk_widget_get_style_context (widget);
gtk_style_context_get_color (style, gtk_widget_get_state(widget), (GdkRGBA*)&fg_normal);
cairo_set_source_rgb (cr, fg_normal.r,
fg_normal.g,
fg_normal.b);
cairo_fill (cr);
}
return FALSE;
}
// GTK 2 Expose handler
#else
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;
gint state = selected ? 5 : 0;
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 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){
gtk_image_clear ( 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;
}
gtk_image_clear (GTK_IMAGE(priv->album_art));
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);
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;
gint offset = (allocation.height - gdk_pixbuf_get_height (priv->icon_buf)) / 2;
// Draw player icon
if (priv->icon_buf != NULL){
gdk_cairo_set_source_pixbuf (cr,
priv->icon_buf,
x + arrow_width + 1,
y + offset);
cairo_paint (cr);
}
// Draw triangle but only if the player is running.
if (dbusmenu_menuitem_property_get_bool (priv->twin_item,
DBUSMENU_METADATA_MENUITEM_PLAYER_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
metadata_widget_selection_received_event_callback ( GtkWidget *widget,
GtkSelectionData *data,
guint time,
gpointer user_data )
{
#if GTK_CHECK_VERSION(3, 0, 0)
cairo_t *cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));
/// TODO: need to translate at the widget's position ...
draw_album_border_gtk_3(widget, TRUE, cr);
cairo_destroy (cr);
#else
draw_album_border(widget, TRUE);
#endif
}
/* 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 ("%s",
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);
if (priv->icon_buf != NULL){
g_object_unref (priv->icon_buf);
priv->icon_buf = NULL;
}
gint padding = 0;
gtk_widget_style_get(GTK_WIDGET(self), "horizontal-padding", &padding, NULL);
gint width, height;
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
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);
GdkPixbuf* icon_buf;
// 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 ));
}
icon_buf = gtk_icon_theme_load_icon ( gtk_icon_theme_get_default(),
app_panel->str,
(width > height) ? width : height,
GTK_ICON_LOOKUP_GENERIC_FALLBACK,
NULL );
priv->icon_buf = icon_buf;
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;
}
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-menu.h 000775 001750 001750 00000002050 12223247501 023461 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_MENU__
#define __APPLET_MENU__
#include
#if (GTK_MAJOR_VERSION < 3) || defined (DBUSMENU_GTK3_NEW)
#include
#else
#include
#endif
void cd_sound_add_menu_handler (DbusmenuGtkClient * client);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/transport-widget.h 000664 001750 001750 00000004706 12223247501 024556 0 ustar 00mbaerts mbaerts 000000 000000 /*
Copyright 2010 Canonical Ltd.
Authors:
Conor Curran
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 .
*/
#ifndef __TRANSPORT_WIDGET_H__
#define __TRANSPORT_WIDGET_H__
#include
#if (GTK_MAJOR_VERSION < 3) || defined (DBUSMENU_GTK3_NEW)
#include
#else
#include
#endif
#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;
/// make it a GdkRGBA
double a;
} 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
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-backend-sound-menu.h 000775 001750 001750 00000001616 12223247501 026203 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_SOUND__
#define __APPLET_SOUND__
#include
void cd_mixer_connect_to_sound_service (void);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/dbus-shared-names-old.h 000664 001750 001750 00000002524 12223247501 025313 0 ustar 00mbaerts mbaerts 000000 000000 /*
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
Ted Gould
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 .
*/
#ifndef __DBUS_SHARED_NAMES_H__
#define __DBUS_SHARED_NAMES_H__
#define INDICATOR_SOUND_DBUS_NAME "com.canonical.indicators.sound"
#define INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH "/com/canonical/indicators/sound/menu"
#define INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH "/com/canonical/indicators/sound/service"
#define INDICATOR_SOUND_DBUS_INTERFACE "com.canonical.indicators.sound"
#define INDICATOR_SOUND_DBUS_VERSION 0
#define INDICATOR_SOUND_SIGNAL_STATE_UPDATE "SoundStateUpdate"
#endif /* __DBUS_SHARED_NAMES_H__ */
cairo-dock-plugins-3.3.2/alsaMixer/src/applet-config.h 000775 001750 001750 00000001741 12223247501 023770 0 ustar 00mbaerts mbaerts 000000 000000 /**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail : see the 'copyright' file.
*
* 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; either version 3
* of the License, or (at your option) any later version.
*
* 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 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 .
*/
#ifndef __APPLET_CONFIG__
#define __APPLET_CONFIG__
#include
CD_APPLET_CONFIG_H
void cd_mixer_load_custom_widget (GldiModuleInstance *myApplet, GKeyFile* pKeyFile, GSList *pWidgetList);
#endif
cairo-dock-plugins-3.3.2/alsaMixer/src/voip-input-widget.c 000664 001750 001750 00000026520 12223247501 024625 0 ustar 00mbaerts mbaerts 000000 000000
/*
Copyright 2011 Canonical Ltd.
Authors:
Conor Curran
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 .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include "voip-input-widget.h"
#include "common-defs.h"
#include
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)
{
/// we need to unref what we ref'ed
VoipInputWidget *self = VOIP_INPUT_WIDGET (object);
VoipInputWidgetPrivate * priv = VOIP_INPUT_WIDGET_GET_PRIVATE(self);
g_object_unref (priv->twin_item);
g_object_unref (priv->ido_voip_input_slider);
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;
}
cairo-dock-plugins-3.3.2/alsaMixer/src/volume-widget.c 000664 001750 001750 00000027721 12223247501 024026 0 ustar 00mbaerts mbaerts 000000 000000
/*
Copyright 2010 Canonical Ltd.
Authors:
Conor Curran
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 .
*/
/**#ifdef HAVE_CONFIG_H
#include "config.h"
#endif*/
#include
#include
#include
#include "volume-widget.h"
#include "common-defs.h"
#include
///#include "indicator-sound.h"
#include "applet-backend-sound-menu-old.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 gboolean volume_widget_value_changed_cb(GtkRange *range, 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)
{
//g_debug("VolumeWidget::volume_widget_init");
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(volume_widget, "value-changed", G_CALLBACK(volume_widget_value_changed_cb), 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)
{
/// we need to unref what we ref'ed
// VolumeWidget *self = VOLUME_WIDGET (object);
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(object);
g_object_unref (priv->twin_item);
g_object_unref (priv->ido_volume_slider);
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) );
if(priv->grabbed == FALSE){
GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
GtkRange *range = (GtkRange*)slider;
gdouble update = g_variant_get_double (value);
gtk_range_set_value(range, update);
/*
g_debug ("volume-widget::volume_widget_property_update - volume - value %f", update);
*/
update_accessible_desc(update/**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);
}
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");
// we need to update the icon here.
update_accessible_desc (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.
*/
static gboolean
volume_widget_value_changed_cb (GtkRange *range, gpointer user_data)
{
g_return_val_if_fail (IS_VOLUME_WIDGET (user_data), FALSE);
VolumeWidget* mitem = VOLUME_WIDGET (user_data);
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100);
gboolean mute = g_variant_get_boolean (dbusmenu_menuitem_property_get_variant (priv->twin_item,
DBUSMENU_VOLUME_MENUITEM_MUTE));
if((current_value == 0 && mute == FALSE) || current_value == 100){
/*
g_debug ("value changed - actual set %f", current_value);
*/
volume_widget_update (mitem, current_value, "value-changed");
}
return FALSE;
}
void
volume_widget_update(VolumeWidget* self, gdouble update, const gchar* label)
{
const 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);
}
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;
}
cairo-dock-plugins-3.3.2/alsaMixer/CMakeLists.txt 000664 001750 001750 00000000332 12223247501 023030 0 ustar 00mbaerts mbaerts 000000 000000
add_subdirectory(src)
add_subdirectory(data)
########### install files ###############
#original Makefile.am contents follow:
##dnl Process this file with automake to produce Makefile.in
#
#SUBDIRS = . src data
cairo-dock-plugins-3.3.2/alsaMixer/data/broken.svg 000664 001750 001750 00000127273 12223247501 023220 0 ustar 00mbaerts mbaerts 000000 000000
cairo-dock-plugins-3.3.2/alsaMixer/data/icon.png 000664 001750 001750 00000010447 12223247501 022647 0 ustar 00mbaerts mbaerts 000000 000000 PNG
IHDR @ @ iq sBIT|d pHYs t tfx tEXtSoftware www.inkscape.org< IDATx[{p\u>=Vo-#$)Ҵ)ut:?0eF1' ĆZf2\ۅH%-˲$KZ}s]m$fwݽ;w~w-C{ ~IOd]iT$z̛J8p`_qLGqMU(Vo<LW_zPrrsݥ嶒/ٹYMOoƫD#`/?S za(?m (( Iq8wZC