1 #include "e.h"
2
3 E_API int E_EVENT_CLIENT_VOLUME = -1;
4 E_API int E_EVENT_CLIENT_MUTE = -1;
5 E_API int E_EVENT_CLIENT_UNMUTE = -1;
6 E_API int E_EVENT_CLIENT_VOLUME_SINK_ADD = -1;
7 E_API int E_EVENT_CLIENT_VOLUME_SINK_DEL = -1;
8 E_API int E_EVENT_CLIENT_VOLUME_SINK_CHANGED = -1;
9
10 static void _e_client_volume_event_simple_free(void *d, E_Event_Client *ev);
11 static void _e_client_volume_event_simple(E_Client *ec, int type);
12 static void _e_client_volume_object_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
13 static void _e_client_volume_object_volume_changed(void *data, Evas_Object *obj, void *event_info);
14 static void _e_client_volume_object_volume_drag_stop(void *data, Evas_Object *obj, void *event_info);
15 static Eina_Bool _e_client_volume_object_changed(void *data, int type, void *event);
16 static void _e_client_volume_object_del_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);
17
18 static void
_e_client_volume_event_simple_free(void * d EINA_UNUSED,E_Event_Client * ev)19 _e_client_volume_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev)
20 {
21 UNREFD(ev->ec, 3);
22 e_object_unref(E_OBJECT(ev->ec));
23 free(ev);
24 }
25
26 static void
_e_client_volume_event_simple(E_Client * ec,int type)27 _e_client_volume_event_simple(E_Client *ec, int type)
28 {
29 E_Event_Client *ev;
30
31 ev = E_NEW(E_Event_Client, 1);
32 ev->ec = ec;
33 REFD(ec, 3);
34 e_object_ref(E_OBJECT(ec));
35 ecore_event_add(type, ev,
36 (Ecore_End_Cb)_e_client_volume_event_simple_free, NULL);
37 }
38
39 static void
_e_client_volume_sink_event_simple_free(void * d EINA_UNUSED,E_Event_Client_Volume_Sink * ev)40 _e_client_volume_sink_event_simple_free(void *d EINA_UNUSED, E_Event_Client_Volume_Sink *ev)
41 {
42 UNREFD(ev->ec, 3);
43 e_object_unref(E_OBJECT(ev->ec));
44 free(ev);
45 }
46
47 static void
_e_client_volume_sink_event_simple(E_Client * ec,E_Client_Volume_Sink * sink,int type)48 _e_client_volume_sink_event_simple(E_Client *ec, E_Client_Volume_Sink *sink, int type)
49 {
50 E_Event_Client_Volume_Sink *ev;
51
52 ev = E_NEW(E_Event_Client_Volume_Sink, 1);
53 ev->ec = ec;
54 ev->sink = sink;
55 REFD(ec, 3);
56 e_object_ref(E_OBJECT(ec));
57 ecore_event_add(type, ev,
58 (Ecore_End_Cb)_e_client_volume_sink_event_simple_free, NULL);
59 }
60
61 static void
_e_client_volume_object_mouse_down_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)62 _e_client_volume_object_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
63 {
64 E_Client *ec;
65
66 ec = data;
67
68 e_client_volume_mute_set(ec, !(ec->mute));
69 }
70
71 static void
_e_client_volume_object_volume_changed(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)72 _e_client_volume_object_volume_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
73 {
74 E_Client *ec;
75
76 ec = data;
77
78 e_client_volume_set(ec, elm_slider_value_get(obj));
79 }
80
81 static void
_e_client_volume_object_volume_drag_stop(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)82 _e_client_volume_object_volume_drag_stop(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
83 {
84 E_Client *ec;
85
86 ec = data;
87
88 e_client_volume_set(ec, elm_slider_value_get(obj));
89 }
90
91 static Eina_Bool
_e_client_volume_object_changed(void * data,int type EINA_UNUSED,void * event)92 _e_client_volume_object_changed(void *data, int type EINA_UNUSED, void *event)
93 {
94 E_Event_Client *ev;
95 Evas_Object *o;
96 Evas_Object *bx;
97 Edje_Message_Int_Set *msg;
98
99 ev = event;
100 bx = data;
101
102 o = edje_object_part_swallow_get(bx, "e.swallow.volume_icon");
103 if (o)
104 {
105 msg = alloca(sizeof(Edje_Message_Int_Set) + (2 * sizeof(int)));
106 msg->count = 3;
107 msg->val[0] = ev->ec->mute;
108 msg->val[1] = ev->ec->volume;
109 msg->val[2] = msg->val[1];
110 edje_object_message_send(o, EDJE_MESSAGE_INT_SET, 0, msg);
111 edje_object_signal_emit(o, "e,action,volume,change", "e");
112 }
113 o = edje_object_part_swallow_get(bx, "e.swallow.volume");
114 if (o)
115 {
116 elm_slider_value_set(o, ev->ec->volume);
117 }
118
119 return ECORE_CALLBACK_PASS_ON;
120 }
121
122 static void
_e_client_volume_object_del_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)123 _e_client_volume_object_del_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
124 {
125 Eina_List *handlers;
126 Evas_Object *o;
127
128 handlers = data;
129
130 o = edje_object_part_swallow_get(obj, "e.swallow.volume_icon");
131 if (o) evas_object_del(o);
132 o = edje_object_part_swallow_get(obj, "e.swallow.volume");
133 if (o) evas_object_del(o);
134
135 E_FREE_LIST(handlers, ecore_event_handler_del);
136 }
137
138
139
140 EINTERN int
e_client_volume_init(void)141 e_client_volume_init(void)
142 {
143 E_EVENT_CLIENT_VOLUME = ecore_event_type_new();
144 E_EVENT_CLIENT_MUTE = ecore_event_type_new();
145 E_EVENT_CLIENT_UNMUTE = ecore_event_type_new();
146 E_EVENT_CLIENT_VOLUME_SINK_ADD = ecore_event_type_new();
147 E_EVENT_CLIENT_VOLUME_SINK_DEL = ecore_event_type_new();
148 E_EVENT_CLIENT_VOLUME_SINK_CHANGED = ecore_event_type_new();
149
150 return EINA_TRUE;
151 }
152
153 EINTERN void
e_client_volume_shutdown(void)154 e_client_volume_shutdown(void)
155 {
156 }
157
158 E_API E_Client_Volume_Sink *
e_client_volume_sink_new(E_Client_Volume_Sink_Get func_get,E_Client_Volume_Sink_Set func_set,E_Client_Volume_Sink_Min_Get func_min_get,E_Client_Volume_Sink_Max_Get func_max_get,E_Client_Volume_Sink_Name_Get func_name_get,void * data)159 e_client_volume_sink_new(E_Client_Volume_Sink_Get func_get, E_Client_Volume_Sink_Set func_set, E_Client_Volume_Sink_Min_Get func_min_get, E_Client_Volume_Sink_Max_Get func_max_get, E_Client_Volume_Sink_Name_Get func_name_get, void *data)
160 {
161 E_Client_Volume_Sink *sink;
162
163 sink = E_NEW(E_Client_Volume_Sink, 1);
164 sink->func_set = func_set;
165 sink->func_get = func_get;
166 sink->func_min_get = func_min_get;
167 sink->func_max_get = func_max_get;
168 sink->func_name_get = func_name_get;
169 sink->data = data;
170
171 return sink;
172 }
173
174 E_API void
e_client_volume_sink_del(E_Client_Volume_Sink * sink)175 e_client_volume_sink_del(E_Client_Volume_Sink *sink)
176 {
177 E_Client *ec;
178
179 EINA_LIST_FREE(sink->clients, ec)
180 {
181 ec->sinks = eina_list_remove(ec->sinks, sink);
182 e_comp_object_frame_volume_update(ec->frame);
183 _e_client_volume_sink_event_simple(ec, sink,
184 E_EVENT_CLIENT_VOLUME_SINK_DEL);
185 e_object_unref(E_OBJECT(ec));
186 }
187 free(sink);
188 }
189
190 E_API void
e_client_volume_sink_set(E_Client_Volume_Sink * sink,int volume,Eina_Bool mute)191 e_client_volume_sink_set(E_Client_Volume_Sink *sink, int volume, Eina_Bool mute)
192 {
193 EINA_SAFETY_ON_NULL_RETURN(sink);
194 if (sink->func_set)
195 sink->func_set(volume, mute, sink->data);
196 }
197
198 E_API void
e_client_volume_sink_get(const E_Client_Volume_Sink * sink,int * volume,Eina_Bool * mute)199 e_client_volume_sink_get(const E_Client_Volume_Sink *sink, int *volume, Eina_Bool *mute)
200 {
201 EINA_SAFETY_ON_NULL_RETURN(sink);
202 if (sink->func_get)
203 sink->func_get(volume, mute, sink->data);
204 }
205
206 E_API int
e_client_volume_sink_min_get(const E_Client_Volume_Sink * sink)207 e_client_volume_sink_min_get(const E_Client_Volume_Sink *sink)
208 {
209 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, 0);
210 if (sink->func_min_get)
211 return sink->func_min_get(sink->data);
212
213 return 0;
214 }
215
216 E_API int
e_client_volume_sink_max_get(const E_Client_Volume_Sink * sink)217 e_client_volume_sink_max_get(const E_Client_Volume_Sink *sink)
218 {
219 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, 0);
220 if (sink->func_max_get)
221 return sink->func_max_get(sink->data);
222 return 0;
223 }
224
225 E_API const char *
e_client_volume_sink_name_get(const E_Client_Volume_Sink * sink)226 e_client_volume_sink_name_get(const E_Client_Volume_Sink *sink)
227 {
228 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, 0);
229 if (sink->func_name_get)
230 return sink->func_name_get(sink->data);
231 return NULL;
232 }
233
234 static void
_e_client_volume_update(E_Client * ec)235 _e_client_volume_update(E_Client *ec)
236 {
237 E_Client_Volume_Sink *sink;
238 Eina_List *l;
239 int volume_min, volume_max, volume, count;
240 Eina_Bool mute;
241
242 mute = EINA_TRUE;
243 volume = 0;
244 volume_min = 9999999;
245 volume_max = 0;
246 count = 0;
247 EINA_LIST_FOREACH(ec->sinks, l, sink)
248 {
249 int volume_min2, volume_max2, volume2;
250 Eina_Bool mute2;
251
252 volume_min2 = e_client_volume_sink_min_get(sink);
253 volume_max2 = e_client_volume_sink_max_get(sink);
254 if (volume_min2 < volume_min) volume_min = volume_min2;
255 if (volume_max2 > volume_max) volume_max = volume_max2;
256 e_client_volume_sink_get(sink, &volume2, &mute2);
257 if (!mute2)
258 {
259 mute = EINA_FALSE;
260 volume += volume2;
261 count++;
262 }
263 }
264 if (ec->sinks)
265 {
266 ec->volume_min = volume_min;
267 ec->volume_max = volume_max;
268 if (count == 0)
269 {
270 if (ec->volume < volume_min)
271 ec->volume = volume_min;
272 if (ec->volume > volume_max)
273 ec->volume = volume_max;
274 }
275 else
276 ec->volume = volume / count;
277 ec->mute = mute;
278 ec->volume_control_enabled = EINA_TRUE;
279 }
280 else
281 {
282 ec->volume_min = 0;
283 ec->volume_max = 0;
284 ec->volume = 0;
285 ec->mute = EINA_FALSE;
286 ec->volume_control_enabled = EINA_FALSE;
287 }
288 if (ec->volume_control_enabled)
289 {
290 e_comp_object_frame_volume_update(ec->frame);
291 e_client_volume_display_set(ec, ec->volume, ec->mute);
292 }
293 }
294
295 E_API void
e_client_volume_sink_append(E_Client * ec,E_Client_Volume_Sink * sink)296 e_client_volume_sink_append(E_Client *ec, E_Client_Volume_Sink *sink)
297 {
298 int volume;
299 Eina_Bool mute;
300
301 EINA_SAFETY_ON_NULL_RETURN(ec);
302
303 ec->sinks = eina_list_append(ec->sinks, sink);
304 sink->clients = eina_list_append(sink->clients, ec);
305 e_object_ref(E_OBJECT(ec));
306 if (!ec->volume_control_enabled)
307 {
308 ec->volume_min = e_client_volume_sink_min_get(sink);
309 ec->volume_max = e_client_volume_sink_max_get(sink);
310 e_client_volume_sink_get(sink, &volume, &mute);
311 ec->volume = volume;
312 ec->mute = !!mute;
313 ec->volume_control_enabled = EINA_TRUE;
314 }
315 _e_client_volume_update(ec);
316 _e_client_volume_sink_event_simple(ec, sink,
317 E_EVENT_CLIENT_VOLUME_SINK_ADD);
318 }
319
320 E_API void
e_client_volume_sink_remove(E_Client * ec,E_Client_Volume_Sink * sink)321 e_client_volume_sink_remove(E_Client *ec, E_Client_Volume_Sink *sink)
322 {
323 EINA_SAFETY_ON_NULL_RETURN(ec);
324 ec->sinks = eina_list_remove(ec->sinks, sink);
325 sink->clients = eina_list_remove(sink->clients, ec);
326 _e_client_volume_update(ec);
327 _e_client_volume_sink_event_simple(ec, sink,
328 E_EVENT_CLIENT_VOLUME_SINK_DEL);
329 e_object_unref(E_OBJECT(ec));
330 }
331
332 E_API void
e_client_volume_sink_update(E_Client_Volume_Sink * sink)333 e_client_volume_sink_update(E_Client_Volume_Sink *sink)
334 {
335 Eina_List *l;
336 E_Client *ec;
337
338 EINA_SAFETY_ON_NULL_RETURN(sink);
339
340 EINA_LIST_FOREACH(sink->clients, l, ec)
341 {
342 _e_client_volume_update(ec);
343 _e_client_volume_sink_event_simple(ec, sink,
344 E_EVENT_CLIENT_VOLUME_SINK_CHANGED);
345 }
346 }
347
348 E_API void
e_client_volume_display_set(E_Client * ec,int volume,Eina_Bool mute)349 e_client_volume_display_set(E_Client *ec, int volume, Eina_Bool mute)
350 {
351 ec->volume = volume;
352 ec->mute = !!mute;
353 if (mute)
354 _e_client_volume_event_simple(ec, E_EVENT_CLIENT_MUTE);
355 else
356 _e_client_volume_event_simple(ec, E_EVENT_CLIENT_UNMUTE);
357 _e_client_volume_event_simple(ec, E_EVENT_CLIENT_VOLUME);
358 }
359
360 E_API void
e_client_volume_set(E_Client * ec,int volume)361 e_client_volume_set(E_Client *ec, int volume)
362 {
363 Eina_List *l;
364 E_Client_Volume_Sink *sink;
365
366 EINA_SAFETY_ON_NULL_RETURN(ec);
367 if (volume < ec->volume_min) volume = ec->volume_min;
368 if (volume > ec->volume_max) volume = ec->volume_max;
369 if (volume == ec->volume) return;
370 ec->volume = volume;
371
372 EINA_LIST_FOREACH(ec->sinks, l, sink)
373 {
374 e_client_volume_sink_set(sink, ec->volume, ec->mute);
375 }
376
377 _e_client_volume_update(ec);
378 _e_client_volume_event_simple(ec, E_EVENT_CLIENT_VOLUME);
379 }
380
381 E_API void
e_client_volume_mute_set(E_Client * ec,Eina_Bool mute)382 e_client_volume_mute_set(E_Client *ec, Eina_Bool mute)
383 {
384 Eina_List *l;
385 E_Client_Volume_Sink *sink;
386
387 EINA_SAFETY_ON_NULL_RETURN(ec);
388 if (!!mute == ec->mute) return;
389 ec->mute = !!mute;
390
391 EINA_LIST_FOREACH(ec->sinks, l, sink)
392 {
393 if (sink->func_set)
394 sink->func_set(ec->volume, ec->mute, sink->data);
395 }
396 if (mute)
397 _e_client_volume_event_simple(ec, E_EVENT_CLIENT_MUTE);
398 else
399 _e_client_volume_event_simple(ec, E_EVENT_CLIENT_UNMUTE);
400 }
401
402 E_API Evas_Object *
e_client_volume_object_add(E_Client * ec,Evas * evas)403 e_client_volume_object_add(E_Client *ec, Evas *evas)
404 {
405 Evas_Object *bx, *o;
406 Edje_Message_Int_Set *msg;
407 Eina_List *handlers = NULL;
408
409 bx = edje_object_add(evas);
410 e_theme_edje_object_set(bx,
411 "base/theme/border/volume",
412 "e/widgets/border/volume");
413
414 if (edje_object_part_exists(bx, "e.swallow.volume_icon"))
415 {
416 o = edje_object_add(evas);
417 e_theme_edje_object_set(o,
418 "base/theme/modules/mixer",
419 "e/modules/mixer/main");
420
421 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
422 _e_client_volume_object_mouse_down_cb,
423 ec);
424 edje_object_part_swallow(bx, "e.swallow.volume_icon", o);
425 msg = alloca(sizeof(Edje_Message_Int_Set) + (2 * sizeof(int)));
426 msg->count = 3;
427 msg->val[0] = ec->mute;
428 msg->val[1] = ec->volume;
429 msg->val[2] = msg->val[1];
430 edje_object_message_send(o, EDJE_MESSAGE_INT_SET, 0, msg);
431 edje_object_signal_emit(o, "e,action,volume,change", "e");
432 evas_object_show(o);
433 }
434 if (edje_object_part_exists(bx, "e.swallow.volume"))
435 {
436 o = edje_object_add(evas);
437 o = elm_slider_add(e_comp->elm);
438 elm_slider_min_max_set(o, ec->volume_min,
439 ec->volume_max);
440 elm_slider_span_size_set(o, ec->volume_max
441 * elm_config_scale_get());
442 elm_slider_unit_format_set(o, "%.0f");
443 elm_slider_indicator_format_set(o, "%.0f");
444 evas_object_smart_callback_add(o, "changed",
445 _e_client_volume_object_volume_changed,
446 ec);
447 evas_object_smart_callback_add(o, "slider,drag,stop",
448 _e_client_volume_object_volume_drag_stop,
449 ec);
450 elm_slider_value_set(o, ec->volume);
451 edje_object_part_swallow(bx, "e.swallow.volume", o);
452 evas_object_show(o);
453 }
454
455 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_VOLUME,
456 _e_client_volume_object_changed, bx);
457 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_MUTE,
458 _e_client_volume_object_changed, bx);
459 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_UNMUTE,
460 _e_client_volume_object_changed, bx);
461
462 evas_object_event_callback_add(bx, EVAS_CALLBACK_DEL,
463 _e_client_volume_object_del_cb, handlers);
464 return bx;
465 }
466
467 E_API void
e_client_volume_object_emit(E_Client * ec,const char * sig,const char * src)468 e_client_volume_object_emit(E_Client *ec, const char *sig, const char *src)
469 {
470 Evas_Object *o;
471
472 EINA_SAFETY_ON_NULL_RETURN(ec);
473 o = e_comp_object_frame_volume_get(ec->frame);
474 if (o)
475 {
476 edje_object_signal_emit(o, sig, src);
477 o = edje_object_part_swallow_get(o, "e.swallow.volume_icon");
478 if (o) edje_object_signal_emit(o, sig, src);
479 }
480 }
481