summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlavio Ceolin <flavio.ceolin@gmail.com>2014-08-08 00:53:38 -0300
committerFlavio Ceolin <flavio.ceolin@gmail.com>2014-08-14 23:33:19 -0300
commitb68c9f556b594fadb7ac43520bb00b8376d418d3 (patch)
tree0d9cd1aac7101a879f343d89d35f6e32483940f9 /src
parentabb65b2ba5ea7b0a1e005538aacc9bc199be820f (diff)
Removed libepulse
It's possible build the module and the mixer without pulseaudio. The application and module have no depencies except efl, all the low-level stuff is done in the backends.
Diffstat (limited to 'src')
-rw-r--r--src/bin/main.c7
-rw-r--r--src/bin/main_window.c1
-rw-r--r--src/lib/epulse.c809
-rw-r--r--src/lib/epulse.h64
-rw-r--r--src/lib/epulse_ml.c309
5 files changed, 2 insertions, 1188 deletions
diff --git a/src/bin/main.c b/src/bin/main.c
index 56f7524..29f66ee 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -1,6 +1,5 @@
1#include <common.h>
2#include <epulse.h>
3#include <emix.h> 1#include <emix.h>
2#include "common.h"
4#include "main_window.h" 3#include "main_window.h"
5 4
6#define DEFAULT_HEIGHT 600 5#define DEFAULT_HEIGHT 600
@@ -11,8 +10,7 @@ elm_main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
11{ 10{
12 Evas_Object *win; 11 Evas_Object *win;
13 12
14 EINA_SAFETY_ON_FALSE_RETURN_VAL(epulse_common_init("epulse"), EXIT_FAILURE); 13 EINA_SAFETY_ON_FALSE_RETURN_VAL(epulse_common_init("emixer"), EXIT_FAILURE);
15 EINA_SAFETY_ON_FALSE_RETURN_VAL(epulse_init() > 0, EXIT_FAILURE);
16 EINA_SAFETY_ON_FALSE_RETURN_VAL(emix_init() == EINA_TRUE, EXIT_FAILURE); 14 EINA_SAFETY_ON_FALSE_RETURN_VAL(emix_init() == EINA_TRUE, EXIT_FAILURE);
17 15
18 win = main_window_add(); 16 win = main_window_add();
@@ -23,7 +21,6 @@ elm_main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
23 elm_run(); 21 elm_run();
24 22
25 epulse_common_shutdown(); 23 epulse_common_shutdown();
26 epulse_shutdown();
27 emix_shutdown(); 24 emix_shutdown();
28 return 0; 25 return 0;
29} 26}
diff --git a/src/bin/main_window.c b/src/bin/main_window.c
index c596e7d..5b49b4a 100644
--- a/src/bin/main_window.c
+++ b/src/bin/main_window.c
@@ -1,6 +1,5 @@
1#include "main_window.h" 1#include "main_window.h"
2 2
3#include "epulse.h"
4#include "playbacks_view.h" 3#include "playbacks_view.h"
5#include "sinks_view.h" 4#include "sinks_view.h"
6#include "sources_view.h" 5#include "sources_view.h"
diff --git a/src/lib/epulse.c b/src/lib/epulse.c
deleted file mode 100644
index 3a2d4aa..0000000
--- a/src/lib/epulse.c
+++ /dev/null
@@ -1,809 +0,0 @@
1#include "epulse.h"
2
3typedef struct _Epulse_Context Epulse_Context;
4struct _Epulse_Context {
5 pa_mainloop_api api;
6 pa_context *context;
7 pa_context_state_t state;
8 void *data;
9};
10
11static unsigned int _init_count = 0;
12static Epulse_Context *ctx = NULL;
13extern pa_mainloop_api functable;
14
15int SINK_ADDED = 0;
16int SINK_CHANGED = 0;
17int SINK_DEFAULT = 0;
18int SINK_REMOVED = 0;
19int SINK_INPUT_ADDED = 0;
20int SINK_INPUT_CHANGED = 0;
21int SINK_INPUT_REMOVED = 0;
22int SOURCE_ADDED = 0;
23int SOURCE_CHANGED = 0;
24int SOURCE_REMOVED = 0;
25int SOURCE_INPUT_ADDED = 0;
26int SOURCE_INPUT_REMOVED = 0;
27int DISCONNECTED = 0;
28
29static void
30_event_free_cb(void *user_data EINA_UNUSED, void *func_data)
31{
32 Epulse_Event *ev = func_data;
33
34 if (ev->name)
35 free(ev->name);
36
37 free(ev);
38}
39
40static void
41_event_sink_input_free_cb(void *user_data EINA_UNUSED, void *func_data)
42{
43 Epulse_Event_Sink_Input *ev = func_data;
44
45 if (ev->base.name)
46 free(ev->base.name);
47
48 if (ev->icon)
49 free(ev->icon);
50
51 free(ev);
52}
53
54static void
55_event_sink_free_cb(void *user_data EINA_UNUSED, void *func_data)
56{
57 Epulse_Event_Sink *ev = func_data;
58 Port *port;
59
60 if (ev->base.name)
61 free(ev->base.name);
62
63 EINA_LIST_FREE(ev->ports, port)
64 {
65 free(port->name);
66 free(port->description);
67 free(port);
68 }
69
70 free(ev);
71}
72
73static void
74_sink_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
75 void *userdata EINA_UNUSED)
76{
77 Epulse_Event_Sink *ev;
78 Port *port;
79 uint32_t i;
80
81 if (eol < 0)
82 {
83 if (pa_context_errno(c) == PA_ERR_NOENTITY)
84 return;
85
86 ERR("Sink callback failure");
87 return;
88 }
89
90 if (eol > 0)
91 return;
92
93 DBG("sink index: %d\nsink name: %s", info->index,
94 info->name);
95
96 ev = calloc(1, sizeof(Epulse_Event_Sink));
97 ev->base.index = info->index;
98 ev->base.name = strdup(info->description);
99 ev->base.volume = info->volume;
100 ev->base.mute = !!info->mute;
101
102 for (i = 0; i < info->n_ports; i++)
103 {
104 port = calloc(1, sizeof(Port));
105 EINA_SAFETY_ON_NULL_GOTO(port, error);
106
107 port->available = !!info->ports[i]->available;
108 port->priority = info->ports[i]->priority;
109 port->name = strdup(info->ports[i]->name);
110 port->description = strdup(info->ports[i]->description);
111 ev->ports = eina_list_append(ev->ports, port);
112 if (info->ports[i]->name == info->active_port->name)
113 port->active = EINA_TRUE;
114 }
115
116 ecore_event_add(SINK_ADDED, ev, _event_sink_free_cb, NULL);
117 return;
118
119 error:
120 _event_sink_free_cb(NULL, ev);
121}
122
123static void
124_sink_changed_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
125 void *userdata EINA_UNUSED)
126{
127 Epulse_Event_Sink *ev;
128 Port *port;
129 uint32_t i;
130
131 if (eol < 0)
132 {
133 if (pa_context_errno(c) == PA_ERR_NOENTITY)
134 return;
135
136 ERR("Sink callback failure");
137 return;
138 }
139
140 if (eol > 0)
141 return;
142
143 DBG("sink index: %d\nsink name: %s", info->index,
144 info->name);
145
146 ev = calloc(1, sizeof(Epulse_Event_Sink));
147 ev->base.index = info->index;
148 ev->base.name = strdup(info->name);
149 ev->base.volume = info->volume;
150 ev->base.mute = !!info->mute;
151
152 for (i = 0; i < info->n_ports; i++)
153 {
154 port = calloc(1, sizeof(Port));
155 EINA_SAFETY_ON_NULL_GOTO(port, error);
156
157 port->priority = info->ports[i]->priority;
158 port->available = !!info->ports[i]->available;
159 port->name = strdup(info->ports[i]->description ?:
160 info->ports[i]->name);
161 ev->ports = eina_list_append(ev->ports, port);
162 if (info->ports[i]->name == info->active_port->name)
163 port->active = EINA_TRUE;
164 }
165
166 ecore_event_add(SINK_CHANGED, ev, _event_sink_free_cb, NULL);
167 return;
168
169 error:
170 _event_sink_free_cb(NULL, ev);
171}
172
173static void
174_sink_remove_cb(int index, void *data EINA_UNUSED)
175{
176 Epulse_Event_Sink *ev;
177 DBG("Removing sink: %d", index);
178
179 ev = calloc(1, sizeof(Epulse_Event_Sink));
180 ev->base.index = index;
181
182 ecore_event_add(SINK_REMOVED, ev, _event_sink_free_cb, NULL);
183}
184
185static const char *
186_icon_from_properties(pa_proplist *l)
187{
188 const char *t;
189
190 if ((t = pa_proplist_gets(l, PA_PROP_MEDIA_ICON_NAME)))
191 return t;
192
193 if ((t = pa_proplist_gets(l, PA_PROP_WINDOW_ICON_NAME)))
194 return t;
195
196 if ((t = pa_proplist_gets(l, PA_PROP_APPLICATION_ICON_NAME)))
197 return t;
198
199 if ((t = pa_proplist_gets(l, PA_PROP_MEDIA_ROLE)))
200 {
201
202 if (strcmp(t, "video") == 0 ||
203 strcmp(t, "phone") == 0)
204 return t;
205
206 if (strcmp(t, "music") == 0)
207 return "audio";
208
209 if (strcmp(t, "game") == 0)
210 return "applications-games";
211
212 if (strcmp(t, "event") == 0)
213 return "dialog-information";
214 }
215
216 return "audio-card";
217}
218
219static void
220_sink_input_cb(pa_context *c EINA_UNUSED, const pa_sink_input_info *info,
221 int eol, void *userdata EINA_UNUSED)
222{
223 Epulse_Event_Sink_Input *ev;
224
225 if (eol < 0)
226 {
227 if (pa_context_errno(c) == PA_ERR_NOENTITY)
228 return;
229
230 ERR("Sink input callback failure");
231 return;
232 }
233
234 if (eol > 0)
235 return;
236
237 DBG("sink input index: %d\nsink input name: %s", info->index,
238 info->name);
239
240 ev = calloc(1, sizeof(Epulse_Event_Sink_Input));
241 ev->base.index = info->index;
242 ev->base.name = strdup(info->name);
243 ev->base.volume = info->volume;
244 ev->base.mute = !!info->mute;
245 ev->sink = info->sink;
246 ev->icon = strdup(_icon_from_properties(info->proplist));
247
248 ecore_event_add(SINK_INPUT_ADDED, ev, _event_sink_input_free_cb, NULL);
249}
250
251static void
252_sink_input_changed_cb(pa_context *c EINA_UNUSED,
253 const pa_sink_input_info *info, int eol,
254 void *userdata EINA_UNUSED)
255{
256 Epulse_Event_Sink_Input *ev;
257
258 if (eol < 0)
259 {
260 if (pa_context_errno(c) == PA_ERR_NOENTITY)
261 return;
262
263 ERR("Sink input changed callback failure");
264 return;
265 }
266
267 if (eol > 0)
268 return;
269
270 DBG("sink input changed index: %d\n", info->index);
271
272 ev = calloc(1, sizeof(Epulse_Event_Sink_Input));
273 ev->base.index = info->index;
274 ev->base.volume = info->volume;
275 ev->base.mute = !!info->mute;
276
277 ecore_event_add(SINK_INPUT_CHANGED, ev, _event_sink_input_free_cb,
278 NULL);
279}
280
281static void
282_sink_input_remove_cb(int index, void *data EINA_UNUSED)
283{
284 Epulse_Event_Sink_Input *ev;
285
286 DBG("Removing sink input: %d", index);
287
288 ev = calloc(1, sizeof(Epulse_Event_Sink_Input));
289 ev->base.index = index;
290
291 ecore_event_add(SINK_INPUT_REMOVED, ev, _event_sink_input_free_cb, NULL);
292}
293
294static void
295_source_cb(pa_context *c EINA_UNUSED, const pa_source_info *info,
296 int eol, void *userdata EINA_UNUSED)
297{
298 Epulse_Event *ev;
299
300 if (eol < 0)
301 {
302 if (pa_context_errno(c) == PA_ERR_NOENTITY)
303 return;
304
305 ERR("Source callback failure");
306 return;
307 }
308
309 if (eol > 0)
310 return;
311
312 ev = calloc(1, sizeof(Epulse_Event));
313 ev->index = info->index;
314 ev->name = strdup(info->name);
315 ev->volume = info->volume;
316 ev->mute = !!info->mute;
317
318 ecore_event_add(SOURCE_ADDED, ev, _event_free_cb, NULL);
319}
320
321static void
322_source_changed_cb(pa_context *c EINA_UNUSED,
323 const pa_source_info *info, int eol,
324 void *userdata EINA_UNUSED)
325{
326 Epulse_Event *ev;
327
328 if (eol < 0)
329 {
330 if (pa_context_errno(c) == PA_ERR_NOENTITY)
331 return;
332
333 ERR("Source changed callback failure");
334 return;
335 }
336
337 if (eol > 0)
338 return;
339
340 DBG("source changed index: %d\n", info->index);
341
342 ev = calloc(1, sizeof(Epulse_Event));
343 ev->index = info->index;
344 ev->volume = info->volume;
345 ev->mute = !!info->mute;
346
347 ecore_event_add(SOURCE_CHANGED, ev, _event_free_cb,
348 NULL);
349}
350
351static void
352_source_remove_cb(int index, void *data EINA_UNUSED)
353{
354 Epulse_Event *ev;
355
356 DBG("Removing source: %d", index);
357
358 ev = calloc(1, sizeof(Epulse_Event));
359 ev->index = index;
360
361 ecore_event_add(SOURCE_REMOVED, ev, _event_free_cb, NULL);
362}
363
364static void
365_sink_default_cb(pa_context *c EINA_UNUSED, const pa_sink_info *info, int eol,
366 void *userdata EINA_UNUSED)
367{
368 Epulse_Event_Sink *ev;
369
370 if (eol < 0)
371 {
372 if (pa_context_errno(c) == PA_ERR_NOENTITY)
373 return;
374
375 ERR("Sink callback failure");
376 return;
377 }
378
379 if (eol > 0)
380 return;
381
382 DBG("sink index: %d\nsink name: %s", info->index,
383 info->name);
384
385 ev = calloc(1, sizeof(Epulse_Event_Sink));
386 ev->base.index = info->index;
387 ev->base.name = strdup(info->description);
388 ev->base.volume = info->volume;
389 ev->base.mute = !!info->mute;
390
391 ecore_event_add(SINK_DEFAULT, ev, _event_sink_free_cb, NULL);
392}
393
394static void
395_server_info_cb(pa_context *c, const pa_server_info *info,
396 void *userdata)
397{
398 pa_operation *o;
399
400 if (!(o = pa_context_get_sink_info_by_name(c, info->default_sink_name,
401 _sink_default_cb, userdata)))
402 {
403 ERR("pa_context_get_sink_info_by_name() failed");
404 return;
405 }
406 pa_operation_unref(o);
407}
408
409static void
410_subscribe_cb(pa_context *c, pa_subscription_event_type_t t,
411 uint32_t index, void *data)
412{
413 pa_operation *o;
414
415 switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
416 case PA_SUBSCRIPTION_EVENT_SINK:
417 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
418 PA_SUBSCRIPTION_EVENT_REMOVE)
419 _sink_remove_cb(index, data);
420 else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
421 PA_SUBSCRIPTION_EVENT_NEW)
422 {
423 if (!(o = pa_context_get_sink_info_by_index(c, index,
424 _sink_cb, data)))
425 {
426 ERR("pa_context_get_sink_info_by_index() failed");
427 return;
428 }
429 pa_operation_unref(o);
430 }
431 else
432 {
433 if (!(o = pa_context_get_sink_info_by_index(c, index,
434 _sink_changed_cb,
435 data)))
436 {
437 ERR("pa_context_get_sink_info_by_index() failed");
438 return;
439 }
440 pa_operation_unref(o);
441 }
442 break;
443
444 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
445 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
446 PA_SUBSCRIPTION_EVENT_REMOVE)
447 _sink_input_remove_cb(index, data);
448 else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
449 PA_SUBSCRIPTION_EVENT_NEW)
450 {
451 if (!(o = pa_context_get_sink_input_info(c, index,
452 _sink_input_cb, data)))
453 {
454 ERR("pa_context_get_sink_input_info() failed");
455 return;
456 }
457 pa_operation_unref(o);
458 }
459 else
460 {
461 if (!(o = pa_context_get_sink_input_info(c, index,
462 _sink_input_changed_cb,
463 data)))
464 {
465 ERR("pa_context_get_sink_input_info() failed");
466 return;
467 }
468 pa_operation_unref(o);
469 }
470 break;
471
472 case PA_SUBSCRIPTION_EVENT_SOURCE:
473 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
474 PA_SUBSCRIPTION_EVENT_REMOVE)
475 _source_remove_cb(index, data);
476 else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
477 PA_SUBSCRIPTION_EVENT_NEW)
478 {
479 if (!(o = pa_context_get_source_info_by_index(c, index,
480 _source_cb, data)))
481 {
482 ERR("pa_context_get_source_info() failed");
483 return;
484 }
485 pa_operation_unref(o);
486 }
487 else
488 {
489 if (!(o = pa_context_get_source_info_by_index(c, index,
490 _source_changed_cb,
491 data)))
492 {
493 ERR("pa_context_get_source_info() failed");
494 return;
495 }
496 pa_operation_unref(o);
497 }
498 break;
499
500 default:
501 WRN("Event not handled");
502 break;
503 }
504}
505
506static Eina_Bool _epulse_connect(void *data);
507
508static void
509_epulse_pa_state_cb(pa_context *context, void *data)
510{
511 pa_operation *o;
512
513 switch (pa_context_get_state(context))
514 {
515 case PA_CONTEXT_UNCONNECTED:
516 case PA_CONTEXT_CONNECTING:
517 case PA_CONTEXT_AUTHORIZING:
518 case PA_CONTEXT_SETTING_NAME:
519 break;
520
521 case PA_CONTEXT_READY:
522 {
523 pa_context_set_subscribe_callback(context, _subscribe_cb, ctx);
524 if (!(o = pa_context_subscribe(context, (pa_subscription_mask_t)
525 (PA_SUBSCRIPTION_MASK_SINK|
526 PA_SUBSCRIPTION_MASK_SOURCE|
527 PA_SUBSCRIPTION_MASK_SINK_INPUT|
528 PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
529 PA_SUBSCRIPTION_MASK_CLIENT|
530 PA_SUBSCRIPTION_MASK_SERVER|
531 PA_SUBSCRIPTION_MASK_CARD),
532 NULL, NULL)))
533 {
534 ERR("pa_context_subscribe() failed");
535 return;
536 }
537 pa_operation_unref(o);
538
539 if (!(o = pa_context_get_sink_info_list(context, _sink_cb, ctx)))
540 {
541 ERR("pa_context_get_sink_info_list() failed");
542 return;
543 }
544 pa_operation_unref(o);
545
546 if (!(o = pa_context_get_sink_input_info_list(context,
547 _sink_input_cb,
548 ctx)))
549 {
550 ERR("pa_context_get_sink_input_info_list() failed");
551 return;
552 }
553 pa_operation_unref(o);
554
555 if (!(o = pa_context_get_source_info_list(context, _source_cb,
556 ctx)))
557 {
558 ERR("pa_context_get_source_info_list() failed");
559 return;
560 }
561 pa_operation_unref(o);
562
563 if (!(o = pa_context_get_server_info(context, _server_info_cb,
564 ctx)))
565 {
566 ERR("pa_context_get_server_info() failed");
567 return;
568 }
569 pa_operation_unref(o);
570 break;
571 }
572
573 case PA_CONTEXT_FAILED:
574 WRN("PA_CONTEXT_FAILED");
575 ecore_event_add(DISCONNECTED, NULL, NULL, NULL);
576 _epulse_connect(data);
577 return;
578
579 case PA_CONTEXT_TERMINATED:
580 ERR("PA_CONTEXT_TERMINATE:");
581 default:
582 exit(0);
583 return;
584 }
585}
586
587static Eina_Bool
588_epulse_connect(void *data)
589{
590 pa_proplist *proplist;
591 Epulse_Context *c = data;
592
593 proplist = pa_proplist_new();
594 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "Efl Volume Control");
595 pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID,
596 "org.enlightenment.volumecontrol");
597 pa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "audio-card");
598 c->context = pa_context_new_with_proplist(&(c->api), NULL, proplist);
599 if (!c->context)
600 {
601 WRN("Could not create the pulseaudio context");
602 goto err;
603 }
604
605 pa_context_set_state_callback(c->context, _epulse_pa_state_cb, c);
606 if (pa_context_connect(c->context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0)
607 {
608 WRN("Could not connect to pulse");
609 goto err;
610 }
611
612 pa_proplist_free(proplist);
613 return ECORE_CALLBACK_DONE;
614
615 err:
616 pa_proplist_free(proplist);
617 return ECORE_CALLBACK_RENEW;
618}
619
620int
621epulse_init(void)
622{
623 if (_init_count > 0)
624 goto end;
625
626 ctx = calloc(1, sizeof(Epulse_Context));
627 if (!ctx)
628 {
629 ERR("Could not create Epulse Context");
630 return 0;
631 }
632
633 DISCONNECTED = ecore_event_type_new();
634 SINK_ADDED = ecore_event_type_new();
635 SINK_CHANGED = ecore_event_type_new();
636 SINK_DEFAULT = ecore_event_type_new();
637 SINK_REMOVED = ecore_event_type_new();
638 SINK_INPUT_ADDED = ecore_event_type_new();
639 SINK_INPUT_CHANGED = ecore_event_type_new();
640 SINK_INPUT_REMOVED = ecore_event_type_new();
641 SOURCE_ADDED = ecore_event_type_new();
642 SOURCE_CHANGED = ecore_event_type_new();
643 SOURCE_REMOVED = ecore_event_type_new();
644 SOURCE_INPUT_ADDED = ecore_event_type_new();
645 SOURCE_INPUT_REMOVED = ecore_event_type_new();
646
647 ctx->api = functable;
648 ctx->api.userdata = ctx;
649
650 /* The reason of compares with EINA_TRUE is because ECORE_CALLBACK_RENEW
651 is EINA_TRUE. The function _epulse_connect returns ECORE_CALLBACK_RENEW
652 when could not connect to pulse.
653 */
654 if (_epulse_connect(ctx) == EINA_TRUE)
655 goto err;
656
657 end:
658 _init_count++;
659 return _init_count;
660
661 err:
662 free(ctx);
663 return 0;
664}
665
666void
667epulse_shutdown(void)
668{
669 if (_init_count == 0)
670 return;
671
672 _init_count--;
673 if (_init_count > 0)
674 return;
675
676 pa_context_unref(ctx->context);
677 free(ctx);
678 ctx = NULL;
679}
680
681Eina_Bool
682epulse_source_volume_set(int index, pa_cvolume volume)
683{
684 pa_operation* o;
685 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
686
687 if (!(o = pa_context_set_source_volume_by_index(ctx->context,
688 index, &volume, NULL, NULL)))
689 {
690 ERR("pa_context_set_source_volume_by_index() failed");
691 return EINA_FALSE;
692 }
693
694 return EINA_TRUE;
695}
696
697Eina_Bool
698epulse_source_mute_set(int index, Eina_Bool mute)
699{
700 pa_operation* o;
701 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
702
703 if (!(o = pa_context_set_source_mute_by_index(ctx->context,
704 index, mute, NULL, NULL)))
705 {
706 ERR("pa_context_set_source_mute() failed");
707 return EINA_FALSE;
708 }
709
710 return EINA_TRUE;
711}
712
713Eina_Bool
714epulse_sink_volume_set(int index, pa_cvolume volume)
715{
716 pa_operation* o;
717 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
718
719 if (!(o = pa_context_set_sink_volume_by_index(ctx->context,
720 index, &volume, NULL, NULL)))
721 {
722 ERR("pa_context_set_sink_volume_by_index() failed");
723 return EINA_FALSE;
724 }
725
726 return EINA_TRUE;
727}
728
729Eina_Bool
730epulse_sink_mute_set(int index, Eina_Bool mute)
731{
732 pa_operation* o;
733 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
734
735 if (!(o = pa_context_set_sink_mute_by_index(ctx->context,
736 index, mute, NULL, NULL)))
737 {
738 ERR("pa_context_set_sink_mute() failed");
739 return EINA_FALSE;
740 }
741
742 return EINA_TRUE;
743}
744
745Eina_Bool
746epulse_sink_input_volume_set(int index, pa_cvolume volume)
747{
748 pa_operation* o;
749 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
750
751 if (!(o = pa_context_set_sink_input_volume(ctx->context,
752 index, &volume, NULL, NULL)))
753 {
754 ERR("pa_context_set_sink_input_volume_by_index() failed");
755 return EINA_FALSE;
756 }
757
758 return EINA_TRUE;
759}
760
761Eina_Bool
762epulse_sink_input_mute_set(int index, Eina_Bool mute)
763{
764 pa_operation* o;
765 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
766
767 if (!(o = pa_context_set_sink_input_mute(ctx->context,
768 index, mute, NULL, NULL)))
769 {
770 ERR("pa_context_set_sink_input_mute() failed");
771 return EINA_FALSE;
772 }
773
774 return EINA_TRUE;
775}
776
777Eina_Bool
778epulse_sink_input_move(int index, int sink_index)
779{
780 pa_operation* o;
781 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
782
783 if (!(o = pa_context_move_sink_input_by_index(ctx->context,
784 index, sink_index, NULL,
785 NULL)))
786 {
787 ERR("pa_context_move_sink_input_by_index() failed");
788 return EINA_FALSE;
789 }
790
791 return EINA_TRUE;
792}
793
794Eina_Bool
795epulse_sink_port_set(int index, const char *port)
796{
797 pa_operation* o;
798 EINA_SAFETY_ON_FALSE_RETURN_VAL((ctx && ctx->context), EINA_FALSE);
799
800 if (!(o = pa_context_set_sink_port_by_index(ctx->context,
801 index, port, NULL,
802 NULL)))
803 {
804 ERR("pa_context_set_source_port_by_index() failed");
805 return EINA_FALSE;
806 }
807
808 return EINA_TRUE;
809}
diff --git a/src/lib/epulse.h b/src/lib/epulse.h
deleted file mode 100644
index ece877a..0000000
--- a/src/lib/epulse.h
+++ /dev/null
@@ -1,64 +0,0 @@
1#include "common.h"
2
3#include <pulse/pulseaudio.h>
4
5#define PA_VOLUME_TO_INT(_vol) \
6 (((_vol+1)*100+PA_VOLUME_NORM/2)/PA_VOLUME_NORM)
7#define INT_TO_PA_VOLUME(_vol) \
8 (!_vol) ? 0 : ((PA_VOLUME_NORM*(_vol+1)-PA_VOLUME_NORM/2)/100)
9
10typedef struct _Port Port;
11struct _Port {
12 Eina_Bool active;
13 Eina_Bool available;
14 int priority;
15 char *name;
16 char *description;
17};
18
19typedef struct _Epulse_Event Epulse_Event;
20struct _Epulse_Event
21{
22 int index;
23 char *name;
24 pa_cvolume volume;
25 Eina_Bool mute;
26};
27
28typedef struct _Epulse_Event_Sink Epulse_Event_Sink;
29struct _Epulse_Event_Sink {
30 Epulse_Event base;
31 Eina_List *ports;
32};
33
34typedef struct _Epulse_Event_Sink_Input Epulse_Event_Sink_Input;
35struct _Epulse_Event_Sink_Input {
36 Epulse_Event base;
37 int sink;
38 char *icon;
39};
40
41EAPI extern int DISCONNECTED;
42EAPI extern int SINK_ADDED;
43EAPI extern int SINK_CHANGED;
44EAPI extern int SINK_DEFAULT;
45EAPI extern int SINK_REMOVED;
46EAPI extern int SINK_INPUT_ADDED;
47EAPI extern int SINK_INPUT_CHANGED;
48EAPI extern int SINK_INPUT_REMOVED;
49EAPI extern int SOURCE_ADDED;
50EAPI extern int SOURCE_CHANGED;
51EAPI extern int SOURCE_REMOVED;
52EAPI extern int SOURCE_INPUT_ADDED;
53EAPI extern int SOURCE_INPUT_REMOVED;
54
55EAPI int epulse_init(void);
56EAPI Eina_Bool epulse_source_volume_set(int index, pa_cvolume volume);
57EAPI Eina_Bool epulse_source_mute_set(int index, Eina_Bool mute);
58EAPI Eina_Bool epulse_sink_volume_set(int index, pa_cvolume volume);
59EAPI Eina_Bool epulse_sink_mute_set(int index, Eina_Bool mute);
60EAPI Eina_Bool epulse_sink_port_set(int index, const char *port);
61EAPI Eina_Bool epulse_sink_input_volume_set(int index, pa_cvolume volume);
62EAPI Eina_Bool epulse_sink_input_mute_set(int index, Eina_Bool mute);
63EAPI Eina_Bool epulse_sink_input_move(int index, int sink_index);
64EAPI void epulse_shutdown(void);
diff --git a/src/lib/epulse_ml.c b/src/lib/epulse_ml.c
deleted file mode 100644
index 9c9a2b9..0000000
--- a/src/lib/epulse_ml.c
+++ /dev/null
@@ -1,309 +0,0 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include "common.h"
6
7#include <ctype.h>
8#include <errno.h>
9
10#include <pulse/pulseaudio.h>
11
12#include <sys/time.h>
13#include <sys/types.h>
14#include <sys/socket.h>
15
16/* Ecore mainloop integration start */
17struct pa_io_event
18{
19 pa_mainloop_api *mainloop;
20 Ecore_Fd_Handler *handler;
21
22 void *userdata;
23
24 pa_io_event_flags_t flags;
25 pa_io_event_cb_t callback;
26 pa_io_event_destroy_cb_t destroy_callback;
27};
28
29static Ecore_Fd_Handler_Flags
30map_flags_to_ecore(pa_io_event_flags_t flags)
31{
32 return (Ecore_Fd_Handler_Flags)((flags & PA_IO_EVENT_INPUT ? ECORE_FD_READ : 0) |
33 (flags & PA_IO_EVENT_OUTPUT ? ECORE_FD_WRITE : 0) |
34 (flags & PA_IO_EVENT_ERROR ? ECORE_FD_ERROR : 0) |
35 (flags & PA_IO_EVENT_HANGUP ? ECORE_FD_READ : 0));
36}
37
38static Eina_Bool
39_ecore_io_wrapper(void *data, Ecore_Fd_Handler *handler)
40{
41 char buf[64];
42 pa_io_event_flags_t flags = 0;
43 pa_io_event *event = (pa_io_event *)data;
44 int fd = 0;
45
46 fd = ecore_main_fd_handler_fd_get(handler);
47 if (fd < 0) return ECORE_CALLBACK_RENEW;
48
49 if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
50 {
51 flags |= PA_IO_EVENT_INPUT;
52
53 /* Check for HUP and report */
54 if (recv(fd, buf, 64, MSG_PEEK))
55 {
56 if (errno == ESHUTDOWN || errno == ECONNRESET || errno == ECONNABORTED || errno == ENETRESET)
57 {
58 DBG("HUP condition detected");
59 flags |= PA_IO_EVENT_HANGUP;
60 }
61 }
62 }
63
64 if (ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE))
65 flags |= PA_IO_EVENT_OUTPUT;
66 if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
67 flags |= PA_IO_EVENT_ERROR;
68
69 event->callback(event->mainloop, event, fd, flags, event->userdata);
70
71 return ECORE_CALLBACK_RENEW;
72}
73
74static pa_io_event *
75_ecore_pa_io_new(pa_mainloop_api *api, int fd, pa_io_event_flags_t flags, pa_io_event_cb_t cb, void *userdata)
76{
77 pa_io_event *event;
78
79 event = calloc(1, sizeof(pa_io_event));
80 event->mainloop = api;
81 event->userdata = userdata;
82 event->callback = cb;
83 event->flags = flags;
84 event->handler = ecore_main_fd_handler_add(fd, map_flags_to_ecore(flags), _ecore_io_wrapper, event, NULL, NULL);
85
86 return event;
87}
88
89static void
90_ecore_pa_io_enable(pa_io_event *event, pa_io_event_flags_t flags)
91{
92 event->flags = flags;
93 ecore_main_fd_handler_active_set(event->handler, map_flags_to_ecore(flags));
94}
95
96static void
97_ecore_pa_io_free(pa_io_event *event)
98{
99 ecore_main_fd_handler_del(event->handler);
100 free(event);
101}
102
103static void
104_ecore_pa_io_set_destroy(pa_io_event *event, pa_io_event_destroy_cb_t cb)
105{
106 event->destroy_callback = cb;
107}
108
109/* Timed events */
110struct pa_time_event
111{
112 pa_mainloop_api *mainloop;
113 Ecore_Timer *timer;
114 struct timeval tv;
115
116 void *userdata;
117
118 pa_time_event_cb_t callback;
119 pa_time_event_destroy_cb_t destroy_callback;
120};
121
122Eina_Bool
123_ecore_time_wrapper(void *data)
124{
125 pa_time_event *event = (pa_time_event *)data;
126
127 event->callback(event->mainloop, event, &event->tv, event->userdata);
128
129 return ECORE_CALLBACK_CANCEL;
130}
131
132pa_time_event *
133_ecore_pa_time_new(pa_mainloop_api *api, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata)
134{
135 pa_time_event *event;
136 struct timeval now;
137 double interval;
138
139 event = calloc(1, sizeof(pa_time_event));
140 event->mainloop = api;
141 event->userdata = userdata;
142 event->callback = cb;
143 event->tv = *tv;
144
145 if (gettimeofday(&now, NULL) == -1)
146 {
147 ERR("Failed to get the current time!");
148 free(event);
149 return NULL;
150 }
151
152 interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
153 event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);
154
155 return event;
156}
157
158void
159_ecore_pa_time_restart(pa_time_event *event, const struct timeval *tv)
160{
161 struct timeval now;
162 double interval;
163
164 /* If tv is NULL disable timer */
165 if (!tv)
166 {
167 ecore_timer_del(event->timer);
168 event->timer = NULL;
169 return;
170 }
171
172 event->tv = *tv;
173
174 if (gettimeofday(&now, NULL) == -1)
175 {
176 ERR("Failed to get the current time!");
177 return;
178 }
179
180 interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
181 if (event->timer)
182 {
183 event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);
184 }
185 else
186 {
187 ecore_timer_interval_set(event->timer, interval);
188 ecore_timer_reset(event->timer);
189 }
190}
191
192void
193_ecore_pa_time_free(pa_time_event *event)
194{
195 if (event->timer)
196 ecore_timer_del(event->timer);
197
198 event->timer = NULL;
199
200 free(event);
201}
202
203void
204_ecore_pa_time_set_destroy(pa_time_event *event, pa_time_event_destroy_cb_t cb)
205{
206 event->destroy_callback = cb;
207}
208
209/* Deferred events */
210struct pa_defer_event
211{
212 pa_mainloop_api *mainloop;
213 Ecore_Idler *idler;
214
215 void *userdata;
216
217 pa_defer_event_cb_t callback;
218 pa_defer_event_destroy_cb_t destroy_callback;
219};
220
221Eina_Bool
222_ecore_defer_wrapper(void *data)
223{
224 pa_defer_event *event = (pa_defer_event *)data;
225
226 event->idler = NULL;
227 event->callback(event->mainloop, event, event->userdata);
228
229 return ECORE_CALLBACK_CANCEL;
230}
231
232pa_defer_event *
233_ecore_pa_defer_new(pa_mainloop_api *api, pa_defer_event_cb_t cb, void *userdata)
234{
235 pa_defer_event *event;
236
237 event = calloc(1, sizeof(pa_defer_event));
238 event->mainloop = api;
239 event->userdata = userdata;
240 event->callback = cb;
241
242 event->idler = ecore_idler_add(_ecore_defer_wrapper, event);
243
244 return event;
245}
246
247void
248_ecore_pa_defer_enable(pa_defer_event *event, int b)
249{
250 if (!b && event->idler)
251 {
252 ecore_idler_del(event->idler);
253 event->idler = NULL;
254 }
255 else if (b && !event->idler)
256 {
257 event->idler = ecore_idler_add(_ecore_defer_wrapper, event);
258 }
259}
260
261void
262_ecore_pa_defer_free(pa_defer_event *event)
263{
264 if (event->idler)
265 ecore_idler_del(event->idler);
266
267 event->idler = NULL;
268
269 free(event);
270}
271
272void
273_ecore_pa_defer_set_destroy(pa_defer_event *event, pa_defer_event_destroy_cb_t cb)
274{
275 event->destroy_callback = cb;
276}
277
278static void
279_ecore_pa_quit(pa_mainloop_api *api EINA_UNUSED, int retval EINA_UNUSED)
280{
281 /* FIXME: Need to clean up timers, etc.? */
282 WRN("Not quitting mainloop, although PA requested it");
283}
284
285/* Function table for PA mainloop integration */
286const pa_mainloop_api functable = {
287 .userdata = NULL,
288
289 .io_new = _ecore_pa_io_new,
290 .io_enable = _ecore_pa_io_enable,
291 .io_free = _ecore_pa_io_free,
292 .io_set_destroy = _ecore_pa_io_set_destroy,
293
294 .time_new = _ecore_pa_time_new,
295 .time_restart = _ecore_pa_time_restart,
296 .time_free = _ecore_pa_time_free,
297 .time_set_destroy = _ecore_pa_time_set_destroy,
298
299 .defer_new = _ecore_pa_defer_new,
300 .defer_enable = _ecore_pa_defer_enable,
301 .defer_free = _ecore_pa_defer_free,
302 .defer_set_destroy = _ecore_pa_defer_set_destroy,
303
304 .quit = _ecore_pa_quit,
305};
306
307/* *****************************************************
308 * Ecore mainloop integration end
309 */