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