2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include "applet-config.h"
24
#include "applet-notifications.h"
25
#include "applet-struct.h"
26
#include "applet-mixer.h"
27
#include "applet-draw.h"
28
#include "applet-init.h"
31
CD_APPLET_PRE_INIT_BEGIN (N_("AlsaMixer"),
33
CAIRO_DOCK_CATEGORY_CONTROLER,
34
N_("This applet lets you control the sound volume from the dock.\n"
35
"Scroll up/down on the icon to increase/decrease the volume.\n"
36
"Click on icon to show/hide volume control (you can bind a keyboard shortcut for it)\n"
37
"You can also hide the dialog by clicking on it.\n"
38
"Middle-click to set or unset to mute, double-click to raise the channels mixer.\n"
39
"This applet works with the Alsa sound driver."),
40
"Fabounet (Fabrice Rey)")
41
CD_APPLET_DEFINE_COMMON_APPLET_INTERFACE
42
pInterface->load_custom_widget = cd_mixer_load_custom_widget;
43
CD_APPLET_PRE_INIT_END
46
static void _load_surfaces (void)
48
GString *sImagePath = g_string_new ("");
50
if (myData.pSurface != NULL)
51
cairo_surface_destroy (myData.pSurface);
52
if (myConfig.cDefaultIcon != NULL)
54
gchar *cUserImagePath = cairo_dock_generate_file_path (myConfig.cDefaultIcon);
55
myData.pSurface = CD_APPLET_LOAD_SURFACE_FOR_MY_APPLET (cUserImagePath);
56
g_free (cUserImagePath);
60
g_string_printf (sImagePath, "%s/default.svg", MY_APPLET_SHARE_DATA_DIR);
61
myData.pSurface = CD_APPLET_LOAD_SURFACE_FOR_MY_APPLET (sImagePath->str);
64
if (myData.pMuteSurface != NULL)
65
cairo_surface_destroy (myData.pMuteSurface);
66
if (myConfig.cMuteIcon != NULL)
68
gchar *cUserImagePath = cairo_dock_generate_file_path (myConfig.cMuteIcon);
69
myData.pMuteSurface = CD_APPLET_LOAD_SURFACE_FOR_MY_APPLET (cUserImagePath);
70
g_free (cUserImagePath);
74
g_string_printf (sImagePath, "%s/mute.svg", MY_APPLET_SHARE_DATA_DIR);
75
myData.pMuteSurface = CD_APPLET_LOAD_SURFACE_FOR_MY_APPLET (sImagePath->str);
78
g_string_free (sImagePath, TRUE);
82
static gboolean _cd_mixer_on_enter (GtkWidget* pWidget,
83
GdkEventCrossing* pEvent,
86
if (myDesklet && myDesklet->iHeight > 64)
88
gtk_widget_show (myData.pScale);
91
gboolean _cd_mixer_on_leave (GtkWidget* pWidget,
92
GdkEventCrossing* pEvent,
95
if (myDesklet && myDesklet->iHeight > 64)
97
if (! myDesklet->bInside)
98
gtk_widget_hide (myData.pScale);
103
if (myDesklet != NULL)
105
int iScaleWidth = (myDesklet->iHeight > 64 ? 15 : 0);
106
myIcon->fWidth = MAX (MAX (1, g_iDockRadius), MIN (myDesklet->iWidth, myDesklet->iHeight) - iScaleWidth);
107
myIcon->fHeight = myIcon->fWidth;
108
myIcon->fDrawX = 0*g_iDockRadius/2;
109
myIcon->fDrawY = myDesklet->iHeight - myIcon->fHeight;
111
cairo_dock_load_one_icon_from_scratch (myIcon, myContainer);
112
cairo_dock_set_desklet_renderer_by_name (myDesklet, "Simple", NULL, ! CAIRO_DOCK_LOAD_ICONS_FOR_DESKLET, NULL); // on charge l'icone nous-memes.
113
myDrawContext = cairo_create (myIcon->pIconBuffer);
114
if (myConfig.bHideScaleOnLeave)
116
g_signal_connect (G_OBJECT (myDesklet->pWidget),
117
"enter-notify-event",
118
G_CALLBACK (_cd_mixer_on_enter),
120
g_signal_connect (G_OBJECT (myDesklet->pWidget),
121
"leave-notify-event",
122
G_CALLBACK (_cd_mixer_on_leave),
129
mixer_init (myConfig.card_id);
131
///mixer_write_elements_list (CD_APPLET_MY_CONF_FILE, CD_APPLET_MY_KEY_FILE);
132
mixer_get_controlled_element ();
134
if (myData.pControledElement == NULL)
136
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cBrokenIcon, "broken.svg");
142
GtkWidget *box = gtk_hbox_new (FALSE, 0);
143
myData.pScale = mixer_build_widget (FALSE);
144
gtk_box_pack_end (GTK_BOX (box), myData.pScale, FALSE, FALSE, 0);
145
gtk_container_add (GTK_CONTAINER (myDesklet->pWidget), box);
146
gtk_widget_show_all (box);
148
if (myConfig.bHideScaleOnLeave && ! myDesklet->bInside)
149
gtk_widget_hide (myData.pScale);
150
g_signal_connect (G_OBJECT (myDesklet->pWidget),
151
"enter-notify-event",
152
G_CALLBACK (_cd_mixer_on_enter),
154
g_signal_connect (G_OBJECT (myDesklet->pWidget),
155
"leave-notify-event",
156
G_CALLBACK (_cd_mixer_on_leave),
160
mixer_element_update_with_event (myData.pControledElement, 1);
161
myData.iSidCheckVolume = g_timeout_add (1000, (GSourceFunc) mixer_check_events, (gpointer) NULL);
164
CD_APPLET_REGISTER_FOR_CLICK_EVENT;
165
CD_APPLET_REGISTER_FOR_MIDDLE_CLICK_EVENT;
166
CD_APPLET_REGISTER_FOR_BUILD_MENU_EVENT;
167
CD_APPLET_REGISTER_FOR_SCROLL_EVENT;
168
CD_APPLET_REGISTER_FOR_DOUBLE_CLICK_EVENT;
170
cd_keybinder_bind (myConfig.cShortcut, (CDBindkeyHandler) mixer_on_keybinding_pull, (gpointer)NULL);
175
//\_______________ On se desabonne de nos notifications.
176
CD_APPLET_UNREGISTER_FOR_CLICK_EVENT;
177
CD_APPLET_UNREGISTER_FOR_MIDDLE_CLICK_EVENT;
178
CD_APPLET_UNREGISTER_FOR_BUILD_MENU_EVENT;
179
CD_APPLET_UNREGISTER_FOR_SCROLL_EVENT;
180
CD_APPLET_UNREGISTER_FOR_DOUBLE_CLICK_EVENT;
182
//\_________________ On stoppe le timer.
183
if (myData.iSidCheckVolume != 0)
185
g_source_remove (myData.iSidCheckVolume);
186
myData.iSidCheckVolume = 0;
191
CD_APPLET_RELOAD_BEGIN
192
if (myDesklet != NULL)
194
int iScaleWidth = (myDesklet->iHeight > 64 ? 15 : 0);
195
myIcon->fWidth = MAX (MAX (1, g_iDockRadius), MIN (myDesklet->iWidth, myDesklet->iHeight) - iScaleWidth);
196
myIcon->fHeight = myIcon->fWidth;
197
myIcon->fDrawX = 0*g_iDockRadius/2;
198
myIcon->fDrawY = myDesklet->iHeight - myIcon->fHeight + 0*g_iDockRadius/2;
200
cairo_dock_load_one_icon_from_scratch (myIcon, myContainer);
201
cairo_dock_set_desklet_renderer_by_name (myDesklet, "Simple", NULL, ! CAIRO_DOCK_LOAD_ICONS_FOR_DESKLET, NULL);
202
myDrawContext = cairo_create (myIcon->pIconBuffer);
205
//\_______________ On recharge les donnees qui ont pu changer.
208
//\_______________ On recharge le mixer si necessaire.
209
if (CD_APPLET_MY_CONFIG_CHANGED)
211
if (myData.iSidCheckVolume != 0)
213
g_source_remove (myData.iSidCheckVolume);
214
myData.iSidCheckVolume = 0;
218
g_free (myData.cErrorMessage);
219
myData.cErrorMessage = NULL;
220
g_free (myData.mixer_card_name);
221
myData.mixer_card_name = NULL;
222
g_free (myData.mixer_device_name);
223
myData.mixer_device_name= NULL;
225
if (myConfig.iVolumeDisplay != VOLUME_ON_ICON)
226
CD_APPLET_SET_QUICK_INFO_ON_MY_ICON_PRINTF (NULL);
228
mixer_init (myConfig.card_id);
229
///mixer_write_elements_list (CD_APPLET_MY_CONF_FILE, CD_APPLET_MY_KEY_FILE);
230
mixer_get_controlled_element ();
232
if (myData.pControledElement == NULL)
234
CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cBrokenIcon, "broken.svg");
238
mixer_element_update_with_event (myData.pControledElement, 1);
239
if (myData.iSidCheckVolume == 0)
240
myData.iSidCheckVolume = g_timeout_add (1000, (GSourceFunc) mixer_check_events, (gpointer) NULL);
243
cd_keybinder_bind (myConfig.cShortcut, (CDBindkeyHandler) mixer_on_keybinding_pull, (gpointer)NULL);
247
if (CD_APPLET_MY_CONTAINER_TYPE_CHANGED)
249
cairo_dock_dialog_unreference (myData.pDialog);
250
myData.pDialog = NULL;
252
GtkWidget *box = gtk_hbox_new (FALSE, 0);
253
myData.pScale = mixer_build_widget (FALSE);
254
gtk_box_pack_end (GTK_BOX (box), myData.pScale, FALSE, FALSE, 0);
255
gtk_widget_show_all (box);
256
gtk_container_add (GTK_CONTAINER (myDesklet->pWidget), box);
257
if (myConfig.bHideScaleOnLeave && ! myDesklet->bInside)
258
gtk_widget_hide (myData.pScale);
261
gulong iOnEnterCallbackID = g_signal_handler_find (myDesklet->pWidget,
268
if (myConfig.bHideScaleOnLeave && iOnEnterCallbackID <= 0)
270
g_signal_connect (G_OBJECT (myDesklet->pWidget),
271
"enter-notify-event",
272
G_CALLBACK (_cd_mixer_on_enter),
274
g_signal_connect (G_OBJECT (myDesklet->pWidget),
275
"leave-notify-event",
276
G_CALLBACK (_cd_mixer_on_leave),
279
else if (! myConfig.bHideScaleOnLeave && iOnEnterCallbackID > 0)
281
g_signal_handler_disconnect (G_OBJECT (myDesklet->pWidget), iOnEnterCallbackID);
282
gulong iOnLeaveCallbackID = g_signal_handler_find (myDesklet->pWidget,
289
g_signal_handler_disconnect (G_OBJECT (myDesklet->pWidget), iOnLeaveCallbackID);
293
else // on redessine juste notre icone si elle n'a pas ete rechargee par le dock.
295
//\_______________ On redessine notre icone.
296
if (myData.pControledElement != NULL)
298
mixer_element_update_with_event (myData.pControledElement, 0);
301
if (myDesklet && myDesklet->iHeight <= 64)
302
gtk_widget_hide (myData.pScale);