summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlavio Ceolin <flavio.ceolin@gmail.com>2014-08-31 21:37:51 -0300
committerFlavio Ceolin <flavio.ceolin@gmail.com>2014-09-02 23:44:48 -0300
commitb726fdaa4c04e7f7fa2794c9a3b679bc3fda6441 (patch)
tree00786bb7babe3b5357f3a4e225c9bcd925dd56a7
parent45b1b92b3575edd9d6546e6724116fe1616ee02c (diff)
alsa: Fixes on volume get/set/mute ...
The volume got from alsa card should be normalized to the range (0 - 100) that is used by the clients, emixer and module. Also some re-factoring was done :)
-rw-r--r--src/lib/backends/alsa/alsa.c346
1 files changed, 100 insertions, 246 deletions
diff --git a/src/lib/backends/alsa/alsa.c b/src/lib/backends/alsa/alsa.c
index f3d42e3..e26be09 100644
--- a/src/lib/backends/alsa/alsa.c
+++ b/src/lib/backends/alsa/alsa.c
@@ -1,7 +1,5 @@
1#include <Eina.h>
2#include <emix.h> 1#include <emix.h>
3#include <alsa/asoundlib.h> 2#include <alsa/asoundlib.h>
4#include <poll.h>
5 3
6#define ERR(...) EINA_LOG_ERR(__VA_ARGS__) 4#define ERR(...) EINA_LOG_ERR(__VA_ARGS__)
7#define DBG(...) EINA_LOG_DBG(__VA_ARGS__) 5#define DBG(...) EINA_LOG_DBG(__VA_ARGS__)
@@ -13,17 +11,15 @@ typedef struct _Context {
13 source_event_cb source_cb; 11 source_event_cb source_cb;
14 disconnect_event_cb disconnect_cb; 12 disconnect_event_cb disconnect_cb;
15 ready_event_cb ready_cb; 13 ready_event_cb ready_cb;
16 Eina_List *sinks; /*list of sinks*/ 14 Eina_List *sinks;
17 Eina_List *sources; /*list of sources*/ 15 Eina_List *sources;
18 Eina_List *cards; /*list of names which are recognized*/ 16 Eina_List *cards;
19} Context; 17} Context;
20static Context *ctx = NULL; 18static Context *ctx = NULL;
21 19
22typedef struct _Alsa_Emix_Sink 20typedef struct _Alsa_Emix_Sink
23{ 21{
24 Emix_Sink sink; 22 Emix_Sink sink;
25 Eina_Bool* mute_cache;
26 snd_mixer_t *handle;
27 const char *hw_name; 23 const char *hw_name;
28 Eina_List *channels; 24 Eina_List *channels;
29} Alsa_Emix_Sink; 25} Alsa_Emix_Sink;
@@ -31,8 +27,6 @@ typedef struct _Alsa_Emix_Sink
31typedef struct _Alsa_Emix_Source 27typedef struct _Alsa_Emix_Source
32{ 28{
33 Emix_Source source; 29 Emix_Source source;
34 Eina_Bool* mute_cache;
35 snd_mixer_t *handle;
36 const char *hw_name; 30 const char *hw_name;
37 Eina_List *channels; 31 Eina_List *channels;
38} Alsa_Emix_Source; 32} Alsa_Emix_Source;
@@ -47,87 +41,76 @@ typedef struct _Alsa_Emix_Source
47 */ 41 */
48 42
49static int 43static int
50_alsa_mixer_changed_cb(snd_mixer_t *ctl, unsigned int mask EINA_UNUSED, snd_mixer_elem_t 44_alsa_mixer_sink_changed_cb(snd_mixer_t *ctl, unsigned int mask EINA_UNUSED,
51*elem) 45 snd_mixer_elem_t *elem EINA_UNUSED)
52{ 46{
53 Eina_Array *arr = snd_mixer_get_callback_private(ctl); 47 Alsa_Emix_Sink *sink = snd_mixer_get_callback_private(ctl);
54 if (snd_mixer_selem_has_capture_volume(elem)) 48 ctx->sink_cb((Emix_Sink *)sink, EMIX_EVENT_CHANGED);
55 ctx->source_cb(eina_array_data_get(arr, 1), EMIX_EVENT_CHANGED); 49 return 0;
56 else 50}
57 ctx->sink_cb(eina_array_data_get(arr, 0), EMIX_EVENT_CHANGED); 51
58 return 0; 52static int
53_alsa_mixer_source_changed_cb(snd_mixer_t *ctl, unsigned int mask EINA_UNUSED,
54 snd_mixer_elem_t *elem EINA_UNUSED)
55{
56 Alsa_Emix_Source *source = snd_mixer_get_callback_private(ctl);
57 ctx->source_cb((Emix_Source *)source, EMIX_EVENT_CHANGED);
58 return 0;
59} 59}
60 60
61static void 61static void
62_alsa_channel_volume_get(snd_mixer_elem_t *channel, int *v, Eina_Bool capture) 62_alsa_channel_volume_get(snd_mixer_elem_t *channel, int *v, Eina_Bool capture)
63{ 63{
64 long int min, max, lvol, rvol; 64 long int min, max, vol;
65 int range; 65 int range, divide;
66 66
67 if (capture) 67 if (capture)
68 snd_mixer_selem_get_capture_volume_range(channel, &min, &max); 68 snd_mixer_selem_get_capture_volume_range(channel, &min, &max);
69 else 69 else
70 snd_mixer_selem_get_playback_volume_range(channel, &min, &max); 70 snd_mixer_selem_get_playback_volume_range(channel, &min, &max);
71 71
72 range = max - min; 72 divide = 100 + min;
73 if (divide == 0)
74 {
75 divide = 1;
76 min++;
77 }
73 78
79 range = max - min;
74 if (range < 1) 80 if (range < 1)
75 return; 81 return;
76 82
77 if (capture) 83 if (capture)
78 { 84 snd_mixer_selem_get_capture_volume(channel, 0, &vol);
79 snd_mixer_selem_get_capture_volume(channel, 0, &lvol);
80 if (!snd_mixer_selem_is_capture_mono(channel))
81 snd_mixer_selem_get_capture_volume(channel, 1, &rvol);
82 }
83 else 85 else
84 { 86 snd_mixer_selem_get_playback_volume(channel, 0, &vol);
85 snd_mixer_selem_get_playback_volume(channel, 0, &lvol);
86 if (!snd_mixer_selem_is_playback_mono(channel))
87 snd_mixer_selem_get_playback_volume(channel, 1, &rvol);
88 }
89 87
90 *v = lvol; 88 *v = (((vol + min) * divide) - ((double) range / 2)) / range + 0.5;
91} 89}
92 90
93static void 91static void
94_alsa_channel_volume_set(snd_mixer_elem_t *channel, int v, Eina_Bool capture) 92_alsa_channel_volume_set(snd_mixer_elem_t *channel, int v, Eina_Bool capture)
95{ 93{
96 int range, divide; 94 long int vol, min, max, divide, range;
97 long int l, r, min, max;
98 snd_mixer_selem_get_playback_volume_range(channel, &min, &max); 95 snd_mixer_selem_get_playback_volume_range(channel, &min, &max);
99 divide = 100 + min;
100 96
101 if (divide == 0) 97 divide = 100 + min;
102 { 98 range = max - min;
103 divide = 1;
104 min ++;
105 }
106 range = max -min;
107 if (range < 1) 99 if (range < 1)
108 return; 100 return;
109 l = (((range * v) + (range / 2)) / divide) - min; 101
110 r = (((range * v) + (range / 2)) / divide) - min; 102 vol = (((v * range) + (range / 2)) / divide) - min;
111 if (!capture) 103 if (!capture)
112 { 104 snd_mixer_selem_set_playback_volume_all(channel, vol);
113 snd_mixer_selem_set_playback_volume(channel, 0, l);
114 if (!snd_mixer_selem_is_playback_mono(channel))
115 snd_mixer_selem_set_playback_volume(channel, 1, r);
116 }
117 else 105 else
118 { 106 snd_mixer_selem_set_capture_volume_all(channel, vol);
119 snd_mixer_selem_set_capture_volume(channel, 0, l);
120 if (!snd_mixer_selem_is_capture_mono(channel))
121 snd_mixer_selem_set_capture_volume(channel, 1, r);
122 }
123} 107}
124 108
125
126/* 109/*
127 * This will append a new device to the cards and call the ecore event for a new device! 110 * This will append a new device to the cards and call the ecore event for
111 * a new device!
128 */ 112 */
129 113static snd_mixer_t *
130snd_mixer_t*
131_alsa_card_create(char *addr) 114_alsa_card_create(char *addr)
132{ 115{
133 snd_mixer_t *control; 116 snd_mixer_t *control;
@@ -150,46 +133,20 @@ error_open:
150} 133}
151 134
152static void 135static void
153_alsa_card_free(snd_mixer_t *mixer)
154{
155 snd_mixer_close(mixer);
156}
157
158static Eina_Bool
159_search_card(char *name)
160{
161 char *card_name;
162 Eina_List *node;
163
164 EINA_LIST_FOREACH(ctx->cards, node, card_name)
165 {
166 if (!strcmp(card_name, name))
167 return EINA_TRUE;
168 }
169 return EINA_FALSE;
170}
171
172static void
173_alsa_volume_create(Emix_Volume *volume, Eina_List *channels) 136_alsa_volume_create(Emix_Volume *volume, Eina_List *channels)
174{ 137{
175 unsigned int i; 138 unsigned int i = 0, count = eina_list_count(channels);
139 Eina_List *l;
140 snd_mixer_elem_t *elem;
176 141
177 volume->channel_count = eina_list_count(channels); 142 volume->channel_count = count;
178 volume->volumes = calloc(eina_list_count(channels), sizeof(int)); 143 volume->volumes = calloc(count, sizeof(int));
179 144
180 for (i = 0; i < eina_list_count(channels); i++) 145 EINA_LIST_FOREACH(channels, l, elem)
181 { 146 {
182 _alsa_channel_volume_get((snd_mixer_elem_t*) eina_list_nth(channels, i), 147 _alsa_channel_volume_get(elem, &(volume->volumes[i]), EINA_FALSE);
183 &(volume->volumes[i]), 148 i++;
184 EINA_FALSE);
185 } 149 }
186
187}
188
189static void
190_alsa_volume_free(Emix_Volume volume)
191{
192 free(volume.volumes);
193} 150}
194 151
195static void 152static void
@@ -199,7 +156,7 @@ _alsa_sink_mute_get(Alsa_Emix_Sink *as)
199 snd_mixer_elem_t *elem; 156 snd_mixer_elem_t *elem;
200 157
201 elem = eina_list_data_get(as->channels); 158 elem = eina_list_data_get(as->channels);
202 snd_mixer_selem_get_playback_switch(elem,0, &i); 159 snd_mixer_selem_get_playback_switch(elem, 0, &i);
203 as->sink.mute = !i; 160 as->sink.mute = !i;
204} 161}
205 162
@@ -215,7 +172,8 @@ _alsa_sources_mute_get(Alsa_Emix_Source *as)
215} 172}
216 173
217static Alsa_Emix_Sink* 174static Alsa_Emix_Sink*
218_alsa_device_sink_create(snd_mixer_t *mixer, const char *name, const char* hw_name, Eina_List *channels) 175_alsa_device_sink_create(const char *name, const char* hw_name,
176 Eina_List *channels)
219{ 177{
220 Alsa_Emix_Sink *sink; 178 Alsa_Emix_Sink *sink;
221 179
@@ -227,7 +185,6 @@ _alsa_device_sink_create(snd_mixer_t *mixer, const char *name, const char* hw_na
227 sink->sink.name = eina_stringshare_add(name); 185 sink->sink.name = eina_stringshare_add(name);
228 _alsa_volume_create(&sink->sink.volume, channels); 186 _alsa_volume_create(&sink->sink.volume, channels);
229 sink->hw_name = eina_stringshare_add(hw_name); 187 sink->hw_name = eina_stringshare_add(hw_name);
230 sink->handle = mixer;
231 sink->channels = channels; 188 sink->channels = channels;
232 _alsa_sink_mute_get(sink); 189 _alsa_sink_mute_get(sink);
233 ctx->sink_cb((Emix_Sink*) sink, EMIX_EVENT_ADDED); 190 ctx->sink_cb((Emix_Sink*) sink, EMIX_EVENT_ADDED);
@@ -237,7 +194,8 @@ _alsa_device_sink_create(snd_mixer_t *mixer, const char *name, const char* hw_na
237} 194}
238 195
239static Alsa_Emix_Source* 196static Alsa_Emix_Source*
240_alsa_device_source_create(snd_mixer_t *mixer, const char *name, const char* hw_name, Eina_List *channels) 197_alsa_device_source_create(const char *name, const char* hw_name,
198 Eina_List *channels)
241{ 199{
242 Alsa_Emix_Source *source; 200 Alsa_Emix_Source *source;
243 201
@@ -249,7 +207,6 @@ _alsa_device_source_create(snd_mixer_t *mixer, const char *name, const char* hw_
249 source->source.name = eina_stringshare_add(name); 207 source->source.name = eina_stringshare_add(name);
250 _alsa_volume_create(&source->source.volume, channels); 208 _alsa_volume_create(&source->source.volume, channels);
251 source->hw_name = eina_stringshare_add(hw_name); 209 source->hw_name = eina_stringshare_add(hw_name);
252 source->handle = mixer;
253 source->channels = channels; 210 source->channels = channels;
254 _alsa_sources_mute_get(source); 211 _alsa_sources_mute_get(source);
255 ctx->source_cb((Emix_Source*) source, EMIX_EVENT_ADDED); 212 ctx->source_cb((Emix_Source*) source, EMIX_EVENT_ADDED);
@@ -258,73 +215,36 @@ _alsa_device_source_create(snd_mixer_t *mixer, const char *name, const char* hw_
258} 215}
259 216
260static void 217static void
261_alsa_device_sink_free(void *emix) 218_alsa_device_sink_free(Alsa_Emix_Sink *sink)
262{ 219{
263 Alsa_Emix_Sink *sink = emix;
264 eina_stringshare_del(sink->hw_name); 220 eina_stringshare_del(sink->hw_name);
265 eina_stringshare_del(sink->sink.name); 221 eina_stringshare_del(sink->sink.name);
266 _alsa_volume_free(sink->sink.volume); 222 free(sink->sink.volume.volumes);
267 free(sink); 223 free(sink);
268} 224}
269 225
270static void 226static void
271_alsa_device_source_free(void *emix) 227_alsa_device_source_free(Alsa_Emix_Source *source)
272{ 228{
273 Alsa_Emix_Source *source = emix;
274 eina_stringshare_del(source->hw_name); 229 eina_stringshare_del(source->hw_name);
275 eina_stringshare_del(source->source.name); 230 eina_stringshare_del(source->source.name);
276 _alsa_volume_free(source->source.volume); 231 free(source->source.volume.volumes);
277 free(source); 232 free(source);
278} 233}
279 234
280 235static char*
281static void
282_alsa_device_sink_remove(char* card_name, snd_mixer_t **mixer)
283{
284 Eina_List *node;
285 Alsa_Emix_Sink *sink;
286 EINA_LIST_FOREACH(ctx->sinks, node, sink)
287 {
288 if (!strcmp(sink->hw_name, card_name))
289 {
290 ctx->sink_cb((Emix_Sink*) sink, EMIX_EVENT_REMOVED);
291 *mixer = sink->handle;
292 _alsa_device_sink_free(sink);
293 return;
294 }
295 }
296}
297
298static void
299_alsa_device_source_remove(char* card_name, snd_mixer_t **mixer)
300{
301 Eina_List *node;
302 Alsa_Emix_Source *source;
303 EINA_LIST_FOREACH(ctx->sources, node, source)
304 {
305 if (!strcmp(source->hw_name, card_name))
306 {
307 ctx->source_cb((Emix_Source*) source, EMIX_EVENT_REMOVED);
308 *mixer = source->handle;
309 _alsa_device_source_free(source);
310 return;
311 }
312 }
313}
314
315static const char*
316_alsa_cards_name_get(char *name) 236_alsa_cards_name_get(char *name)
317{ 237{
318 snd_ctl_t *control; 238 snd_ctl_t *control;
319 snd_ctl_card_info_t *hw_info; 239 snd_ctl_card_info_t *hw_info;
320 const char *result = NULL; 240 char *result = NULL;
321 241
322 snd_ctl_card_info_alloca(&hw_info); 242 snd_ctl_card_info_alloca(&hw_info);
323 243
324 if (snd_ctl_open(&control, name, 0) < 0) 244 if (snd_ctl_open(&control, name, 0) < 0)
325 { 245 {
326 ERR("Failed to open device"); 246 ERR("Failed to open device");
327 goto err; 247 goto err;
328 } 248 }
329 249
330 if (snd_ctl_card_info(control, hw_info) < 0) 250 if (snd_ctl_card_info(control, hw_info) < 0)
@@ -333,24 +253,24 @@ _alsa_cards_name_get(char *name)
333 goto err_open; 253 goto err_open;
334 } 254 }
335 255
336 result = eina_stringshare_add(snd_ctl_card_info_get_name(hw_info)); 256 result = strdup(snd_ctl_card_info_get_name(hw_info));
337 257
338 err_open: 258err_open:
339 snd_ctl_close(control); 259 snd_ctl_close(control);
340 err: 260err:
341 return result; 261 return result;
342} 262}
343 263
344static void 264static void
345_alsa_cards_refresh(void) 265_alsa_cards_refresh(void)
346{ 266{
347 int err, card_num = -1; 267 int err, card_num = -1;
348 Eina_List *tmp = NULL, *tmp_source = NULL, *tmp_sink = NULL; 268 Eina_List *tmp_source = NULL, *tmp_sink = NULL;
349 269
350 while (((err = snd_card_next(&card_num)) == 0) && (card_num >= 0)) 270 while (((err = snd_card_next(&card_num)) == 0) && (card_num >= 0))
351 { 271 {
352 char buf[PATH_MAX]; 272 char buf[PATH_MAX];
353 const char *device_name; 273 char *device_name;
354 snd_mixer_t *mixer; 274 snd_mixer_t *mixer;
355 snd_mixer_elem_t *elem; 275 snd_mixer_elem_t *elem;
356 Alsa_Emix_Source *source; 276 Alsa_Emix_Source *source;
@@ -364,15 +284,9 @@ _alsa_cards_refresh(void)
364 //generate card addr 284 //generate card addr
365 snprintf(buf, sizeof(buf), "hw:%d", card_num); 285 snprintf(buf, sizeof(buf), "hw:%d", card_num);
366 //save the addr to see if there are missing devices in the cache list 286 //save the addr to see if there are missing devices in the cache list
367 tmp = eina_list_append(tmp, eina_stringshare_add(buf));
368 //is this card new?
369 if (_search_card(buf))
370 continue;
371 //yes..
372 //create mixer
373 mixer = _alsa_card_create(buf);
374 287
375 ctx->cards = eina_list_append(ctx->cards, eina_stringshare_add(buf)); 288 mixer = _alsa_card_create(buf);
289 ctx->cards = eina_list_append(ctx->cards, mixer);
376 //get elements of the device 290 //get elements of the device
377 elem = snd_mixer_first_elem(mixer); 291 elem = snd_mixer_first_elem(mixer);
378 for (; elem; elem = snd_mixer_elem_next(elem)) 292 for (; elem; elem = snd_mixer_elem_next(elem))
@@ -383,60 +297,28 @@ _alsa_cards_refresh(void)
383 else 297 else
384 tmp_sink = eina_list_append(tmp_sink, elem); 298 tmp_sink = eina_list_append(tmp_sink, elem);
385 } 299 }
386 //get the complete device name 300
387 device_name = _alsa_cards_name_get(buf); 301 device_name = _alsa_cards_name_get(buf);
388 //create the sinks / sources 302 //create the sinks / sources
389 if (tmp_sink) 303 if (tmp_sink)
390 sink = _alsa_device_sink_create(mixer,
391 device_name,
392 buf,
393 tmp_sink);
394 if (tmp_source)
395 source = _alsa_device_source_create(mixer,
396 device_name,
397 buf,
398 tmp_source);
399 eina_stringshare_del(device_name);
400 //set callbacks for changes
401 snd_mixer_set_callback(mixer, _alsa_mixer_changed_cb);
402 Eina_Array *arr = eina_array_new(2);
403 eina_array_push(arr, sink);
404 eina_array_push(arr, source);
405 snd_mixer_set_callback_private(mixer, arr);
406 }
407
408 // Check if a card was removed
409 char *card_name;
410 Eina_List *node, *node2;
411 const char *name;
412 snd_mixer_t *mixer = NULL, *mixer2 = NULL;
413
414 EINA_LIST_FOREACH(ctx->cards, node, card_name)
415 {
416 Eina_Bool found = EINA_FALSE;
417 //search in the tmp list for this entry
418 EINA_LIST_FOREACH(tmp, node2, name)
419 { 304 {
420 if (!strcmp(card_name, name)) 305 sink = _alsa_device_sink_create(device_name,
421 { 306 buf,
422 found = EINA_TRUE; 307 tmp_sink);
423 break; 308 snd_mixer_set_callback(mixer, _alsa_mixer_sink_changed_cb);
424 } 309 snd_mixer_set_callback_private(mixer, sink);
425 } 310 }
426 if (!found) 311 if (tmp_source)
427 { 312 {
428 ctx->cards = eina_list_remove(ctx->cards, card_name); 313 source = _alsa_device_source_create(device_name,
429 _alsa_device_sink_remove(card_name, &mixer); 314 buf,
430 _alsa_device_source_remove(card_name, &mixer2); 315 tmp_source);
431 if (!mixer) 316 snd_mixer_set_callback(mixer, _alsa_mixer_source_changed_cb);
432 mixer = mixer2; 317 snd_mixer_set_callback_private(mixer, source);
433 _alsa_card_free(mixer);
434 eina_stringshare_del(card_name);
435 } 318 }
319 if (device_name)
320 free(device_name);
436 } 321 }
437 //cleanup
438 EINA_LIST_FREE(tmp, card_name)
439 eina_stringshare_del(card_name);
440} 322}
441 323
442static Eina_Bool 324static Eina_Bool
@@ -460,6 +342,17 @@ _alsa_init(sink_event_cb sink_cb, sink_input_event_cb input_cb,
460static void 342static void
461_alsa_shutdown(void) 343_alsa_shutdown(void)
462{ 344{
345 Alsa_Emix_Sink *sink;
346 Alsa_Emix_Source *source;
347 snd_mixer_t *mixer;
348
349 EINA_LIST_FREE(ctx->sinks, sink)
350 _alsa_device_sink_free(sink);
351 EINA_LIST_FREE(ctx->sources, source)
352 _alsa_device_source_free(source);
353 EINA_LIST_FREE(ctx->cards, mixer)
354 snd_mixer_close(mixer);
355
463 ctx->disconnect_cb(); 356 ctx->disconnect_cb();
464 free(ctx); 357 free(ctx);
465 ctx = NULL; 358 ctx = NULL;
@@ -477,36 +370,15 @@ _alsa_sources_mute_set(Emix_Source *source, Eina_Bool mute)
477 Alsa_Emix_Source *s = (Alsa_Emix_Source*) source; 370 Alsa_Emix_Source *s = (Alsa_Emix_Source*) source;
478 Eina_List *node; 371 Eina_List *node;
479 snd_mixer_elem_t *elem; 372 snd_mixer_elem_t *elem;
480 int i = 0, c = 0;
481
482 if ((mute && s->mute_cache) || (!mute && !s->mute_cache))
483 return;
484 if (mute)
485 s->mute_cache = calloc(eina_list_count(s->channels), sizeof(Eina_Bool));
486 373
487 EINA_LIST_FOREACH(s->channels, node, elem) 374 EINA_LIST_FOREACH(s->channels, node, elem)
488 { 375 {
489 if (!snd_mixer_selem_has_capture_switch(elem)) 376 if (!snd_mixer_selem_has_capture_switch(elem))
490 continue; 377 continue;
491 if (mute)
492 {
493 snd_mixer_selem_get_capture_switch(elem, 0, &i);
494 s->mute_cache[c] = !!i;
495 i = 0;
496 }
497 else
498 {
499 i = s->mute_cache[c];
500 }
501 if (snd_mixer_selem_set_capture_switch_all(elem, !mute) < 0) 378 if (snd_mixer_selem_set_capture_switch_all(elem, !mute) < 0)
502 ERR("Failed to mute device\n"); 379 ERR("Failed to mute device\n");
503 c++;
504 }
505 if (!mute && s->mute_cache)
506 {
507 free(s->mute_cache);
508 s->mute_cache = NULL;
509 } 380 }
381
510 source->mute = mute; 382 source->mute = mute;
511 ctx->source_cb(source, EMIX_EVENT_CHANGED); 383 ctx->source_cb(source, EMIX_EVENT_CHANGED);
512} 384}
@@ -558,42 +430,24 @@ _alsa_sink_mute_set(Emix_Sink *sink, Eina_Bool mute)
558 Alsa_Emix_Sink *as = (Alsa_Emix_Sink*) sink; 430 Alsa_Emix_Sink *as = (Alsa_Emix_Sink*) sink;
559 Eina_List *node; 431 Eina_List *node;
560 snd_mixer_elem_t *elem; 432 snd_mixer_elem_t *elem;
561 int i = 0, c = 0;
562 433
563 if ((mute && as->mute_cache) || (!mute && !as->mute_cache))
564 return;
565 if (mute)
566 as->mute_cache = calloc(eina_list_count(as->channels), sizeof(Eina_Bool));
567 EINA_LIST_FOREACH(as->channels, node, elem) 434 EINA_LIST_FOREACH(as->channels, node, elem)
568 { 435 {
569 if (!snd_mixer_selem_has_playback_switch(elem)) 436 if (!snd_mixer_selem_has_playback_switch(elem))
570 continue; 437 continue;
571 if (mute) 438
572 { 439 if (snd_mixer_selem_set_playback_switch_all(elem, !mute) < 0)
573 snd_mixer_selem_get_playback_switch(elem, 0, &i);
574 as->mute_cache[c] = !!i;
575 i = 0;
576 }
577 else
578 {
579 i = as->mute_cache[c];
580 }
581 if (snd_mixer_selem_set_playback_switch_all(elem, i) < 0)
582 ERR("Failed to set mute(%d) device(%p)", mute, elem); 440 ERR("Failed to set mute(%d) device(%p)", mute, elem);
583 c++;
584 }
585 if (!mute && as->mute_cache)
586 {
587 free(as->mute_cache);
588 as->mute_cache = NULL;
589 } 441 }
442
590 sink->mute = mute; 443 sink->mute = mute;
591 ctx->sink_cb(sink, EMIX_EVENT_CHANGED); 444 ctx->sink_cb(sink, EMIX_EVENT_CHANGED);
592} 445}
446
593static void 447static void
594_alsa_sink_volume_set(Emix_Sink *sink, Emix_Volume v) 448_alsa_sink_volume_set(Emix_Sink *sink, Emix_Volume v)
595{ 449{
596 Alsa_Emix_Sink *s = (Alsa_Emix_Sink*) sink; 450 Alsa_Emix_Sink *s = (Alsa_Emix_Sink *)sink;
597 unsigned int i; 451 unsigned int i;
598 snd_mixer_elem_t *elem; 452 snd_mixer_elem_t *elem;
599 453