update for beta release
[framework/uifw/e17.git] / src / modules / mixer / serial.c
1 #include "pa.h"
2
3 static void
4 deserialize_sinks_watcher(Pulse *conn, Pulse_Tag *tag)
5 {
6    pa_subscription_event_type_t e;
7    uint32_t idx;
8
9    EINA_SAFETY_ON_FALSE_RETURN(untag_uint32(tag, &e));
10    EINA_SAFETY_ON_FALSE_RETURN(untag_uint32(tag, &idx));
11
12    if (e & PA_SUBSCRIPTION_EVENT_CHANGE)
13      {
14         Pulse_Sink *sink;
15
16         sink = eina_hash_find(pulse_sinks, &idx);
17         if (sink)
18           {
19              if (pulse_sink_get(conn, idx))
20                sink->update = EINA_TRUE;
21           }
22         else
23           {
24              sink = eina_hash_find(pulse_sources, &idx);
25              if (!sink) return;
26              if (pulse_source_get(conn, idx))
27                sink->update = EINA_TRUE;
28           }
29      }
30 }
31
32 static Pulse_Sink *
33 deserialize_sink(Pulse *conn __UNUSED__, Pulse_Tag *tag, Eina_Bool source)
34 {
35    Pulse_Sink *sink = NULL;
36    Eina_Bool mute, exist;
37    pa_sample_spec spec;
38    uint32_t owner_module, monitor_source, flags, base_volume, state, n_volume_steps, card, n_ports;
39    uint64_t latency, configured_latency;
40    const char *monitor_source_name, *driver;
41    Eina_Hash *props;
42    unsigned int x;
43
44    monitor_source_name = driver = NULL;
45    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &x), error);
46    if (source && pulse_sources)
47      sink = eina_hash_find(pulse_sources, &x);
48    else if ((!source) && pulse_sinks)
49      sink = eina_hash_find(pulse_sinks, &x);
50    exist = !!sink;
51    if (!sink) sink = calloc(1, sizeof(Pulse_Sink));
52    sink->index = x;
53    EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &sink->name), error);
54    EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &sink->description), error);
55    EINA_SAFETY_ON_FALSE_GOTO(untag_sample(tag, &spec), error);
56    EINA_SAFETY_ON_FALSE_GOTO(untag_channel_map(tag, &sink->channel_map), error);
57    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &owner_module), error);
58    EINA_SAFETY_ON_FALSE_GOTO(untag_cvol(tag, &sink->volume), error);
59    EINA_SAFETY_ON_FALSE_GOTO(untag_bool(tag, &mute), error);
60    sink->mute = !!mute;
61    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &monitor_source), error);
62    EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &monitor_source_name), error);
63    eina_stringshare_del(monitor_source_name);
64    EINA_SAFETY_ON_FALSE_GOTO(untag_usec(tag, &latency), error);
65    EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &driver), error);
66    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &flags), error);
67    EINA_SAFETY_ON_FALSE_GOTO(untag_proplist(tag, &props), error);
68    eina_hash_free(props);
69    EINA_SAFETY_ON_FALSE_GOTO(untag_usec(tag, &configured_latency), error);
70    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &base_volume), error);
71    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &state), error);
72    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &n_volume_steps), error);
73    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &card), error);
74    EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &n_ports), error);
75
76    for (x = 0; x < n_ports; x++)
77      {
78         Pulse_Sink_Port_Info *pi;
79
80         pi = calloc(1, sizeof(Pulse_Sink_Port_Info));
81         EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &pi->name), error);
82         eina_stringshare_del(pi->name);
83         EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &pi->description), error);
84         eina_stringshare_del(pi->description);
85         EINA_SAFETY_ON_FALSE_GOTO(untag_uint32(tag, &pi->priority), error);
86         sink->ports = eina_list_append(sink->ports, pi);
87      }
88    EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &sink->active_port), error);
89    if (exist)
90      ecore_event_add(PULSE_EVENT_CHANGE, sink, pulse_fake_free, NULL);
91    else
92      {
93         if (source && (!pulse_sources))
94           pulse_sources = eina_hash_int32_new((Eina_Free_Cb)pulse_sink_free);
95         else if ((!source) && (!pulse_sinks))
96           pulse_sinks = eina_hash_int32_new((Eina_Free_Cb)pulse_sink_free);
97         eina_hash_add(source ? pulse_sources : pulse_sinks, (uintptr_t*)&sink->index, sink);
98      }
99    return sink;
100 error:
101    pulse_sink_free(sink);
102    return NULL;
103 }
104
105 Eina_Bool
106 deserialize_tag(Pulse *conn, PA_Commands command, Pulse_Tag *tag)
107 {
108    Pulse_Cb cb;
109    void *ev = (!command) ? NULL : PULSE_SUCCESS;
110
111    cb = eina_hash_find(conn->tag_cbs, &tag->tag_count);
112    if (command == PA_COMMAND_SUBSCRIBE)
113      conn->watching = EINA_TRUE;
114    switch (command)
115      {
116       case PA_COMMAND_GET_SINK_INFO_LIST:
117       case PA_COMMAND_GET_SOURCE_INFO_LIST:
118         if (!cb) return EINA_TRUE;
119         ev = NULL;
120         while (tag->size < tag->dsize - PA_TAG_SIZE_STRING_NULL)
121           {
122              Pulse_Sink *sink;
123
124              sink = deserialize_sink(conn, tag, (command == PA_COMMAND_GET_SOURCE_INFO_LIST));
125              if (!sink)
126                {
127                   EINA_LIST_FREE(ev, sink)
128                     pulse_sink_free(sink);
129                   break;
130                }
131              ev = eina_list_append(ev, sink);
132           }
133         break;
134       case PA_COMMAND_GET_SINK_INFO:
135       case PA_COMMAND_GET_SOURCE_INFO:
136         if ((!cb) && (!conn->watching)) return EINA_TRUE;
137         ev = deserialize_sink(conn, tag, (command == PA_COMMAND_GET_SOURCE_INFO));
138         break;
139       case 0:
140         deserialize_sinks_watcher(conn, tag);
141         return EINA_TRUE;
142       default:
143         break;
144      }
145    if (!cb) return EINA_TRUE;
146    eina_hash_del_by_key(conn->tag_cbs, &tag->tag_count);
147    cb(conn, tag->tag_count, ev);
148
149    return EINA_TRUE;
150 }