1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * based on indicator-messages.c written by :
6 *  Ted Gould <ted@canonical.com>
7 *  Cody Russell <cody.russell@canonical.com>
8 * E-mail    : see the 'copyright' file.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 3
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #include <stdlib.h>
24 
25 #if (SOUND_SERVICE_VERSION < 1)
26 #include "dbus-shared-names-old.h"
27 #else
28 #include "dbus-shared-names.h"
29 #endif
30 
31 #include "applet-struct.h"
32 #include "common-defs.h"
33 #include "volume-widget.h"
34 #include "mute-widget.h"
35 #include "applet-menu.h"
36 #include "applet-backend-alsamixer.h"  // cd_mixer_init_alsa (fallback alsa backend)
37 #include "applet-generic.h"
38 #include "applet-draw.h"
39 #include "applet-backend-sound-menu-old.h"
40 
41 /*
42 // we can use icons designed for Unity, or more common icons that we are likely to find in icons themes.
43 static const gchar *_get_icon_from_state_unity (gint iState)
44 {
45 	switch (iState)
46 	{
47 		case MUTED: return "audio-volume-muted-panel";
48 		case ZERO_LEVEL: return "audio-volume-low-zero-panel";
49 		case LOW_LEVEL: return "audio-volume-low-panel";
50 		case MEDIUM_LEVEL: return "audio-volume-medium-panel";
51 		case HIGH_LEVEL: return "audio-volume-high-panel";
52 		case BLOCKED: return "audio-volume-muted-blocking-panel";
53 		default: return "audio-output-none-panel";
54 	}
55 }
56 static const gchar *_get_icon_from_state (gint iState)
57 {
58 	switch (iState)
59 	{
60 		case ZERO_LEVEL: return "audio-volume-off";
61 		case LOW_LEVEL: return "audio-volume-low";
62 		case MEDIUM_LEVEL: return "audio-volume-medium";
63 		case HIGH_LEVEL: return "audio-volume-high";
64 		default: return "audio-volume-muted";
65 	}
66 }*/
67 
68   ///////////
69  // PROXY //
70 ///////////
71 
72 static void
on_sound_state_updated(DBusGProxy * proxy,gint iNewState,GldiModuleInstance * myApplet)73 on_sound_state_updated (DBusGProxy * proxy, gint iNewState, GldiModuleInstance *myApplet)
74 {
75 	cd_debug ("%s (iNewState : %d)", __func__, iNewState);
76 	CD_APPLET_ENTER;
77 	if (iNewState != myData.iCurrentState)
78 	{
79 		myData.iCurrentState = iNewState;
80 		gboolean bIsMute = (iNewState == MUTED
81 		|| iNewState == UNAVAILABLE
82 		|| iNewState == BLOCKED);
83 		if (myData.bIsMute != bIsMute)
84 		{
85 			myData.bIsMute = bIsMute;
86 			cd_update_icon ();
87 		}
88 	}
89 	CD_APPLET_LEAVE();
90 }
91 
_get_volume(void)92 static int _get_volume (void)
93 {
94 	if (myData.volume_widget)
95 		return (int)volume_widget_get_current_volume (myData.volume_widget);
96 	else
97 		return 0;
98 }
99 
_set_volume(int iVolume)100 static void _set_volume (int iVolume)
101 {
102 	if (myData.volume_widget)
103 		volume_widget_update (VOLUME_WIDGET(myData.volume_widget), (gdouble)iVolume, "scroll updates");
104 }
105 
_toggle_mute(void)106 static void _toggle_mute (void)
107 {
108 	if (myData.mute_widget)
109 		mute_widget_toggle (MUTE_WIDGET (myData.mute_widget));
110 }
111 
_show_menu(void)112 static void _show_menu (void)
113 {
114 	cd_indicator_show_menu (myData.pIndicator);
115 }
116 
_stop(void)117 static void _stop (void)
118 {
119 	cd_indicator_destroy (myData.pIndicator);
120 
121 	g_list_free (myData.transport_widgets_list);
122 }
123 
cd_sound_on_connect(GldiModuleInstance * myApplet)124 static void cd_sound_on_connect (GldiModuleInstance *myApplet)
125 {
126 	cd_debug ("%s ()", __func__);
127 	// the sound service is up and running, stop the alsa mixer if ever we initialized it before.
128 	cd_stop ();
129 
130 	// and set the interface
131 	myData.ctl.get_volume = _get_volume;
132 	myData.ctl.set_volume = _set_volume;
133 	myData.ctl.toggle_mute = _toggle_mute;
134 	myData.ctl.show_hide = _show_menu;
135 	myData.ctl.stop = _stop;
136 	myData.ctl.reload = cd_update_icon;
137 
138 	// connect to the service signals.
139 	dbus_g_proxy_add_signal(myData.pIndicator->pServiceProxy, INDICATOR_SOUND_SIGNAL_STATE_UPDATE, G_TYPE_INT, G_TYPE_INVALID);
140 	dbus_g_proxy_connect_signal(myData.pIndicator->pServiceProxy,
141 		INDICATOR_SOUND_SIGNAL_STATE_UPDATE,
142 		G_CALLBACK(on_sound_state_updated),
143 		myApplet,
144 		NULL);
145 }
146 
cd_sound_on_disconnect(GldiModuleInstance * myApplet)147 static void cd_sound_on_disconnect (GldiModuleInstance *myApplet)
148 {
149 	CD_APPLET_ENTER;
150 	cd_debug ("%s", __func__);
151 
152 	if (myData.ctl.get_volume == _get_volume)  // the backend was set, unset it
153 	{
154 		memset (&myData.ctl, 0, sizeof (CDSoundCtl));
155 
156 		cd_debug ("clean");
157 		myData.volume_widget = NULL;
158 		myData.transport_widgets_list = NULL;
159 		myData.voip_widget = NULL;
160 		myData.mute_widget = NULL;
161 	}
162 
163 	// no (more) sound service, now rely on alsa.
164 	cd_mixer_init_alsa ();
165 
166 	CD_APPLET_LEAVE();
167 }
168 
_on_got_sound_state(DBusGProxy * proxy,DBusGProxyCall * call_id,GldiModuleInstance * myApplet)169 static void _on_got_sound_state (DBusGProxy *proxy, DBusGProxyCall *call_id, GldiModuleInstance *myApplet)
170 {
171 	CD_APPLET_ENTER;
172 	int iCurrentState = 0;
173 	gboolean bSuccess = dbus_g_proxy_end_call (proxy,
174 		call_id,
175 		NULL,
176 		G_TYPE_INT,
177 		&iCurrentState,
178 		G_TYPE_INVALID);
179 	cd_debug ("got sound state: %d", iCurrentState);
180 
181 	// update the icon.
182 	if (bSuccess)
183 	{
184 		myData.iCurrentState = iCurrentState;
185 		myData.bIsMute = (iCurrentState == MUTED
186 		|| iCurrentState == UNAVAILABLE
187 		|| iCurrentState == BLOCKED);
188 		myData.iCurrentVolume = _get_volume ();
189 
190 		cd_update_icon ();
191 	}
192 	CD_APPLET_LEAVE();
193 }
cd_sound_get_initial_values(GldiModuleInstance * myApplet)194 static void cd_sound_get_initial_values (GldiModuleInstance *myApplet)
195 {
196 	// query the service to display initial values.
197 	dbus_g_proxy_begin_call (myData.pIndicator->pServiceProxy, "GetSoundState",
198 		(DBusGProxyCallNotify)_on_got_sound_state,
199 		myApplet,
200 		(GDestroyNotify) NULL,
201 		G_TYPE_INVALID);
202 }
203 
204 
205 
update_accessible_desc(double new_value)206 void update_accessible_desc (double new_value)
207 {
208 	cd_debug ("%s (%p)", __func__, myData.volume_widget);
209 	if (!myData.volume_widget)
210 		return;
211 
212 	myData.iCurrentVolume = (new_value < 0 ? _get_volume() : new_value);
213 	cd_update_icon ();
214 }
215 
cd_mixer_connect_to_sound_service(void)216 void cd_mixer_connect_to_sound_service (void)
217 {
218 	myData.pIndicator = cd_indicator_new (myApplet,
219 		INDICATOR_SOUND_DBUS_NAME,
220 		INDICATOR_SOUND_SERVICE_DBUS_OBJECT_PATH,
221 		INDICATOR_SOUND_DBUS_INTERFACE,
222 		INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH,
223 		0);
224 	myData.pIndicator->on_connect 			= cd_sound_on_connect;
225 	myData.pIndicator->on_disconnect 		= cd_sound_on_disconnect;
226 	myData.pIndicator->get_initial_values 	= cd_sound_get_initial_values;
227 	myData.pIndicator->add_menu_handler 	= cd_sound_add_menu_handler;
228 }
229