summaryrefslogtreecommitdiff
path: root/src/bin/sinks_view.c
diff options
context:
space:
mode:
authorFlavio Ceolin <flavio.ceolin@gmail.com>2013-09-01 19:41:13 -0300
committerFlavio Ceolin <flavio.ceolin@gmail.com>2014-04-03 16:23:04 -0300
commit196cdb70b84958dd827797f86e78abd798e48cf7 (patch)
treefa94c67c0794b8dd8d64b8e216daccc20801c584 /src/bin/sinks_view.c
parentc984cf740b8625571a5d1617e0c3911fc27c11f9 (diff)
Adding common code
Init/shutdown used libraries and including common headers.
Diffstat (limited to 'src/bin/sinks_view.c')
-rw-r--r--src/bin/sinks_view.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/src/bin/sinks_view.c b/src/bin/sinks_view.c
new file mode 100644
index 0000000..7ddea2c
--- /dev/null
+++ b/src/bin/sinks_view.c
@@ -0,0 +1,320 @@
1#include "sinks_view.h"
2
3#include "epulse.h"
4
5#define SINKS_KEY "sinks.key"
6
7struct Sink
8{
9 int index;
10 pa_cvolume volume;
11 const char *name;
12 Eina_Bool mute;
13
14 Elm_Object_Item *item;
15 Eina_List *ports;
16};
17
18struct Sink_Port
19{
20 char *name;
21 Eina_Bool active;
22};
23
24struct Sinks_View
25{
26 Evas_Object *self;
27 Evas_Object *genlist;
28 Elm_Genlist_Item_Class *itc;
29
30 Eina_List *sinks;
31 Ecore_Event_Handler *sink_added;
32 Ecore_Event_Handler *sink_changed;
33 Ecore_Event_Handler *sink_removed;
34};
35
36
37static Eina_Bool
38_sink_add_cb(void *data, int type EINA_UNUSED, void *info)
39{
40 struct Sinks_View *sv = data;
41 struct Sink_Port *sp;
42 Epulse_Event_Sink *ev = info;
43 Port *port;
44 Eina_List *l;
45 struct Sink *sink = calloc(1, sizeof(struct Sink));
46 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, ECORE_CALLBACK_PASS_ON);
47
48 sink->name = eina_stringshare_add(ev->base.name);
49 sink->index = ev->base.index;
50 sink->volume = ev->base.volume;
51 sink->mute = ev->base.mute;
52
53 EINA_LIST_FOREACH(ev->ports, l, port)
54 {
55 sp = calloc(1, sizeof(struct Sink_Port));
56 sp->name = strdup(port->name);
57 if (port->active)
58 sp->active = EINA_TRUE;
59 sink->ports = eina_list_append(sink->ports, sp);
60 }
61
62 sv->sinks = eina_list_append(sv->sinks, sink);
63 sink->item = elm_genlist_item_append(sv->genlist, sv->itc, sink, NULL,
64 ELM_GENLIST_ITEM_NONE, NULL, sv);
65
66 return ECORE_CALLBACK_PASS_ON;
67}
68
69static Eina_Bool
70_sink_removed_cb(void *data, int type EINA_UNUSED, void *info)
71{
72 struct Sinks_View *sv = data;
73 Epulse_Event_Sink *ev = info;
74 Eina_List *l, *ll;
75 struct Sink *sink;
76
77 EINA_LIST_FOREACH_SAFE(sv->sinks, l, ll, sink)
78 {
79 if (sink->index == ev->base.index)
80 {
81 sv->sinks = eina_list_remove_list(sv->sinks, l);
82 elm_object_item_del(sink->item);
83 break;
84 }
85 }
86
87 return ECORE_CALLBACK_PASS_ON;
88}
89
90static Eina_Bool
91_sink_changed_cb(void *data, int type EINA_UNUSED, void *info)
92{
93 struct Sinks_View *sv = data;
94 Epulse_Event_Sink *ev = info;
95 Eina_List *l;
96 struct Sink *sink;
97 Evas_Object *item = NULL;
98
99 EINA_LIST_FOREACH(sv->sinks, l, sink)
100 {
101 if (sink->index == ev->base.index)
102 {
103 pa_volume_t vol = pa_cvolume_avg(&ev->base.volume);
104
105 item = elm_object_item_part_content_get(sink->item, "slider");
106 sink->volume = ev->base.volume;
107 if (item)
108 elm_slider_value_set(item, PA_VOLUME_TO_INT(vol));
109
110 item = elm_object_item_part_content_get(sink->item, "mute");
111 sink->mute = ev->base.mute;
112 if (item)
113 elm_check_state_set(item, sink->mute);
114
115 break;
116 }
117 }
118
119 return ECORE_CALLBACK_DONE;
120}
121
122static void
123_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED,
124 void *event_info EINA_UNUSED)
125{
126 struct Sinks_View *sv = data;
127
128 eina_list_free(sv->sinks);
129 if (sv->sink_added)
130 {
131 ecore_event_handler_del(sv->sink_added);
132 sv->sink_added = NULL;
133 }
134 if (sv->sink_changed)
135 {
136 ecore_event_handler_del(sv->sink_changed);
137 sv->sink_changed = NULL;
138 }
139 if (sv->sink_removed)
140 {
141 ecore_event_handler_del(sv->sink_removed);
142 sv->sink_removed = NULL;
143 }
144}
145
146static char *
147_item_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
148{
149 struct Sink *sink = data;
150
151 if (!strcmp(part, "name"))
152 {
153 return strdup(sink->name);
154 }
155
156 return NULL;
157}
158
159static void
160_item_del(void *data, Evas_Object *obj EINA_UNUSED)
161{
162 struct Sink *sink = data;
163 struct Sink_Port *port;
164
165 eina_stringshare_del(sink->name);
166 EINA_LIST_FREE(sink->ports, port)
167 {
168 free(port->name);
169 free(port);
170 }
171 free(sink);
172}
173
174static void
175_volume_changed_cb(void *data, Evas_Object *o,
176 void *event_info EINA_UNUSED)
177{
178 struct Sink *sink = data;
179 double val = elm_slider_value_get(o);
180 pa_volume_t v = INT_TO_PA_VOLUME(val);
181
182 pa_cvolume_set(&sink->volume, sink->volume.channels, v);
183
184 epulse_sink_volume_set(sink->index, sink->volume);
185}
186
187static void
188_mute_changed_cb(void *data, Evas_Object *o EINA_UNUSED,
189 void *event_info EINA_UNUSED)
190{
191 struct Sink *sink = data;
192
193 if (!epulse_sink_mute_set(sink->index, sink->mute))
194 {
195 ERR("Could not mute the sink: %d", sink->index);
196 sink->mute = !sink->mute;
197 return;
198 }
199}
200
201static void
202_port_selected_cb(void *data, Evas_Object *o,
203 void *event_info EINA_UNUSED)
204{
205 struct Sink *sink = data;
206 Elm_Object_Item *item = event_info;
207 struct Sink_Port *port = elm_object_item_data_get(item);
208
209 if (!epulse_sink_port_set(sink->index, port->name))
210 ERR("Could not change the port");
211 else
212 elm_object_text_set(o, port->name);
213}
214
215static Evas_Object *
216_item_content_get(void *data, Evas_Object *obj, const char *part)
217{
218 Evas_Object *item = NULL;
219 struct Sink *sink = data;
220
221 if (!strcmp(part, "slider"))
222 {
223 pa_volume_t vol = pa_cvolume_avg(&sink->volume);
224 item = elm_slider_add(obj);
225 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
226
227 elm_slider_unit_format_set(item, "%1.0f");
228 elm_slider_indicator_format_set(item, "%1.0f");
229 elm_slider_span_size_set(item, 120);
230 elm_slider_min_max_set(item, 0.0, 100.0);
231 elm_slider_value_set(item, PA_VOLUME_TO_INT(vol));
232 evas_object_smart_callback_add(item, "delay,changed",
233 _volume_changed_cb, sink);
234 }
235 else if (!strcmp(part, "mute"))
236 {
237 item = elm_check_add(obj);
238 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
239
240 elm_object_style_set(item, "toggle");
241 elm_object_part_text_set(item, "off", "Mute");
242 elm_object_part_text_set(item, "on", "Unmute");
243
244 elm_check_state_set(item, sink->mute);
245 elm_check_state_pointer_set(item, &sink->mute);
246 evas_object_smart_callback_add(item, "changed", _mute_changed_cb,
247 sink);
248 }
249 else if (!strcmp(part, "hover"))
250 {
251 Eina_List *l;
252 struct Sink_Port *sp;
253
254 if (sink->ports)
255 item = elm_hoversel_add(obj);
256
257 EINA_LIST_FOREACH(sink->ports, l, sp)
258 {
259 elm_hoversel_item_add(item, sp->name, NULL,
260 ELM_ICON_NONE, NULL, sp);
261 if (sp->active)
262 elm_object_text_set(item, sp->name);
263 }
264 evas_object_smart_callback_add(item, "selected",
265 _port_selected_cb, sink);
266 }
267
268 return item;
269}
270
271
272Evas_Object *
273sinks_view_add(Evas_Object *parent)
274{
275 Evas_Object *layout;
276 struct Sinks_View *sv;
277
278 sv = calloc(1, sizeof(struct Sinks_View));
279 EINA_SAFETY_ON_NULL_RETURN_VAL(sv, NULL);
280
281 layout = epulse_layout_add(parent, "sinks", "default");
282 EINA_SAFETY_ON_NULL_GOTO(layout, err);
283
284 evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, _del_cb, sv);
285
286 sv->genlist = elm_genlist_add(layout);
287 EINA_SAFETY_ON_NULL_GOTO(sv->genlist, err_genlist);
288
289 sv->sink_added = ecore_event_handler_add(SINK_ADDED, _sink_add_cb, sv);
290 sv->sink_added = ecore_event_handler_add(SINK_CHANGED, _sink_changed_cb, sv);
291 sv->sink_removed = ecore_event_handler_add(SINK_REMOVED,
292 _sink_removed_cb, sv);
293
294 sv->itc = elm_genlist_item_class_new();
295 EINA_SAFETY_ON_NULL_GOTO(sv->itc, err_genlist);
296 sv->itc->item_style = "sinks";
297 sv->itc->func.text_get = _item_text_get;
298 sv->itc->func.content_get = _item_content_get;
299 sv->itc->func.del = _item_del;
300
301 evas_object_data_set(layout, SINKS_KEY, sv);
302 elm_layout_content_set(layout, "list", sv->genlist);
303
304 evas_object_size_hint_weight_set(sv->genlist, EVAS_HINT_EXPAND,
305 EVAS_HINT_EXPAND);
306 evas_object_size_hint_align_set(sv->genlist, EVAS_HINT_FILL,
307 EVAS_HINT_FILL);
308
309 return layout;
310
311 err_genlist:
312 ecore_event_handler_del(sv->sink_added);
313 ecore_event_handler_del(sv->sink_changed);
314 ecore_event_handler_del(sv->sink_removed);
315 free(layout);
316 err:
317 free(sv);
318
319 return NULL;
320}