summaryrefslogtreecommitdiff
path: root/src/bin/playbacks_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/playbacks_view.c
parentc984cf740b8625571a5d1617e0c3911fc27c11f9 (diff)
Adding common code
Init/shutdown used libraries and including common headers.
Diffstat (limited to 'src/bin/playbacks_view.c')
-rw-r--r--src/bin/playbacks_view.c375
1 files changed, 375 insertions, 0 deletions
diff --git a/src/bin/playbacks_view.c b/src/bin/playbacks_view.c
new file mode 100644
index 0000000..98edff4
--- /dev/null
+++ b/src/bin/playbacks_view.c
@@ -0,0 +1,375 @@
1#include "playbacks_view.h"
2
3#include "epulse.h"
4
5#define PLAYBACKS_KEY "playbacks.key"
6
7struct Sink
8{
9 int index;
10 const char *name;
11};
12
13struct Playbacks_View
14{
15 Evas_Object *self;
16 Evas_Object *genlist;
17 Elm_Genlist_Item_Class *itc;
18
19 Eina_List *inputs;
20 Eina_List *sinks;
21
22 Ecore_Event_Handler *sink_input_added;
23 Ecore_Event_Handler *sink_input_changed;
24 Ecore_Event_Handler *sink_input_removed;
25
26 Ecore_Event_Handler *sink_added;
27 Ecore_Event_Handler *sink_removed;
28};
29
30struct Sink_Input
31{
32 struct Playbacks_View *pv;
33
34 int index;
35 int sink_index;
36 pa_cvolume volume;
37 const char *name;
38 const char *icon;
39 Eina_Bool mute;
40
41 Elm_Object_Item *item;
42};
43
44static Eina_Bool
45_sink_input_add_cb(void *data, int type EINA_UNUSED,
46 void *info)
47{
48 struct Playbacks_View *pv = data;
49 Epulse_Event_Sink_Input *ev = info;
50 struct Sink_Input *input = calloc(1, sizeof(struct Sink_Input));
51 EINA_SAFETY_ON_NULL_RETURN_VAL(input, ECORE_CALLBACK_PASS_ON);
52
53 input->name = eina_stringshare_add(ev->base.name);
54 input->icon = eina_stringshare_add(ev->icon);
55 input->index = ev->base.index;
56 input->sink_index = ev->sink;
57 input->volume = ev->base.volume;
58 input->mute = ev->base.mute;
59 input->pv = pv;
60
61 pv->inputs = eina_list_append(pv->inputs, input);
62 input->item = elm_genlist_item_append(pv->genlist, pv->itc, input, NULL,
63 ELM_GENLIST_ITEM_NONE, NULL, pv);
64
65 return ECORE_CALLBACK_DONE;
66}
67
68static Eina_Bool
69_sink_input_removed_cb(void *data, int type EINA_UNUSED,
70 void *info)
71{
72 struct Playbacks_View *pv = data;
73 Epulse_Event_Sink_Input *ev = info;
74 Eina_List *l, *ll;
75 struct Sink_Input *input;
76
77 EINA_LIST_FOREACH_SAFE(pv->inputs, l, ll, input)
78 {
79 if (input->index == ev->base.index)
80 {
81 pv->inputs = eina_list_remove_list(pv->inputs, l);
82 elm_object_item_del(input->item);
83 break;
84 }
85 }
86
87 return ECORE_CALLBACK_DONE;
88}
89
90static Eina_Bool
91_sink_input_changed_cb(void *data, int type EINA_UNUSED,
92 void *info)
93{
94 struct Playbacks_View *pv = data;
95 Epulse_Event_Sink_Input *ev = info;
96 Eina_List *l;
97 struct Sink_Input *input;
98 Evas_Object *item = NULL;
99
100 EINA_LIST_FOREACH(pv->inputs, l, input)
101 {
102 if (input->index == ev->base.index)
103 {
104 pa_volume_t vol = pa_cvolume_avg(&ev->base.volume);
105
106 item = elm_object_item_part_content_get(input->item, "item");
107 input->volume = ev->base.volume;
108 if (item)
109 elm_slider_value_set(item, PA_VOLUME_TO_INT(vol));
110
111 item = elm_object_item_part_content_get(input->item, "mute");
112 input->mute = ev->base.mute;
113 if (item)
114 {
115 elm_check_state_set(item, input->mute);
116 }
117 break;
118 }
119 }
120
121 return ECORE_CALLBACK_DONE;
122}
123
124static Eina_Bool
125_sink_add_cb(void *data, int type EINA_UNUSED,
126 void *info)
127{
128 struct Playbacks_View *pv = data;
129 Epulse_Event_Sink *ev = info;
130 struct Sink *sink = calloc(1, sizeof(struct Sink));
131 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, ECORE_CALLBACK_PASS_ON);
132
133 sink->name = eina_stringshare_add(ev->base.name);
134 sink->index = ev->base.index;
135
136 pv->sinks = eina_list_append(pv->sinks, sink);
137 elm_genlist_realized_items_update(pv->genlist);
138
139 return ECORE_CALLBACK_PASS_ON;
140}
141
142static Eina_Bool
143_sink_removed_cb(void *data, int type EINA_UNUSED,
144 void *info)
145{
146 struct Playbacks_View *pv = data;
147 Epulse_Event_Sink *ev = info;
148 Eina_List *l, *ll;
149 struct Sink *sink;
150
151 EINA_LIST_FOREACH_SAFE(pv->sinks, l, ll, sink)
152 {
153 if (sink->index == ev->base.index)
154 {
155 pv->sinks = eina_list_remove_list(pv->sinks, l);
156 break;
157 }
158 }
159
160 elm_genlist_realized_items_update(pv->genlist);
161 return ECORE_CALLBACK_PASS_ON;
162}
163
164static void
165_del_cb(void *data,
166 Evas *e EINA_UNUSED,
167 Evas_Object *o EINA_UNUSED,
168 void *event_info EINA_UNUSED)
169{
170 struct Playbacks_View *pv = data;
171 struct Sink *sink;
172 eina_list_free(pv->inputs);
173
174 EINA_LIST_FREE(pv->sinks, sink)
175 {
176 eina_stringshare_del(sink->name);
177 free(sink);
178 }
179
180#define ECORE_EVENT_HANDLER_DEL(_handle) \
181 if (pv->_handle) \
182 { \
183 ecore_event_handler_del(pv->_handle); \
184 pv->_handle = NULL; \
185 }
186
187 ECORE_EVENT_HANDLER_DEL(sink_input_added)
188 ECORE_EVENT_HANDLER_DEL(sink_input_changed)
189 ECORE_EVENT_HANDLER_DEL(sink_input_removed)
190 ECORE_EVENT_HANDLER_DEL(sink_added)
191 ECORE_EVENT_HANDLER_DEL(sink_removed)
192#undef ECORE_EVENT_HANDLER_DEL
193}
194
195static char *
196_item_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
197{
198 struct Sink_Input *input = data;
199
200 if (!strcmp(part, "name"))
201 {
202 return strdup(input->name);
203 }
204
205 return NULL;
206}
207
208static void
209_item_del(void *data, Evas_Object *obj EINA_UNUSED)
210{
211 struct Sink_Input *input = data;
212
213 eina_stringshare_del(input->name);
214 eina_stringshare_del(input->icon);
215 free(input);
216}
217
218static void
219_volume_changed_cb(void *data, Evas_Object *o,
220 void *event_info EINA_UNUSED)
221{
222 struct Sink_Input *input = data;
223 double val = elm_slider_value_get(o);
224 pa_volume_t v = INT_TO_PA_VOLUME(val);
225
226 pa_cvolume_set(&input->volume, input->volume.channels, v);
227
228 epulse_sink_input_volume_set(input->index, input->volume);
229}
230
231static void
232_mute_changed_cb(void *data, Evas_Object *o EINA_UNUSED,
233 void *event_info EINA_UNUSED)
234{
235 struct Sink_Input *input = data;
236
237 if (!epulse_sink_input_mute_set(input->index, input->mute))
238 {
239 ERR("Could not mute the input: %d", input->index);
240 input->mute = !input->mute;
241 return;
242 }
243}
244
245static void
246_sink_selected(void *data, Evas_Object *obj, void *event_info)
247{
248 struct Sink_Input *input = data;
249 Elm_Object_Item *item = event_info;
250 struct Sink *sink = elm_object_item_data_get(item);
251
252 epulse_sink_input_move(input->index, sink->index);
253 elm_object_text_set(obj, sink->name);
254}
255
256static Evas_Object *
257_item_content_get(void *data, Evas_Object *obj, const char *part)
258{
259 Evas_Object *item = NULL;
260 struct Sink_Input *input = data;
261
262 if (!strcmp(part, "slider"))
263 {
264 pa_volume_t vol = pa_cvolume_avg(&input->volume);
265 item = elm_slider_add(obj);
266 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
267
268 elm_slider_unit_format_set(item, "%1.0f");
269 elm_slider_indicator_format_set(item, "%1.0f");
270 elm_slider_span_size_set(item, 120);
271 elm_slider_min_max_set(item, 0.0, 100.0);
272 elm_slider_value_set(item, PA_VOLUME_TO_INT(vol));
273
274 evas_object_smart_callback_add(item, "delay,changed",
275 _volume_changed_cb, input);
276 }
277 else if (!strcmp(part, "mute"))
278 {
279 item = elm_check_add(obj);
280 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
281
282 elm_object_style_set(item, "toggle");
283 elm_object_part_text_set(item, "off", "Mute");
284 elm_object_part_text_set(item, "on", "Unmute");
285
286 elm_check_state_set(item, input->mute);
287 elm_check_state_pointer_set(item, &input->mute);
288 evas_object_smart_callback_add(item, "changed", _mute_changed_cb,
289 input);
290 }
291 else if (!strcmp(part, "icon"))
292 {
293 EINA_SAFETY_ON_NULL_RETURN_VAL(input->icon, NULL);
294
295 item = elm_icon_add(obj);
296 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
297
298 elm_icon_standard_set(item, input->icon);
299 }
300 else if (!strcmp(part, "hover"))
301 {
302 Eina_List *l;
303 struct Sink *sink;
304 item = elm_hoversel_add(obj);
305
306 EINA_LIST_FOREACH(input->pv->sinks, l, sink)
307 {
308 if (sink->index == input->sink_index)
309 elm_object_text_set(item, sink->name);
310 elm_hoversel_item_add(item, sink->name, NULL,
311 ELM_ICON_NONE, NULL, sink);
312 }
313 evas_object_smart_callback_add(item, "selected",
314 _sink_selected, input);
315 }
316
317 return item;
318}
319
320Evas_Object *
321playbacks_view_add(Evas_Object *parent)
322{
323 Evas_Object *layout;
324 struct Playbacks_View *pv;
325
326 pv = calloc(1, sizeof(struct Playbacks_View));
327 EINA_SAFETY_ON_NULL_RETURN_VAL(pv, NULL);
328
329 layout = epulse_layout_add(parent, "playbacks", "default");
330 EINA_SAFETY_ON_NULL_GOTO(layout, err);
331
332 evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL, _del_cb, pv);
333
334 pv->genlist = elm_genlist_add(layout);
335 EINA_SAFETY_ON_NULL_GOTO(pv->genlist, err_genlist);
336
337 pv->sink_input_added = ecore_event_handler_add(SINK_INPUT_ADDED,
338 _sink_input_add_cb, pv);
339 pv->sink_input_added = ecore_event_handler_add(SINK_INPUT_CHANGED,
340 _sink_input_changed_cb, pv);
341 pv->sink_input_removed = ecore_event_handler_add(SINK_INPUT_REMOVED,
342 _sink_input_removed_cb, pv);
343 pv->sink_added = ecore_event_handler_add(SINK_ADDED,
344 _sink_add_cb, pv);
345 pv->sink_removed = ecore_event_handler_add(SINK_REMOVED,
346 _sink_removed_cb, pv);
347
348 pv->itc = elm_genlist_item_class_new();
349 EINA_SAFETY_ON_NULL_GOTO(pv->itc, err_genlist);
350 pv->itc->item_style = "playbacks";
351 pv->itc->func.text_get = _item_text_get;
352 pv->itc->func.content_get = _item_content_get;
353 pv->itc->func.del = _item_del;
354
355 evas_object_data_set(layout, PLAYBACKS_KEY, pv);
356 elm_layout_content_set(layout, "list", pv->genlist);
357
358 evas_object_size_hint_weight_set(pv->genlist, EVAS_HINT_EXPAND,
359 EVAS_HINT_EXPAND);
360 evas_object_size_hint_align_set(pv->genlist, EVAS_HINT_FILL,
361 EVAS_HINT_FILL);
362
363 return layout;
364
365 err_genlist:
366 ecore_event_handler_del(pv->sink_input_added);
367 ecore_event_handler_del(pv->sink_input_changed);
368 ecore_event_handler_del(pv->sink_input_removed);
369 ecore_event_handler_del(pv->sink_added);
370 ecore_event_handler_del(pv->sink_removed);
371 free(layout);
372 err:
373 free(pv);
374 return NULL;
375}