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