summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Bouchaud (yoz) <yoz@efl.so>2019-05-21 14:40:43 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-05-21 14:41:24 +0100
commit5aedf54042e3af234b4dd35d6ba0961ae5023739 (patch)
tree8233fc2a972c9da8135b6012fcb4bb9a89130432
parent5cded14b76419154cc5de5dbe984805ebcf99d6f (diff)
emixer: Add volume channels control on emixer
Summary: This commit allow the user to control each volumes channels in emixer. A lock flag is introduced to manage volume as before. @feature Reviewers: zmike!, devilhorns, raster Subscribers: cedric Tags: #enlightenment-git Differential Revision: https://phab.enlightenment.org/D7639
-rw-r--r--src/modules/mixer/e_mod_config.c4
-rw-r--r--src/modules/mixer/emixer.c711
-rw-r--r--src/modules/mixer/gadget/backend.c4
-rw-r--r--src/modules/mixer/lib/backends/alsa/alsa.c24
-rw-r--r--src/modules/mixer/lib/backends/pulseaudio/pulse.c79
-rw-r--r--src/modules/mixer/lib/emix.c6
-rw-r--r--src/modules/mixer/lib/emix.h25
7 files changed, 705 insertions, 148 deletions
diff --git a/src/modules/mixer/e_mod_config.c b/src/modules/mixer/e_mod_config.c
index 1dad09389..9f93e7972 100644
--- a/src/modules/mixer/e_mod_config.c
+++ b/src/modules/mixer/e_mod_config.c
@@ -347,7 +347,7 @@ emix_config_save_state_restore(void)
347 v.channel_count = emsink->volume.channel_count; 347 v.channel_count = emsink->volume.channel_count;
348 for (i = 0; i < v.channel_count; i++) 348 for (i = 0; i < v.channel_count; i++)
349 v.volumes[i] = sink->volume; 349 v.volumes[i] = sink->volume;
350 emix_sink_volume_set(emsink, v); 350 emix_sink_volume_set(emsink, &v);
351 free(v.volumes); 351 free(v.volumes);
352 } 352 }
353 emix_sink_mute_set(emsink, sink->mute); 353 emix_sink_mute_set(emsink, sink->mute);
@@ -373,7 +373,7 @@ emix_config_save_state_restore(void)
373 v.channel_count = emsource->volume.channel_count; 373 v.channel_count = emsource->volume.channel_count;
374 for (i = 0; i < v.channel_count; i++) 374 for (i = 0; i < v.channel_count; i++)
375 v.volumes[i] = source->volume; 375 v.volumes[i] = source->volume;
376 emix_source_volume_set(emsource, v); 376 emix_source_volume_set(emsource, &v);
377 free(v.volumes); 377 free(v.volumes);
378 } 378 }
379 emix_source_mute_set(emsource, source->mute); 379 emix_source_mute_set(emsource, source->mute);
diff --git a/src/modules/mixer/emixer.c b/src/modules/mixer/emixer.c
index 9b3644013..ae1719c25 100644
--- a/src/modules/mixer/emixer.c
+++ b/src/modules/mixer/emixer.c
@@ -9,6 +9,8 @@ Eina_List *source_list = NULL, *sink_input_list = NULL, *sink_list = NULL, *card
9 9
10////////////////////////////////////////////////////////////////////////////// 10//////////////////////////////////////////////////////////////////////////////
11 11
12static void _emix_sink_volume_fill(Emix_Sink *sink, Evas_Object *bxv, Evas_Object *bx, Eina_Bool locked);
13
12static Eina_Bool 14static Eina_Bool
13_backend_init(const char *back) 15_backend_init(const char *back)
14{ 16{
@@ -49,24 +51,167 @@ _cb_sink_volume_change(void *data,
49} 51}
50 52
51static void 53static void
54_cb_sink_volume_channel_change(void *data,
55 Evas_Object *obj,
56 void *event_info EINA_UNUSED)
57{
58 Evas_Object *bxv = data;
59 Emix_Sink *sink = evas_object_data_get(bxv, "sink");
60 double vol = elm_slider_value_get(obj);
61 sink->volume.volumes[(uintptr_t)evas_object_data_get(obj, "channel")] = vol;
62 elm_slider_value_set(obj, vol);
63 emix_sink_volume_set(sink, &sink->volume);
64}
65
66
67static void
52_cb_sink_mute_change(void *data, 68_cb_sink_mute_change(void *data,
53 Evas_Object *obj, 69 Evas_Object *obj,
54 void *event_info EINA_UNUSED) 70 void *event_info EINA_UNUSED)
55{ 71{
56 Evas_Object *bxv = data; 72 Evas_Object *bxv = data;
57 Emix_Sink *sink = evas_object_data_get(bxv, "sink"); 73 Emix_Sink *sink = evas_object_data_get(bxv, "sink");
58 Evas_Object *sl = evas_object_data_get(bxv, "volume"); 74 Evas_Object *lock = evas_object_data_get(bxv, "lock");
59 Eina_Bool mute = elm_check_state_get(obj); 75 Eina_Bool mute = elm_check_state_get(obj);
60 elm_object_disabled_set(sl, mute); 76 Eina_List *l;
77 Evas_Object *o;
78
79 if (lock && !elm_check_state_get(lock))
80 {
81 EINA_LIST_FOREACH(evas_object_data_get(bxv, "volumes"), l, o)
82 {
83 elm_object_disabled_set(o, mute);
84 o = evas_object_data_get(o, "lb");
85 elm_object_disabled_set(o, mute);
86 }
87 }
88 else
89 {
90 o = evas_object_data_get(bxv, "volume");
91 elm_object_disabled_set(o, mute);
92 }
61 emix_sink_mute_set(sink, mute); 93 emix_sink_mute_set(sink, mute);
62} 94}
63 95
64static void 96static void
97_cb_sink_lock_change(void *data,
98 Evas_Object *obj,
99 void *event_info EINA_UNUSED)
100{
101 Evas_Object *bxv = data;
102 Emix_Sink *sink = evas_object_data_get(bxv, "sink");
103 Evas_Object *bx = evas_object_data_get(bxv, "volume_bx");
104 Eina_Bool lock = elm_check_state_get(obj);
105 if (lock)
106 VOLSET(sink->volume.volumes[0], sink->volume,
107 sink, emix_sink_volume_set);
108 _emix_sink_volume_fill(sink, bxv, bx, lock);
109}
110
111static void
112_emix_sink_volume_fill(Emix_Sink *sink, Evas_Object *bxv, Evas_Object *bx, Eina_Bool locked)
113{
114 Evas_Object *bxhv, *sl, *ck, *lb;
115 Eina_List *sls = NULL;
116 unsigned int i;
117
118 eina_list_free(evas_object_data_get(bxv, "volumes"));
119 elm_box_clear(bx);
120
121 bxhv = elm_box_add(bx);
122 evas_object_size_hint_weight_set(bxhv, EVAS_HINT_EXPAND, 0.0);
123 evas_object_size_hint_align_set(bxhv, EVAS_HINT_FILL, 0.5);
124 elm_box_pack_end(bx, bxhv);
125 evas_object_show(bxhv);
126
127 if (locked)
128 {
129 sl = elm_slider_add(bx);
130 evas_object_data_set(bxv, "volume", sl);
131 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get());
132 elm_slider_span_size_set(sl, emix_max_volume_get() * elm_config_scale_get());
133 elm_slider_unit_format_set(sl, "%1.0f");
134 elm_slider_indicator_format_set(sl, "%1.0f");
135 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
136 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, EVAS_HINT_FILL);
137 elm_slider_value_set(sl, sink->volume.volumes[0]);
138 elm_box_pack_end(bxhv, sl);
139 evas_object_show(sl);
140 evas_object_smart_callback_add(sl, "changed", _cb_sink_volume_change, bxv);
141 elm_object_disabled_set(sl, sink->mute);
142 }
143 else
144 {
145 for (i = 0; i < sink->volume.channel_count; ++i)
146 {
147 lb = elm_label_add(bx);
148 if (!sink->volume.channel_names)
149 {
150 char buf[1024];
151 snprintf(buf, sizeof(buf), "Channel %d", i);
152 elm_object_text_set(lb, buf);
153 }
154 else
155 elm_object_text_set(lb, sink->volume.channel_names[i]);
156 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.5);
157 evas_object_size_hint_align_set(lb, 0.0, 0.5);
158 elm_box_pack_end(bxhv, lb);
159 elm_object_disabled_set(lb, sink->mute);
160 evas_object_show(lb);
161
162 sl = elm_slider_add(bx);
163 evas_object_data_set(sl, "lb", lb);
164 evas_object_data_set(sl, "channel", (uintptr_t *)(uintptr_t)i);
165 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get());
166 elm_slider_span_size_set(sl, (emix_max_volume_get()) * elm_config_scale_get());
167 elm_slider_unit_format_set(sl, "%1.0f");
168 elm_slider_indicator_format_set(sl, "%1.0f");
169 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
170 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, EVAS_HINT_FILL);
171 elm_slider_value_set(sl, sink->volume.volumes[i]);
172 elm_box_pack_end(bxhv, sl);
173 evas_object_show(sl);
174 evas_object_smart_callback_add(sl, "changed", _cb_sink_volume_channel_change, bxv);
175 elm_object_disabled_set(sl, sink->mute);
176 sls = eina_list_append(sls, sl);
177 }
178 }
179 evas_object_data_set(bxv, "volumes", sls);
180
181 bxhv = elm_box_add(bx);
182 elm_box_pack_end(bx, bxhv);
183 evas_object_show(bxhv);
184
185 ck = elm_check_add(bx);
186 evas_object_data_set(bxv, "mute", ck);
187 elm_object_text_set(ck, "Mute");
188 elm_check_state_set(ck, sink->mute);
189 elm_box_pack_end(bxhv, ck);
190 evas_object_show(ck);
191 evas_object_smart_callback_add(ck, "changed", _cb_sink_mute_change, bxv);
192
193 if (sink->volume.channel_count > 1)
194 {
195 ck = elm_check_add(bx);
196 elm_object_text_set(ck, "Lock");
197 evas_object_data_set(bxv, "lock", ck);
198 elm_check_state_set(ck, locked);
199 elm_box_pack_end(bxhv, ck);
200 evas_object_show(ck);
201 evas_object_smart_callback_add(ck, "changed", _cb_sink_lock_change, bxv);
202 }
203}
204
205
206
207static void
65_emix_sink_add(Emix_Sink *sink) 208_emix_sink_add(Emix_Sink *sink)
66{ 209{
67 Evas_Object *bxv, *bx, *lb, *ck, *sl, *hv, *sep; 210 Evas_Object *bxv, *bx, *lb, *hv, *sep;
68 const Eina_List *l; 211 const Eina_List *l;
69 Emix_Port *port; 212 Emix_Port *port;
213 Eina_Bool locked = EINA_TRUE;
214 unsigned int i;
70 215
71 bxv = elm_box_add(win); 216 bxv = elm_box_add(win);
72 sink_list = eina_list_append(sink_list, bxv); 217 sink_list = eina_list_append(sink_list, bxv);
@@ -104,34 +249,27 @@ _emix_sink_add(Emix_Sink *sink)
104 elm_box_pack_end(bx, hv); 249 elm_box_pack_end(bx, hv);
105 evas_object_show(hv); 250 evas_object_show(hv);
106 251
107 bx = elm_box_add(win); 252 /* Compare each volume level and check if they differ. If they differ unlock
253 the volume control and let user set each channel volume level */
254 for (i = 1; i < sink->volume.channel_count; ++i)
255 {
256 if (sink->volume.volumes[i - 1] != sink->volume.volumes[i])
257 {
258 locked = EINA_FALSE;
259 break;
260 }
261 }
262
263 bx = elm_box_add(bxv);
264 evas_object_data_set(bxv, "volume_bx", bx);
108 elm_box_horizontal_set(bx, EINA_TRUE); 265 elm_box_horizontal_set(bx, EINA_TRUE);
109 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); 266 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
110 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); 267 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
111 elm_box_pack_end(bxv, bx); 268 elm_box_pack_end(bxv, bx);
112 evas_object_show(bx); 269 evas_object_show(bx);
113 270
114 sl = elm_slider_add(win); 271
115 evas_object_data_set(bxv, "volume", sl); 272 _emix_sink_volume_fill(sink, bxv, bx, locked);
116 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get());
117 elm_slider_span_size_set(sl, emix_max_volume_get() * elm_config_scale_get());
118 elm_slider_unit_format_set(sl, "%1.0f");
119 elm_slider_indicator_format_set(sl, "%1.0f");
120 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.5);
121 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
122 elm_slider_value_set(sl, sink->volume.volumes[0]);
123 elm_box_pack_end(bx, sl);
124 evas_object_show(sl);
125 evas_object_smart_callback_add(sl, "changed", _cb_sink_volume_change, bxv);
126
127 ck = elm_check_add(win);
128 evas_object_data_set(bxv, "mute", ck);
129 elm_object_text_set(ck, "Mute");
130 elm_check_state_set(ck, sink->mute);
131 elm_object_disabled_set(sl, sink->mute);
132 elm_box_pack_end(bx, ck);
133 evas_object_show(ck);
134 evas_object_smart_callback_add(ck, "changed", _cb_sink_mute_change, bxv);
135 273
136 sep = elm_separator_add(win); 274 sep = elm_separator_add(win);
137 elm_separator_horizontal_set(sep, EINA_TRUE); 275 elm_separator_horizontal_set(sep, EINA_TRUE);
@@ -164,7 +302,8 @@ static void
164_emix_sink_change(Emix_Sink *sink) 302_emix_sink_change(Emix_Sink *sink)
165{ 303{
166 const Eina_List *l; 304 const Eina_List *l;
167 Evas_Object *bxv, *hv, *ck, *sl; 305 Eina_List *ll;
306 Evas_Object *bxv, *hv, *ck, *sl, *lb;
168 Emix_Port *port; 307 Emix_Port *port;
169 308
170 EINA_LIST_FOREACH(sink_list, l, bxv) 309 EINA_LIST_FOREACH(sink_list, l, bxv)
@@ -181,15 +320,35 @@ _emix_sink_change(Emix_Sink *sink)
181 _cb_sink_port_change, port); 320 _cb_sink_port_change, port);
182 if (port->active) elm_object_text_set(hv, port->description); 321 if (port->active) elm_object_text_set(hv, port->description);
183 } 322 }
184 sl = evas_object_data_get(bxv, "volume"); 323 ck = evas_object_data_get(bxv, "lock");
185 elm_slider_value_set(sl, sink->volume.volumes[0]); 324
325 if (ck && !elm_check_state_get(ck))
326 {
327 ck = evas_object_data_get(bxv, "mute");
328 elm_check_state_set(ck, sink->mute);
329 EINA_LIST_FOREACH(evas_object_data_get(bxv, "volumes"), ll, sl)
330 {
331 elm_slider_value_set(sl,
332 sink->volume.volumes[(uintptr_t)evas_object_data_get(sl, "channel")]);
333 elm_object_disabled_set(sl, sink->mute);
334 lb = evas_object_data_get(sl, "lb");
335 elm_object_disabled_set(lb, sink->mute);
336 }
337 }
338 else
339 {
340 ck = evas_object_data_get(bxv, "mute");
341 elm_check_state_set(ck, sink->mute);
342
343 sl = evas_object_data_get(bxv, "volume");
344 elm_slider_value_set(sl, sink->volume.volumes[0]);
345 elm_object_disabled_set(sl, sink->mute);
346 }
186 347
187 ck = evas_object_data_get(bxv, "mute");
188 elm_check_state_set(ck, sink->mute);
189 elm_object_disabled_set(sl, sink->mute);
190} 348}
191 349
192////////////////////////////////////////////////////////////////////////////// 350//////////////////////////////////////////////////////////////////////////////
351static void _emix_sink_input_volume_fill(Emix_Sink_Input *input, Evas_Object *bxv, Evas_Object *bx, Eina_Bool locked);
193 352
194static void 353static void
195_cb_sink_input_port_change(void *data, 354_cb_sink_input_port_change(void *data,
@@ -216,6 +375,19 @@ _cb_sink_input_volume_change(void *data,
216} 375}
217 376
218static void 377static void
378_cb_sink_input_volume_channel_change(void *data,
379 Evas_Object *obj,
380 void *event_info EINA_UNUSED)
381{
382 Evas_Object *bxv = data;
383 Emix_Sink_Input *input = evas_object_data_get(bxv, "input");
384 double vol = elm_slider_value_get(obj);
385 input->volume.volumes[(uintptr_t)evas_object_data_get(obj, "channel")] = vol;
386 elm_slider_value_set(obj, vol);
387 emix_sink_input_volume_set(input, &input->volume);
388}
389
390static void
219_cb_sink_input_volume_drag_stop(void *data, 391_cb_sink_input_volume_drag_stop(void *data,
220 Evas_Object *obj, 392 Evas_Object *obj,
221 void *event EINA_UNUSED) 393 void *event EINA_UNUSED)
@@ -227,24 +399,173 @@ _cb_sink_input_volume_drag_stop(void *data,
227} 399}
228 400
229static void 401static void
402_cb_sink_input_volume_channel_drag_stop(void *data,
403 Evas_Object *obj,
404 void *event EINA_UNUSED)
405{
406 Evas_Object *bxv = data;
407 Emix_Sink_Input *input = evas_object_data_get(bxv, "input");
408 int vol = input->volume.volumes[(uintptr_t)evas_object_data_get(obj, "channel")];
409 elm_slider_value_set(obj, vol);
410}
411
412static void
230_cb_sink_input_mute_change(void *data, 413_cb_sink_input_mute_change(void *data,
231 Evas_Object *obj, 414 Evas_Object *obj,
232 void *event_info EINA_UNUSED) 415 void *event_info EINA_UNUSED)
233{ 416{
234 Evas_Object *bxv = data; 417 Evas_Object *bxv = data;
235 Emix_Sink_Input *input = evas_object_data_get(bxv, "input"); 418 Emix_Sink_Input *input = evas_object_data_get(bxv, "input");
236 Evas_Object *sl = evas_object_data_get(bxv, "volume"); 419 Evas_Object *sl;
420 Evas_Object *lock = evas_object_data_get(bxv, "lock");
237 Eina_Bool mute = elm_check_state_get(obj); 421 Eina_Bool mute = elm_check_state_get(obj);
238 elm_object_disabled_set(sl, mute); 422 Evas_Object *lb;
423 Eina_List *l;
424
425 if (lock && !elm_check_state_get(lock))
426 {
427 EINA_LIST_FOREACH(evas_object_data_get(bxv, "volumes"), l, sl)
428 {
429 elm_object_disabled_set(sl, mute);
430 lb = evas_object_data_get(sl, "lb");
431 elm_object_disabled_set(lb, mute);
432 }
433 }
434 else
435 {
436 sl = evas_object_data_get(bxv, "volume");
437 elm_object_disabled_set(sl, mute);
438 }
239 emix_sink_input_mute_set(input, mute); 439 emix_sink_input_mute_set(input, mute);
240} 440}
241 441
242static void 442static void
443_cb_sink_input_lock_change(void *data,
444 Evas_Object *obj,
445 void *event_info EINA_UNUSED)
446{
447 Evas_Object *bxv = data;
448 Emix_Sink_Input *input = evas_object_data_get(bxv, "input");
449 Evas_Object *bx = evas_object_data_get(bxv, "volume_bx");
450 Eina_Bool lock = elm_check_state_get(obj);
451 if (lock)
452 VOLSET(input->volume.volumes[0], input->volume,
453 input, emix_sink_input_volume_set);
454 _emix_sink_input_volume_fill(input, bxv, bx, lock);
455}
456
457static void
458_emix_sink_input_volume_fill(Emix_Sink_Input *input, Evas_Object *bxv, Evas_Object *bx, Eina_Bool locked)
459{
460 Evas_Object *bxhv, *lb, *sl, *ck;
461 unsigned int i;
462 Eina_List *sls = NULL;
463
464 eina_list_free(evas_object_data_get(bxv, "volumes"));
465 elm_box_clear(bx);
466
467 bxhv = elm_box_add(bx);
468 evas_object_size_hint_weight_set(bxhv, EVAS_HINT_EXPAND, 0.0);
469 evas_object_size_hint_align_set(bxhv, EVAS_HINT_FILL, 0.5);
470 elm_box_pack_end(bx, bxhv);
471 evas_object_show(bxhv);
472
473 if (locked)
474 {
475 sl = elm_slider_add(bx);
476 evas_object_data_set(bxv, "volume", sl);
477 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get());
478 elm_slider_span_size_set(sl, (emix_max_volume_get()) * elm_config_scale_get());
479 elm_slider_unit_format_set(sl, "%1.0f");
480 elm_slider_indicator_format_set(sl, "%1.0f");
481 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.0);
482 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5);
483 elm_slider_value_set(sl, input->volume.volumes[0]);
484 elm_box_pack_end(bxhv, sl);
485 evas_object_show(sl);
486 evas_object_smart_callback_add(sl, "changed",
487 _cb_sink_input_volume_change, bxv);
488 evas_object_smart_callback_add(sl, "slider,drag,stop",
489 _cb_sink_input_volume_drag_stop, bxv);
490
491 }
492 else
493 {
494 for (i = 0; i < input->volume.channel_count; ++i)
495 {
496 lb = elm_label_add(bx);
497 if (!input->volume.channel_names)
498 {
499 char buf[1024];
500 snprintf(buf, sizeof(buf), "Channel %d", i);
501 elm_object_text_set(lb, buf);
502 }
503 else
504 elm_object_text_set(lb, input->volume.channel_names[i]);
505 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.5);
506 evas_object_size_hint_align_set(lb, 0.0, 0.5);
507 elm_box_pack_end(bxhv, lb);
508 elm_object_disabled_set(lb, input->mute);
509 evas_object_show(lb);
510
511 sl = elm_slider_add(bx);
512 evas_object_data_set(sl, "lb", lb);
513 evas_object_data_set(sl, "channel", (uintptr_t *)(uintptr_t)i);
514 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get());
515 elm_slider_span_size_set(sl, (emix_max_volume_get()) * elm_config_scale_get());
516 elm_slider_unit_format_set(sl, "%1.0f");
517 elm_slider_indicator_format_set(sl, "%1.0f");
518 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
519 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, EVAS_HINT_FILL);
520 elm_slider_value_set(sl, input->volume.volumes[i]);
521 elm_box_pack_end(bxhv, sl);
522 evas_object_show(sl);
523 evas_object_smart_callback_add(sl, "changed",
524 _cb_sink_input_volume_channel_change, bxv);
525 evas_object_smart_callback_add(sl, "slider,drag,stop",
526 _cb_sink_input_volume_channel_drag_stop, bxv);
527 elm_object_disabled_set(sl, input->mute);
528 sls = eina_list_append(sls, sl);
529 }
530 }
531 evas_object_data_set(bxv, "volumes", sls);
532
533 bxhv = elm_box_add(bx);
534 elm_box_pack_end(bx, bxhv);
535 evas_object_show(bxhv);
536
537 ck = elm_check_add(bx);
538 evas_object_data_set(bxv, "mute", ck);
539 elm_object_text_set(ck, "Mute");
540 elm_check_state_set(ck, input->mute);
541 elm_object_disabled_set(sl, input->mute);
542 elm_box_pack_end(bxhv, ck);
543 evas_object_show(ck);
544 evas_object_smart_callback_add(ck, "changed",
545 _cb_sink_input_mute_change, bxv);
546
547 if (input->volume.channel_count > 1)
548 {
549 ck = elm_check_add(bx);
550 evas_object_data_set(bxv, "lock", ck);
551 elm_object_text_set(ck, "Lock");
552 elm_check_state_set(ck, locked);
553 elm_box_pack_end(bxhv, ck);
554 evas_object_show(ck);
555 evas_object_smart_callback_add(ck, "changed",
556 _cb_sink_input_lock_change, bxv);
557 }
558}
559
560
561static void
243_emix_sink_input_add(Emix_Sink_Input *input) 562_emix_sink_input_add(Emix_Sink_Input *input)
244{ 563{
245 Evas_Object *bxv, *bx, *lb, *ck, *sl, *hv, *sep; 564 Evas_Object *bxv, *bx, *lb, *hv, *sep;
246 const Eina_List *l; 565 const Eina_List *l;
247 Emix_Sink *sink; 566 Emix_Sink *sink;
567 Eina_Bool locked = EINA_TRUE;
568 unsigned int i;
248 569
249 bxv = elm_box_add(win); 570 bxv = elm_box_add(win);
250 sink_input_list = eina_list_append(sink_input_list, bxv); 571 sink_input_list = eina_list_append(sink_input_list, bxv);
@@ -255,13 +576,13 @@ _emix_sink_input_add(Emix_Sink_Input *input)
255 bx = elm_box_add(win); 576 bx = elm_box_add(win);
256 elm_box_horizontal_set(bx, EINA_TRUE); 577 elm_box_horizontal_set(bx, EINA_TRUE);
257 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); 578 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
258 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); 579 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
259 elm_box_pack_end(bxv, bx); 580 elm_box_pack_end(bxv, bx);
260 evas_object_show(bx); 581 evas_object_show(bx);
261 582
262 lb = elm_label_add(win); 583 lb = elm_label_add(win);
263 elm_object_text_set(lb, input->name); 584 elm_object_text_set(lb, input->name);
264 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.5); 585 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.0);
265 evas_object_size_hint_align_set(lb, 0.0, 0.5); 586 evas_object_size_hint_align_set(lb, 0.0, 0.5);
266 elm_box_pack_end(bx, lb); 587 elm_box_pack_end(bx, lb);
267 evas_object_show(lb); 588 evas_object_show(lb);
@@ -283,37 +604,25 @@ _emix_sink_input_add(Emix_Sink_Input *input)
283 evas_object_show(hv); 604 evas_object_show(hv);
284 605
285 bx = elm_box_add(win); 606 bx = elm_box_add(win);
607 evas_object_data_set(bxv, "volume_bx", bx);
286 elm_box_horizontal_set(bx, EINA_TRUE); 608 elm_box_horizontal_set(bx, EINA_TRUE);
287 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); 609 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
288 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); 610 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
289 elm_box_pack_end(bxv, bx); 611 elm_box_pack_end(bxv, bx);
290 evas_object_show(bx); 612 evas_object_show(bx);
291 613
292 sl = elm_slider_add(win); 614 /* Compare each volume level and check if they differ. If they differ unlock
293 evas_object_data_set(bxv, "volume", sl); 615 the volume control and let user set each channel volume level */
294 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get()); 616 for (i = 1; i < input->volume.channel_count; ++i)
295 elm_slider_span_size_set(sl, (emix_max_volume_get()) * elm_config_scale_get()); 617 {
296 elm_slider_unit_format_set(sl, "%1.0f"); 618 if (input->volume.volumes[i - 1] != input->volume.volumes[i])
297 elm_slider_indicator_format_set(sl, "%1.0f"); 619 {
298 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.5); 620 locked = EINA_FALSE;
299 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5); 621 break;
300 elm_slider_value_set(sl, input->volume.volumes[0]); 622 }
301 elm_box_pack_end(bx, sl); 623 }
302 evas_object_show(sl); 624
303 evas_object_smart_callback_add(sl, "changed", 625 _emix_sink_input_volume_fill(input, bxv, bx, locked);
304 _cb_sink_input_volume_change, bxv);
305 evas_object_smart_callback_add(sl, "slider,drag,stop",
306 _cb_sink_input_volume_drag_stop, bxv);
307
308 ck = elm_check_add(win);
309 evas_object_data_set(bxv, "mute", ck);
310 elm_object_text_set(ck, "Mute");
311 elm_check_state_set(ck, input->mute);
312 elm_object_disabled_set(sl, input->mute);
313 elm_box_pack_end(bx, ck);
314 evas_object_show(ck);
315 evas_object_smart_callback_add(ck, "changed",
316 _cb_sink_input_mute_change, bxv);
317 626
318 sep = elm_separator_add(win); 627 sep = elm_separator_add(win);
319 elm_separator_horizontal_set(sep, EINA_TRUE); 628 elm_separator_horizontal_set(sep, EINA_TRUE);
@@ -346,7 +655,8 @@ static void
346_emix_sink_input_change(Emix_Sink_Input *input) 655_emix_sink_input_change(Emix_Sink_Input *input)
347{ 656{
348 const Eina_List *l; 657 const Eina_List *l;
349 Evas_Object *bxv, *hv, *ck, *sl; 658 Eina_List *ll;
659 Evas_Object *bxv, *hv, *ck, *sl, *lb;
350 Emix_Sink *sink; 660 Emix_Sink *sink;
351 661
352 EINA_LIST_FOREACH(sink_input_list, l, bxv) 662 EINA_LIST_FOREACH(sink_input_list, l, bxv)
@@ -363,15 +673,35 @@ _emix_sink_input_change(Emix_Sink_Input *input)
363 _cb_sink_input_port_change, sink); 673 _cb_sink_input_port_change, sink);
364 if (input->sink == sink) elm_object_text_set(hv, sink->name); 674 if (input->sink == sink) elm_object_text_set(hv, sink->name);
365 } 675 }
366 sl = evas_object_data_get(bxv, "volume");
367 elm_slider_value_set(sl, input->volume.volumes[0]);
368 676
369 ck = evas_object_data_get(bxv, "mute"); 677 ck = evas_object_data_get(bxv, "lock");
370 elm_check_state_set(ck, input->mute); 678
371 elm_object_disabled_set(sl, input->mute); 679 if (ck && !elm_check_state_get(ck))
680 {
681 ck = evas_object_data_get(bxv, "mute");
682 elm_check_state_set(ck, input->mute);
683 EINA_LIST_FOREACH(evas_object_data_get(bxv, "volumes"), ll, sl)
684 {
685 elm_slider_value_set(sl,
686 input->volume.volumes[(uintptr_t)evas_object_data_get(sl, "channel")]);
687 elm_object_disabled_set(sl, input->mute);
688 lb = evas_object_data_get(sl, "lb");
689 elm_object_disabled_set(lb, input->mute);
690 }
691 }
692 else
693 {
694 ck = evas_object_data_get(bxv, "mute");
695 elm_check_state_set(ck, input->mute);
696
697 sl = evas_object_data_get(bxv, "volume");
698 elm_slider_value_set(sl, input->volume.volumes[0]);
699 elm_object_disabled_set(sl, input->mute);
700 }
372} 701}
373 702
374////////////////////////////////////////////////////////////////////////////// 703//////////////////////////////////////////////////////////////////////////////
704static void _emix_source_volume_fill(Emix_Source *source, Evas_Object *bxv, Evas_Object *bx, Eina_Bool locked);
375 705
376static void 706static void
377_cb_source_volume_change(void *data, 707_cb_source_volume_change(void *data,
@@ -386,6 +716,20 @@ _cb_source_volume_change(void *data,
386} 716}
387 717
388static void 718static void
719_cb_source_volume_channel_change(void *data,
720 Evas_Object *obj,
721 void *event_info EINA_UNUSED)
722{
723 Evas_Object *bxv = data;
724 Emix_Source *source = evas_object_data_get(bxv, "source");
725 double vol = elm_slider_value_get(obj);
726 source->volume.volumes[(uintptr_t)evas_object_data_get(obj, "channel")] = vol;
727 elm_slider_value_set(obj, vol);
728 emix_source_volume_set(source, &source->volume);
729}
730
731
732static void
389_cb_source_volume_drag_stop(void *data, 733_cb_source_volume_drag_stop(void *data,
390 Evas_Object *obj, 734 Evas_Object *obj,
391 void *event EINA_UNUSED) 735 void *event EINA_UNUSED)
@@ -397,22 +741,170 @@ _cb_source_volume_drag_stop(void *data,
397} 741}
398 742
399static void 743static void
744_cb_source_volume_channel_drag_stop(void *data,
745 Evas_Object *obj,
746 void *event EINA_UNUSED)
747{
748 Evas_Object *bxv = data;
749 Emix_Source *source = evas_object_data_get(bxv, "source");
750 int vol = source->volume.volumes[(uintptr_t)evas_object_data_get(obj, "channel")];
751 elm_slider_value_set(obj, vol);
752}
753
754static void
400_cb_source_mute_change(void *data, 755_cb_source_mute_change(void *data,
401 Evas_Object *obj, 756 Evas_Object *obj,
402 void *event_info EINA_UNUSED) 757 void *event_info EINA_UNUSED)
403{ 758{
404 Evas_Object *bxv = data; 759 Evas_Object *bxv = data;
405 Emix_Source *source = evas_object_data_get(bxv, "source"); 760 Emix_Source *source = evas_object_data_get(bxv, "source");
406 Evas_Object *sl = evas_object_data_get(bxv, "volume"); 761 Evas_Object *sl;
762 Evas_Object *lock = evas_object_data_get(bxv, "lock");
407 Eina_Bool mute = elm_check_state_get(obj); 763 Eina_Bool mute = elm_check_state_get(obj);
408 elm_object_disabled_set(sl, mute); 764 Evas_Object *lb;
765 Eina_List *l;
766
767 if (lock && !elm_check_state_get(lock))
768 {
769 EINA_LIST_FOREACH(evas_object_data_get(bxv, "volumes"), l, sl)
770 {
771 elm_object_disabled_set(sl, mute);
772 lb = evas_object_data_get(sl, "lb");
773 elm_object_disabled_set(lb, mute);
774 }
775 }
776 else
777 {
778 sl = evas_object_data_get(bxv, "volume");
779 elm_object_disabled_set(sl, mute);
780 }
409 emix_source_mute_set(source, mute); 781 emix_source_mute_set(source, mute);
410} 782}
411 783
412static void 784static void
785_cb_source_lock_change(void *data,
786 Evas_Object *obj,
787 void *event_info EINA_UNUSED)
788{
789 Evas_Object *bxv = data;
790 Emix_Source *source = evas_object_data_get(bxv, "source");
791 Evas_Object *bx = evas_object_data_get(bxv, "volume_bx");
792 Eina_Bool lock = elm_check_state_get(obj);
793 if (lock)
794 VOLSET(source->volume.volumes[0], source->volume,
795 source, emix_source_volume_set);
796 _emix_source_volume_fill(source, bxv, bx, lock);
797}
798
799static void
800_emix_source_volume_fill(Emix_Source *source, Evas_Object *bxv, Evas_Object *bx, Eina_Bool locked)
801{
802 Evas_Object *bxhv, *lb, *sl, *ck;
803 Eina_List *sls = NULL;
804 unsigned int i;
805
806 eina_list_free(evas_object_data_get(bxv, "volumes"));
807 elm_box_clear(bx);
808
809 bxhv = elm_box_add(bx);
810 evas_object_size_hint_weight_set(bxhv, EVAS_HINT_EXPAND, 0.0);
811 evas_object_size_hint_align_set(bxhv, EVAS_HINT_FILL, 0.5);
812 elm_box_pack_end(bx, bxhv);
813 evas_object_show(bxhv);
814
815 if (locked)
816 {
817 sl = elm_slider_add(bx);
818 evas_object_data_set(bxv, "volume", sl);
819 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get());
820 elm_slider_span_size_set(sl, (emix_max_volume_get()) * elm_config_scale_get());
821 elm_slider_unit_format_set(sl, "%1.0f");
822 elm_slider_indicator_format_set(sl, "%1.0f");
823 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
824 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, EVAS_HINT_FILL);
825 elm_slider_value_set(sl, source->volume.volumes[0]);
826 elm_box_pack_end(bxhv, sl);
827 evas_object_show(sl);
828 evas_object_smart_callback_add(sl, "changed",
829 _cb_source_volume_change, bxv);
830 evas_object_smart_callback_add(sl, "slider,drag,stop",
831 _cb_source_volume_drag_stop, bxv);
832 elm_object_disabled_set(sl, source->mute);
833 }
834 else
835 {
836 for (i = 0; i < source->volume.channel_count; ++i)
837 {
838 lb = elm_label_add(bx);
839 if (!source->volume.channel_names)
840 {
841 char buf[1024];
842 snprintf(buf, sizeof(buf), "Channel %d", i);
843 elm_object_text_set(lb, buf);
844 }
845 else
846 elm_object_text_set(lb, source->volume.channel_names[i]);
847 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.5);
848 evas_object_size_hint_align_set(lb, 0.0, 0.5);
849 elm_box_pack_end(bxhv, lb);
850 elm_object_disabled_set(lb, source->mute);
851 evas_object_show(lb);
852
853 sl = elm_slider_add(bx);
854 evas_object_data_set(sl, "lb", lb);
855 evas_object_data_set(sl, "channel", (uintptr_t *)(uintptr_t)i);
856 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get());
857 elm_slider_span_size_set(sl, (emix_max_volume_get()) * elm_config_scale_get());
858 elm_slider_unit_format_set(sl, "%1.0f");
859 elm_slider_indicator_format_set(sl, "%1.0f");
860 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
861 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, EVAS_HINT_FILL);
862 elm_slider_value_set(sl, source->volume.volumes[i]);
863 elm_box_pack_end(bxhv, sl);
864 evas_object_show(sl);
865 evas_object_smart_callback_add(sl, "changed",
866 _cb_source_volume_channel_change, bxv);
867 evas_object_smart_callback_add(sl, "slider,drag,stop",
868 _cb_source_volume_channel_drag_stop, bxv);
869 elm_object_disabled_set(sl, source->mute);
870 sls = eina_list_append(sls, sl);
871 }
872 }
873 evas_object_data_set(bxv, "volumes", sls);
874
875 bxhv = elm_box_add(bx);
876 elm_box_pack_end(bx, bxhv);
877 evas_object_show(bxhv);
878
879 ck = elm_check_add(bx);
880 evas_object_data_set(bxv, "mute", ck);
881 elm_object_text_set(ck, "Mute");
882 elm_check_state_set(ck, source->mute);
883 elm_box_pack_end(bxhv, ck);
884 evas_object_show(ck);
885 evas_object_smart_callback_add(ck, "changed",
886 _cb_source_mute_change, bxv);
887
888 if (source->volume.channel_count > 1)
889 {
890 ck = elm_check_add(bx);
891 evas_object_data_set(bxv, "lock", ck);
892 elm_object_text_set(ck, "Lock");
893 elm_check_state_set(ck, locked);
894 elm_box_pack_end(bxhv, ck);
895 evas_object_show(ck);
896 evas_object_smart_callback_add(ck, "changed",
897 _cb_source_lock_change, bxv);
898 }
899}
900
901
902static void
413_emix_source_add(Emix_Source *source) 903_emix_source_add(Emix_Source *source)
414{ 904{
415 Evas_Object *bxv, *bx, *lb, *ck, *sl, *sep; 905 Evas_Object *bxv, *bx, *lb, *sep;
906 unsigned int i;
907 Eina_Bool locked = EINA_TRUE;
416 908
417 bxv = elm_box_add(win); 909 bxv = elm_box_add(win);
418 source_list = eina_list_append(source_list, bxv); 910 source_list = eina_list_append(source_list, bxv);
@@ -429,43 +921,32 @@ _emix_source_add(Emix_Source *source)
429 921
430 lb = elm_label_add(win); 922 lb = elm_label_add(win);
431 elm_object_text_set(lb, source->name); 923 elm_object_text_set(lb, source->name);
432 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.5); 924 evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.0);
433 evas_object_size_hint_align_set(lb, 0.0, 0.5); 925 evas_object_size_hint_align_set(lb, 0.0, 0.5);
434 elm_box_pack_end(bx, lb); 926 elm_box_pack_end(bx, lb);
435 evas_object_show(lb); 927 evas_object_show(lb);
436 928
437 bx = elm_box_add(win); 929 bx = elm_box_add(win);
930 evas_object_data_set(bxv, "volume_bx", bx);
438 elm_box_horizontal_set(bx, EINA_TRUE); 931 elm_box_horizontal_set(bx, EINA_TRUE);
439 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); 932 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0);
440 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); 933 evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.5);
441 elm_box_pack_end(bxv, bx); 934 elm_box_pack_end(bxv, bx);
442 evas_object_show(bx); 935 evas_object_show(bx);
443 936
444 sl = elm_slider_add(win); 937 /* Compare each volume level and check if they differ. If they differ unlock
445 evas_object_data_set(bxv, "volume", sl); 938 the volume control and let user set each channel volume level */
446 elm_slider_min_max_set(sl, 0.0, emix_max_volume_get()); 939 for (i = 1; i < source->volume.channel_count; ++i)
447 elm_slider_span_size_set(sl, (emix_max_volume_get()) * elm_config_scale_get()); 940 {
448 elm_slider_unit_format_set(sl, "%1.0f"); 941 if (source->volume.volumes[i - 1] != source->volume.volumes[i])
449 elm_slider_indicator_format_set(sl, "%1.0f"); 942 {
450 evas_object_size_hint_weight_set(sl, EVAS_HINT_EXPAND, 0.5); 943 locked = EINA_FALSE;
451 evas_object_size_hint_align_set(sl, EVAS_HINT_FILL, 0.5); 944 break;
452 elm_slider_value_set(sl, source->volume.volumes[0]); 945 }
453 elm_box_pack_end(bx, sl); 946 }
454 evas_object_show(sl); 947
455 evas_object_smart_callback_add(sl, "changed", 948 _emix_source_volume_fill(source, bxv, bx, locked);
456 _cb_source_volume_change, bxv); 949
457 evas_object_smart_callback_add(sl, "slider,drag,stop",
458 _cb_source_volume_drag_stop, bxv);
459
460 ck = elm_check_add(win);
461 evas_object_data_set(bxv, "mute", ck);
462 elm_object_text_set(ck, "Mute");
463 elm_check_state_set(ck, source->mute);
464 elm_object_disabled_set(sl, source->mute);
465 elm_box_pack_end(bx, ck);
466 evas_object_show(ck);
467 evas_object_smart_callback_add(ck, "changed",
468 _cb_source_mute_change, bxv);
469 950
470 sep = elm_separator_add(win); 951 sep = elm_separator_add(win);
471 elm_separator_horizontal_set(sep, EINA_TRUE); 952 elm_separator_horizontal_set(sep, EINA_TRUE);
@@ -498,19 +979,39 @@ static void
498_emix_source_change(Emix_Source *source) 979_emix_source_change(Emix_Source *source)
499{ 980{
500 const Eina_List *l; 981 const Eina_List *l;
501 Evas_Object *bxv, *ck, *sl; 982 Eina_List *ll;
983 Evas_Object *bxv, *ck, *sl, *lb;
502 984
503 EINA_LIST_FOREACH(source_list, l, bxv) 985 EINA_LIST_FOREACH(source_list, l, bxv)
504 { 986 {
505 if (evas_object_data_get(bxv, "source") == source) break; 987 if (evas_object_data_get(bxv, "source") == source) break;
506 } 988 }
507 if (!l) return; 989 if (!l) return;
508 sl = evas_object_data_get(bxv, "volume");
509 elm_slider_value_set(sl, source->volume.volumes[0]);
510 990
511 ck = evas_object_data_get(bxv, "mute"); 991 ck = evas_object_data_get(bxv, "lock");
512 elm_check_state_set(ck, source->mute); 992
513 elm_object_disabled_set(sl, source->mute); 993 if (ck && !elm_check_state_get(ck))
994 {
995 ck = evas_object_data_get(bxv, "mute");
996 elm_check_state_set(ck, source->mute);
997 EINA_LIST_FOREACH(evas_object_data_get(bxv, "volumes"), ll, sl)
998 {
999 elm_slider_value_set(sl,
1000 source->volume.volumes[(uintptr_t)evas_object_data_get(sl, "channel")]);
1001 elm_object_disabled_set(sl, source->mute);
1002 lb = evas_object_data_get(sl, "lb");
1003 elm_object_disabled_set(lb, source->mute);
1004 }
1005 }
1006 else
1007 {
1008 ck = evas_object_data_get(bxv, "mute");
1009 elm_check_state_set(ck, source->mute);
1010
1011 sl = evas_object_data_get(bxv, "volume");
1012 elm_slider_value_set(sl, source->volume.volumes[0]);
1013 elm_object_disabled_set(sl, source->mute);
1014 }
514} 1015}
515 1016
516////////////////////////////////////////////////////////////////////////////// 1017//////////////////////////////////////////////////////////////////////////////
diff --git a/src/modules/mixer/gadget/backend.c b/src/modules/mixer/gadget/backend.c
index 0f9b469c1..59e7d7acb 100644
--- a/src/modules/mixer/gadget/backend.c
+++ b/src/modules/mixer/gadget/backend.c
@@ -158,7 +158,7 @@ _volume_increase_cb(E_Object *obj EINA_UNUSED, const char *params EINA_UNUSED)
158 volume.volumes[i] = s->volume.volumes[i]; 158 volume.volumes[i] = s->volume.volumes[i];
159 } 159 }
160 160
161 emix_sink_volume_set(s, volume); 161 emix_sink_volume_set(s, &volume);
162 emix_config_save_state_get(); 162 emix_config_save_state_get();
163 if (emix_config_save_get()) e_config_save_queue(); 163 if (emix_config_save_get()) e_config_save_queue();
164 free(volume.volumes); 164 free(volume.volumes);
@@ -184,7 +184,7 @@ _volume_decrease_cb(E_Object *obj EINA_UNUSED, const char *params EINA_UNUSED)
184 volume.volumes[i] = s->volume.volumes[i]; 184 volume.volumes[i] = s->volume.volumes[i];
185 } 185 }
186 186
187 emix_sink_volume_set((Emix_Sink *)_sink_default, volume); 187 emix_sink_volume_set((Emix_Sink *)_sink_default, &volume);
188 emix_config_save_state_get(); 188 emix_config_save_state_get();
189 if (emix_config_save_get()) e_config_save_queue(); 189 if (emix_config_save_get()) e_config_save_queue();
190 free(volume.volumes); 190 free(volume.volumes);
diff --git a/src/modules/mixer/lib/backends/alsa/alsa.c b/src/modules/mixer/lib/backends/alsa/alsa.c
index e09227db6..0d12d03a9 100644
--- a/src/modules/mixer/lib/backends/alsa/alsa.c
+++ b/src/modules/mixer/lib/backends/alsa/alsa.c
@@ -408,25 +408,25 @@ _alsa_sources_mute_set(Emix_Source *source, Eina_Bool mute)
408} 408}
409 409
410static void 410static void
411_alsa_sources_volume_set(Emix_Source *source, Emix_Volume v) 411_alsa_sources_volume_set(Emix_Source *source, Emix_Volume *v)
412{ 412{
413 Alsa_Emix_Source *s = (Alsa_Emix_Source*) source; 413 Alsa_Emix_Source *s = (Alsa_Emix_Source*) source;
414 unsigned int i; 414 unsigned int i;
415 snd_mixer_elem_t *elem; 415 snd_mixer_elem_t *elem;
416 416
417 EINA_SAFETY_ON_FALSE_RETURN((ctx && source)); 417 EINA_SAFETY_ON_FALSE_RETURN((ctx && source && v));
418 418
419 if (v.channel_count != eina_list_count(s->channels)) 419 if (v->channel_count != eina_list_count(s->channels))
420 { 420 {
421 ERR("Volume struct doesn't have the same length than the channels"); 421 ERR("Volume struct doesn't have the same length than the channels");
422 return; 422 return;
423 } 423 }
424 424
425 for (i = 0; i < v.channel_count; i++ ) 425 for (i = 0; i < v->channel_count; i++ )
426 { 426 {
427 elem = eina_list_nth(s->channels, i); 427 elem = eina_list_nth(s->channels, i);
428 _alsa_channel_volume_set(elem, v.volumes[i], EINA_FALSE); 428 _alsa_channel_volume_set(elem, v->volumes[i], EINA_FALSE);
429 s->source.volume.volumes[i] = v.volumes[i]; 429 s->source.volume.volumes[i] = v->volumes[i];
430 } 430 }
431 if (ctx->cb) 431 if (ctx->cb)
432 ctx->cb((void *)ctx->userdata, EMIX_SOURCE_CHANGED_EVENT, 432 ctx->cb((void *)ctx->userdata, EMIX_SOURCE_CHANGED_EVENT,
@@ -480,25 +480,25 @@ _alsa_sink_mute_set(Emix_Sink *sink, Eina_Bool mute)
480} 480}
481 481
482static void 482static void
483_alsa_sink_volume_set(Emix_Sink *sink, Emix_Volume v) 483_alsa_sink_volume_set(Emix_Sink *sink, Emix_Volume *v)
484{ 484{
485 Alsa_Emix_Sink *s = (Alsa_Emix_Sink *)sink; 485 Alsa_Emix_Sink *s = (Alsa_Emix_Sink *)sink;
486 unsigned int i; 486 unsigned int i;
487 snd_mixer_elem_t *elem; 487 snd_mixer_elem_t *elem;
488 488
489 EINA_SAFETY_ON_FALSE_RETURN((ctx && sink)); 489 EINA_SAFETY_ON_FALSE_RETURN((ctx && sink && v));
490 490
491 if (v.channel_count != eina_list_count(s->channels)) 491 if (v->channel_count != eina_list_count(s->channels))
492 { 492 {
493 ERR("Volume struct doesn't have the same length than the channels"); 493 ERR("Volume struct doesn't have the same length than the channels");
494 return; 494 return;
495 } 495 }
496 496
497 for (i = 0; i < v.channel_count; i++ ) 497 for (i = 0; i < v->channel_count; i++ )
498 { 498 {
499 elem = eina_list_nth(s->channels, i); 499 elem = eina_list_nth(s->channels, i);
500 _alsa_channel_volume_set(elem, v.volumes[i], EINA_FALSE); 500 _alsa_channel_volume_set(elem, v->volumes[i], EINA_FALSE);
501 s->sink.volume.volumes[i] = v.volumes[i]; 501 s->sink.volume.volumes[i] = v->volumes[i];
502 } 502 }
503 if (ctx->cb) 503 if (ctx->cb)
504 ctx->cb((void *)ctx->userdata, EMIX_SINK_CHANGED_EVENT, 504 ctx->cb((void *)ctx->userdata, EMIX_SINK_CHANGED_EVENT,
diff --git a/src/modules/mixer/lib/backends/pulseaudio/pulse.c b/src/modules/mixer/lib/backends/pulseaudio/pulse.c
index 5c58749d1..8cbb1f4f9 100644
--- a/src/modules/mixer/lib/backends/pulseaudio/pulse.c
+++ b/src/modules/mixer/lib/backends/pulseaudio/pulse.c
@@ -66,14 +66,14 @@ static Context *ctx = NULL;
66extern pa_mainloop_api functable; 66extern pa_mainloop_api functable;
67 67
68static pa_cvolume 68static pa_cvolume
69_emix_volume_convert(const Emix_Volume volume) 69_emix_volume_convert(const Emix_Volume *volume)
70{ 70{
71 pa_cvolume vol; 71 pa_cvolume vol;
72 unsigned int i; 72 unsigned int i;
73 73
74 vol.channels = volume.channel_count; 74 vol.channels = volume->channel_count;
75 for (i = 0; i < volume.channel_count; i++) 75 for (i = 0; i < volume->channel_count; i++)
76 vol.values[i] = INT_TO_PA_VOLUME(volume.volumes[i]); 76 vol.values[i] = INT_TO_PA_VOLUME(volume->volumes[i]);
77 return vol; 77 return vol;
78} 78}
79 79
@@ -98,6 +98,7 @@ _pa_cvolume_convert(const pa_cvolume *volume, Emix_Volume *vol)
98static void 98static void
99_sink_del(Sink *sink) 99_sink_del(Sink *sink)
100{ 100{
101 unsigned int i;
101 Emix_Port *port; 102 Emix_Port *port;
102 103
103 EINA_SAFETY_ON_NULL_RETURN(sink); 104 EINA_SAFETY_ON_NULL_RETURN(sink);
@@ -109,6 +110,9 @@ _sink_del(Sink *sink)
109 } 110 }
110 111
111 free(sink->base.volume.volumes); 112 free(sink->base.volume.volumes);
113 for(i = 0; i < sink->base.volume.channel_count; ++i)
114 eina_stringshare_del(sink->base.volume.channel_names[i]);
115 free(sink->base.volume.channel_names);
112 eina_stringshare_del(sink->base.name); 116 eina_stringshare_del(sink->base.name);
113 free(sink); 117 free(sink);
114} 118}
@@ -116,9 +120,13 @@ _sink_del(Sink *sink)
116static void 120static void
117_sink_input_del(Sink_Input *input) 121_sink_input_del(Sink_Input *input)
118{ 122{
123 unsigned int i;
119 EINA_SAFETY_ON_NULL_RETURN(input); 124 EINA_SAFETY_ON_NULL_RETURN(input);
120 125
121 free(input->base.volume.volumes); 126 free(input->base.volume.volumes);
127 for(i = 0; i < input->base.volume.channel_count; ++i)
128 eina_stringshare_del(input->base.volume.channel_names[i]);
129 free(input->base.volume.channel_names);
122 eina_stringshare_del(input->base.name); 130 eina_stringshare_del(input->base.name);
123 eina_stringshare_del(input->icon); 131 eina_stringshare_del(input->icon);
124 free(input); 132 free(input);
@@ -127,9 +135,13 @@ _sink_input_del(Sink_Input *input)
127static void 135static void
128_source_del(Source *source) 136_source_del(Source *source)
129{ 137{
138 unsigned int i;
130 EINA_SAFETY_ON_NULL_RETURN(source); 139 EINA_SAFETY_ON_NULL_RETURN(source);
131 140
132 free(source->base.volume.volumes); 141 free(source->base.volume.volumes);
142 for(i = 0; i < source->base.volume.channel_count; ++i)
143 eina_stringshare_del(source->base.volume.channel_names[i]);
144 free(source->base.volume.channel_names);
133 eina_stringshare_del(source->base.name); 145 eina_stringshare_del(source->base.name);
134 free(source); 146 free(source);
135} 147}
@@ -177,6 +189,9 @@ _sink_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
177 sink->idx = info->index; 189 sink->idx = info->index;
178 sink->base.name = eina_stringshare_add(info->description); 190 sink->base.name = eina_stringshare_add(info->description);
179 _pa_cvolume_convert(&info->volume, &sink->base.volume); 191 _pa_cvolume_convert(&info->volume, &sink->base.volume);
192 sink->base.volume.channel_names = calloc(sink->base.volume.channel_count, sizeof(Emix_Channel));
193 for (i = 0; i < sink->base.volume.channel_count; ++i)
194 sink->base.volume.channel_names[i] = eina_stringshare_add(pa_channel_position_to_pretty_string(info->channel_map.map[i]));
180 sink->base.mute = !!info->mute; 195 sink->base.mute = !!info->mute;
181 196
182 for (i = 0; i < info->n_ports; i++) 197 for (i = 0; i < info->n_ports; i++)
@@ -238,7 +253,18 @@ _sink_changed_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
238 EINA_SAFETY_ON_NULL_RETURN(sink); 253 EINA_SAFETY_ON_NULL_RETURN(sink);
239 254
240 eina_stringshare_replace(&sink->base.name, info->description); 255 eina_stringshare_replace(&sink->base.name, info->description);
256
257 if (sink->base.volume.channel_count != info->volume.channels)
258 {
259 for (i = 0; i < sink->base.volume.channel_count; ++i)
260 eina_stringshare_del(sink->base.volume.channel_names[i]);
261 free(sink->base.volume.channel_names);
262 sink->base.volume.channel_names = calloc(info->volume.channels, sizeof(Emix_Channel));
263 }
241 _pa_cvolume_convert(&info->volume, &sink->base.volume); 264 _pa_cvolume_convert(&info->volume, &sink->base.volume);
265 for (i = 0; i < sink->base.volume.channel_count; ++i)
266 eina_stringshare_replace(&sink->base.volume.channel_names[i],
267 pa_channel_position_to_pretty_string(info->channel_map.map[i]));
242 sink->base.mute = !!info->mute; 268 sink->base.mute = !!info->mute;
243 269
244 if (sink->base.ports) 270 if (sink->base.ports)
@@ -335,6 +361,7 @@ _sink_input_cb(pa_context *c EINA_UNUSED, const pa_sink_input_info *info,
335 Eina_List *l; 361 Eina_List *l;
336 Sink *s; 362 Sink *s;
337 const char *t; 363 const char *t;
364 unsigned int i;
338 EINA_SAFETY_ON_NULL_RETURN(ctx); 365 EINA_SAFETY_ON_NULL_RETURN(ctx);
339 366
340 if (eol < 0) 367 if (eol < 0)
@@ -374,6 +401,9 @@ _sink_input_cb(pa_context *c EINA_UNUSED, const pa_sink_input_info *info,
374 input->base.name = eina_stringshare_add(eina_strbuf_string_get(input_name)); 401 input->base.name = eina_stringshare_add(eina_strbuf_string_get(input_name));
375 eina_strbuf_free(input_name); 402 eina_strbuf_free(input_name);
376 _pa_cvolume_convert(&info->volume, &input->base.volume); 403 _pa_cvolume_convert(&info->volume, &input->base.volume);
404 input->base.volume.channel_names = calloc(input->base.volume.channel_count, sizeof(Emix_Channel));
405 for (i = 0; i < input->base.volume.channel_count; ++i)
406 input->base.volume.channel_names[i] = eina_stringshare_add(pa_channel_position_to_pretty_string(info->channel_map.map[i]));
377 input->base.mute = !!info->mute; 407 input->base.mute = !!info->mute;
378 EINA_LIST_FOREACH(ctx->sinks, l, s) 408 EINA_LIST_FOREACH(ctx->sinks, l, s)
379 { 409 {
@@ -398,10 +428,11 @@ _sink_input_changed_cb(pa_context *c EINA_UNUSED,
398 const pa_sink_input_info *info, int eol, 428 const pa_sink_input_info *info, int eol,
399 void *userdata EINA_UNUSED) 429 void *userdata EINA_UNUSED)
400{ 430{
401 Sink_Input *input = NULL, *i; 431 Sink_Input *input = NULL, *si;
402 Sink *s = NULL; 432 Sink *s = NULL;
403 Eina_List *l; 433 Eina_List *l;
404 const char *t; 434 const char *t;
435 unsigned int i;
405 436
406 EINA_SAFETY_ON_NULL_RETURN(ctx); 437 EINA_SAFETY_ON_NULL_RETURN(ctx);
407 if (eol < 0) 438 if (eol < 0)
@@ -416,11 +447,11 @@ _sink_input_changed_cb(pa_context *c EINA_UNUSED,
416 if (eol > 0) 447 if (eol > 0)
417 return; 448 return;
418 449
419 EINA_LIST_FOREACH(ctx->inputs, l, i) 450 EINA_LIST_FOREACH(ctx->inputs, l, si)
420 { 451 {
421 if (i->idx == (int)info->index) 452 if (si->idx == (int)info->index)
422 { 453 {
423 input = i; 454 input = si;
424 break; 455 break;
425 } 456 }
426 } 457 }
@@ -434,7 +465,18 @@ _sink_input_changed_cb(pa_context *c EINA_UNUSED,
434 ctx->inputs = eina_list_append(ctx->inputs, input); 465 ctx->inputs = eina_list_append(ctx->inputs, input);
435 } 466 }
436 input->idx = info->index; 467 input->idx = info->index;
468 if (input->base.volume.channel_count != info->volume.channels)
469 {
470 for (i = 0; i < input->base.volume.channel_count; ++i)
471 eina_stringshare_del(input->base.volume.channel_names[i]);
472 free(input->base.volume.channel_names);
473 input->base.volume.channel_names = calloc(info->volume.channels, sizeof(Emix_Channel));
474 }
437 _pa_cvolume_convert(&info->volume, &input->base.volume); 475 _pa_cvolume_convert(&info->volume, &input->base.volume);
476 for (i = 0; i < input->base.volume.channel_count; ++i)
477 eina_stringshare_replace(&input->base.volume.channel_names[i],
478 pa_channel_position_to_pretty_string(info->channel_map.map[i]));
479
438 input->base.mute = !!info->mute; 480 input->base.mute = !!info->mute;
439 481
440 EINA_LIST_FOREACH(ctx->sinks, l, s) 482 EINA_LIST_FOREACH(ctx->sinks, l, s)
@@ -482,6 +524,7 @@ _source_cb(pa_context *c EINA_UNUSED, const pa_source_info *info,
482 int eol, void *userdata EINA_UNUSED) 524 int eol, void *userdata EINA_UNUSED)
483{ 525{
484 Source *source; 526 Source *source;
527 unsigned int i;
485 EINA_SAFETY_ON_NULL_RETURN(ctx); 528 EINA_SAFETY_ON_NULL_RETURN(ctx);
486 529
487 if (eol < 0) 530 if (eol < 0)
@@ -502,6 +545,9 @@ _source_cb(pa_context *c EINA_UNUSED, const pa_source_info *info,
502 source->idx = info->index; 545 source->idx = info->index;
503 source->base.name = eina_stringshare_add(info->name); 546 source->base.name = eina_stringshare_add(info->name);
504 _pa_cvolume_convert(&info->volume, &source->base.volume); 547 _pa_cvolume_convert(&info->volume, &source->base.volume);
548 source->base.volume.channel_names = calloc(source->base.volume.channel_count, sizeof(Emix_Channel));
549 for (i = 0; i < source->base.volume.channel_count; ++i)
550 source->base.volume.channel_names[i] = eina_stringshare_add(pa_channel_position_to_pretty_string(info->channel_map.map[i]));
505 source->base.mute = !!info->mute; 551 source->base.mute = !!info->mute;
506 552
507 ctx->sources = eina_list_append(ctx->sources, source); 553 ctx->sources = eina_list_append(ctx->sources, source);
@@ -517,6 +563,7 @@ _source_changed_cb(pa_context *c EINA_UNUSED,
517{ 563{
518 Source *source = NULL, *s; 564 Source *source = NULL, *s;
519 Eina_List *l; 565 Eina_List *l;
566 unsigned int i;
520 EINA_SAFETY_ON_NULL_RETURN(ctx); 567 EINA_SAFETY_ON_NULL_RETURN(ctx);
521 568
522 if (eol < 0) 569 if (eol < 0)
@@ -549,7 +596,17 @@ _source_changed_cb(pa_context *c EINA_UNUSED,
549 ctx->sources = eina_list_append(ctx->sources, source); 596 ctx->sources = eina_list_append(ctx->sources, source);
550 } 597 }
551 source->idx= info->index; 598 source->idx= info->index;
599 if (source->base.volume.channel_count != info->volume.channels)
600 {
601 for (i = 0; i < source->base.volume.channel_count; ++i)
602 eina_stringshare_del(source->base.volume.channel_names[i]);
603 free(source->base.volume.channel_names);
604 source->base.volume.channel_names = calloc(info->volume.channels, sizeof(Emix_Channel));
605 }
552 _pa_cvolume_convert(&info->volume, &source->base.volume); 606 _pa_cvolume_convert(&info->volume, &source->base.volume);
607 for (i = 0; i < source->base.volume.channel_count; ++i)
608 eina_stringshare_replace(&source->base.volume.channel_names[i],
609 pa_channel_position_to_pretty_string(info->channel_map.map[i]));
553 source->base.mute = !!info->mute; 610 source->base.mute = !!info->mute;
554 611
555 if (ctx->cb) 612 if (ctx->cb)
@@ -1164,7 +1221,7 @@ _disconnect_cb()
1164} 1221}
1165 1222
1166static void 1223static void
1167_source_volume_set(Emix_Source *source, Emix_Volume volume) 1224_source_volume_set(Emix_Source *source, Emix_Volume *volume)
1168{ 1225{
1169 pa_operation* o; 1226 pa_operation* o;
1170 pa_cvolume vol = _emix_volume_convert(volume); 1227 pa_cvolume vol = _emix_volume_convert(volume);
@@ -1211,7 +1268,7 @@ _sink_inputs_get(void)
1211} 1268}
1212 1269
1213static void 1270static void
1214_sink_volume_set(Emix_Sink *sink, Emix_Volume volume) 1271_sink_volume_set(Emix_Sink *sink, Emix_Volume *volume)
1215{ 1272{
1216 pa_operation* o; 1273 pa_operation* o;
1217 Sink *s = (Sink *)sink; 1274 Sink *s = (Sink *)sink;
@@ -1236,7 +1293,7 @@ _sink_mute_set(Emix_Sink *sink, Eina_Bool mute)
1236} 1293}
1237 1294
1238static void 1295static void
1239_sink_input_volume_set(Emix_Sink_Input *input, Emix_Volume volume) 1296_sink_input_volume_set(Emix_Sink_Input *input, Emix_Volume *volume)
1240{ 1297{
1241 pa_operation* o; 1298 pa_operation* o;
1242 Sink_Input *sink_input = (Sink_Input *)input; 1299 Sink_Input *sink_input = (Sink_Input *)input;
diff --git a/src/modules/mixer/lib/emix.c b/src/modules/mixer/lib/emix.c
index 4d22fb509..65f9cb33f 100644
--- a/src/modules/mixer/lib/emix.c
+++ b/src/modules/mixer/lib/emix.c
@@ -282,7 +282,7 @@ emix_sink_mute_set(Emix_Sink *sink, Eina_Bool mute)
282} 282}
283 283
284void 284void
285emix_sink_volume_set(Emix_Sink *sink, Emix_Volume volume) 285emix_sink_volume_set(Emix_Sink *sink, Emix_Volume *volume)
286{ 286{
287 EINA_SAFETY_ON_FALSE_RETURN((ctx && ctx->loaded && 287 EINA_SAFETY_ON_FALSE_RETURN((ctx && ctx->loaded &&
288 ctx->loaded->ebackend_sink_volume_set && 288 ctx->loaded->ebackend_sink_volume_set &&
@@ -320,7 +320,7 @@ emix_sink_input_mute_set(Emix_Sink_Input *input, Eina_Bool mute)
320} 320}
321 321
322void 322void
323emix_sink_input_volume_set(Emix_Sink_Input *input, Emix_Volume volume) 323emix_sink_input_volume_set(Emix_Sink_Input *input, Emix_Volume *volume)
324{ 324{
325 EINA_SAFETY_ON_FALSE_RETURN((ctx && ctx->loaded && 325 EINA_SAFETY_ON_FALSE_RETURN((ctx && ctx->loaded &&
326 ctx->loaded->ebackend_sink_input_volume_set && 326 ctx->loaded->ebackend_sink_input_volume_set &&
@@ -359,7 +359,7 @@ emix_source_mute_set(Emix_Source *source, Eina_Bool mute)
359} 359}
360 360
361void 361void
362emix_source_volume_set(Emix_Source *source, Emix_Volume volume) 362emix_source_volume_set(Emix_Source *source, Emix_Volume *volume)
363{ 363{
364 EINA_SAFETY_ON_FALSE_RETURN((ctx && ctx->loaded && 364 EINA_SAFETY_ON_FALSE_RETURN((ctx && ctx->loaded &&
365 ctx->loaded->ebackend_source_volume_set && 365 ctx->loaded->ebackend_source_volume_set &&
diff --git a/src/modules/mixer/lib/emix.h b/src/modules/mixer/lib/emix.h
index 94bfb89ed..6725a96c7 100644
--- a/src/modules/mixer/lib/emix.h
+++ b/src/modules/mixer/lib/emix.h
@@ -42,10 +42,13 @@ enum Emix_Event {
42 EMIX_CARD_CHANGED_EVENT 42 EMIX_CARD_CHANGED_EVENT
43}; 43};
44 44
45typedef const char * Emix_Channel;
46
45typedef struct _Emix_Volume { 47typedef struct _Emix_Volume {
46 unsigned int channel_count; 48 unsigned int channel_count;
47 // the index of the field is the id of the channel, the value the volume 49 // the index of the field is the id of the channel, the value the volume
48 int *volumes; 50 int *volumes;
51 Emix_Channel *channel_names;
49} Emix_Volume; 52} Emix_Volume;
50 53
51typedef struct _Emix_Port { 54typedef struct _Emix_Port {
@@ -104,7 +107,7 @@ typedef struct _Emix_Backend {
104 void (*ebackend_sink_mute_set)(Emix_Sink *sink, 107 void (*ebackend_sink_mute_set)(Emix_Sink *sink,
105 Eina_Bool mute); 108 Eina_Bool mute);
106 void (*ebackend_sink_volume_set)(Emix_Sink *sink, 109 void (*ebackend_sink_volume_set)(Emix_Sink *sink,
107 Emix_Volume volume); 110 Emix_Volume *volume);
108 Eina_Bool (*ebackend_sink_port_set)(Emix_Sink *sink, 111 Eina_Bool (*ebackend_sink_port_set)(Emix_Sink *sink,
109 const Emix_Port *port); 112 const Emix_Port *port);
110 Eina_Bool (*ebackend_sink_change_support)(void); 113 Eina_Bool (*ebackend_sink_change_support)(void);
@@ -113,7 +116,7 @@ typedef struct _Emix_Backend {
113 void (*ebackend_sink_input_mute_set)( 116 void (*ebackend_sink_input_mute_set)(
114 Emix_Sink_Input *input, Eina_Bool mute); 117 Emix_Sink_Input *input, Eina_Bool mute);
115 void (*ebackend_sink_input_volume_set)( 118 void (*ebackend_sink_input_volume_set)(
116 Emix_Sink_Input *input, Emix_Volume volume); 119 Emix_Sink_Input *input, Emix_Volume *volume);
117 void (*ebackend_sink_input_sink_change)( 120 void (*ebackend_sink_input_sink_change)(
118 Emix_Sink_Input *input, Emix_Sink *sink); 121 Emix_Sink_Input *input, Emix_Sink *sink);
119 122
@@ -121,7 +124,7 @@ typedef struct _Emix_Backend {
121 void (*ebackend_source_mute_set)(Emix_Source *source, 124 void (*ebackend_source_mute_set)(Emix_Source *source,
122 Eina_Bool mute); 125 Eina_Bool mute);
123 void (*ebackend_source_volume_set)(Emix_Source *source, 126 void (*ebackend_source_volume_set)(Emix_Source *source,
124 Emix_Volume volume); 127 Emix_Volume *volume);
125 128
126 Evas_Object* (*ebackend_advanced_options_add)(Evas_Object *parent); 129 Evas_Object* (*ebackend_advanced_options_add)(Evas_Object *parent);
127 const Eina_List* (*ebackend_cards_get)(void); 130 const Eina_List* (*ebackend_cards_get)(void);
@@ -132,17 +135,13 @@ typedef struct _Emix_Backend {
132 135
133#define VOLSET(vol, srcvol, target, func) \ 136#define VOLSET(vol, srcvol, target, func) \
134 do { \ 137 do { \
135 Emix_Volume _v; \
136 int _pvol = srcvol.volumes[0]; \ 138 int _pvol = srcvol.volumes[0]; \
137 if ((_pvol > 80) && (_pvol <= 100) && \ 139 if ((_pvol > 80) && (_pvol <= 100) && \
138 (vol > 100) && (vol < 120)) vol = 100; \ 140 (vol > 100) && (vol < 120)) vol = 100; \
139 _v.channel_count = srcvol.channel_count; \ 141 if (srcvol.volumes) { \
140 _v.volumes = calloc(srcvol.channel_count, sizeof(int)); \
141 if (_v.volumes) { \
142 unsigned int _i; \ 142 unsigned int _i; \
143 for (_i = 0; _i < _v.channel_count; _i++) _v.volumes[_i] = vol; \ 143 for (_i = 0; _i < srcvol.channel_count; _i++) srcvol.volumes[_i] = vol; \
144 func(target, _v); \ 144 func(target, &srcvol); \
145 free(_v.volumes); \
146 } \ 145 } \
147 } while (0) 146 } while (0)
148 147
@@ -167,14 +166,14 @@ E_API Eina_Bool emix_sink_port_set(Emix_Sink *sink, Emix_Port *port);
167E_API void emix_sink_default_set(Emix_Sink *sink); 166E_API void emix_sink_default_set(Emix_Sink *sink);
168E_API void emix_sink_mute_set(Emix_Sink *sink, Eina_Bool mute); 167E_API void emix_sink_mute_set(Emix_Sink *sink, Eina_Bool mute);
169E_API void emix_sink_volume_set(Emix_Sink *sink, 168E_API void emix_sink_volume_set(Emix_Sink *sink,
170 Emix_Volume volume); 169 Emix_Volume *volume);
171E_API Eina_Bool emix_sink_change_support(void); 170E_API Eina_Bool emix_sink_change_support(void);
172 171
173E_API const Eina_List* emix_sink_inputs_get(void); 172E_API const Eina_List* emix_sink_inputs_get(void);
174E_API void emix_sink_input_mute_set(Emix_Sink_Input *input, 173E_API void emix_sink_input_mute_set(Emix_Sink_Input *input,
175 Eina_Bool mute); 174 Eina_Bool mute);
176E_API void emix_sink_input_volume_set(Emix_Sink_Input *input, 175E_API void emix_sink_input_volume_set(Emix_Sink_Input *input,
177 Emix_Volume volume); 176 Emix_Volume *volume);
178E_API void emix_sink_input_sink_change(Emix_Sink_Input *input, 177E_API void emix_sink_input_sink_change(Emix_Sink_Input *input,
179 Emix_Sink *sink); 178 Emix_Sink *sink);
180 179
@@ -182,7 +181,7 @@ E_API const Eina_List* emix_sources_get(void);
182E_API void emix_source_mute_set(Emix_Source *source, 181E_API void emix_source_mute_set(Emix_Source *source,
183 Eina_Bool mute); 182 Eina_Bool mute);
184E_API void emix_source_volume_set(Emix_Source *source, 183E_API void emix_source_volume_set(Emix_Source *source,
185 Emix_Volume volume); 184 Emix_Volume *volume);
186E_API Evas_Object* emix_advanced_options_add(Evas_Object *parent); 185E_API Evas_Object* emix_advanced_options_add(Evas_Object *parent);
187 186
188E_API const Eina_List* emix_cards_get(void); 187E_API const Eina_List* emix_cards_get(void);