resetting manifest requested domain to floor
[platform/core/multimedia/avsystem.git] / avsys-audio-pactrl.c
1 /*
2  * avsystem
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jonghyuk Choi <jhchoi.choi@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <string.h>
23 #include <stdio.h>
24
25 #include "avsys-audio-pactrl.h"
26 #include "avsys-debug.h"
27
28 enum {
29         AVSYS_PA_CTL_CMD_VOLUME,
30         AVSYS_PA_CTL_CMD_MUTE,
31         AVSYS_PA_CTL_CMD_GET_SINK_INFO,
32         AVSYS_PA_CTL_CMD_GET_DEFAULT_SINK,
33         AVSYS_PA_CTL_CMD_MAX,
34 };
35
36 typedef struct avsys_pa_ctrl_info {
37         pa_threaded_mainloop *m;
38         int cmd;
39         int mute;
40         int idx;
41         int vol;
42         int ch;
43         int res;
44 } avsys_pa_ctrl_info_t;
45
46 static void __avsys_audio_pa_ctrl_success_cb(pa_context *c, int success, void *userdata)
47 {
48         pa_threaded_mainloop *mainloop = (pa_threaded_mainloop *)userdata;
49         avsys_assert_r(c);
50         avsys_assert_r(mainloop);
51
52         if (!success) {
53                 avsys_error(AVAUDIO, "pa control failed\n");
54         } else {
55                 avsys_info(AVAUDIO, "pa control success\n");
56         }
57         pa_threaded_mainloop_signal(mainloop, 0);
58 }
59
60 static void __avsys_audio_pa_ctrl_get_sink_info_cb(pa_context *c, const pa_sink_info *i, int is_last, void *userdata)
61 {
62         avsys_pa_ctrl_info_t *info = NULL;
63         avsys_assert_r(userdata);
64         info = (avsys_pa_ctrl_info_t *)userdata;
65         int sink_state;
66         int sink_name;
67
68         if (is_last < 0) {
69                 avsys_error(AVAUDIO, "Failed to get sink information: %s", pa_strerror(pa_context_errno(c)));
70                 return;
71         }
72
73         if (is_last) {
74                 pa_threaded_mainloop_signal(info->m, 0);
75                 return;
76         }
77
78         avsys_assert_r(i);
79
80         if (!strncmp(i->name, "alsa_", 4)) {
81                 sink_name = ALSA_SINK;
82         } else if (!strncmp(i->name, "bluez", 5)) {
83                 sink_name = BLUEZ_SINK;
84         } else {
85                 return;
86         }
87
88         switch (i->state) {
89         case PA_SINK_RUNNING:
90                 sink_state = _ACTIVE;
91                 break;
92         case PA_SINK_IDLE:
93         case PA_SINK_SUSPENDED:
94                 sink_state = _DEACTIVE;
95                 break;
96         default:
97                 sink_state = _EXIST;
98                 break;
99         }
100
101         info->res |= ((1 << (sink_state + sink_name)));
102 }
103
104 static void __avsys_audio_pa_ctrl_get_server_info_cb(pa_context *c, const pa_server_info *i, void *userdata)
105 {
106         avsys_pa_ctrl_info_t *info = NULL;
107         avsys_assert_r(userdata);
108         info = (avsys_pa_ctrl_info_t *)userdata;
109
110         if (!i) {
111                 info->res = AVSYS_AUDIO_PA_CTL_SINK_UNKNOWN;
112         } else {
113                 if (strstr(i->default_sink_name, "alsa_"))
114                         info->res = AVSYS_AUDIO_PA_CTL_SINK_ALSA;
115                 else if (strstr(i->default_sink_name, "bluez"))
116                         info->res = AVSYS_AUDIO_PA_CTL_SINK_BLUEZ;
117                 else
118                         info->res = AVSYS_AUDIO_PA_CTL_SINK_UNKNOWN;
119         }
120         pa_threaded_mainloop_signal(info->m, 0);
121 }
122
123 static void __avsys_audio_pa_ctrl_state_cb(pa_context *c, void *userdata)
124 {
125         pa_cvolume cv;
126         avsys_pa_ctrl_info_t *info = NULL;
127
128         avsys_assert_r(c);
129         info = (avsys_pa_ctrl_info_t *)userdata;
130         avsys_assert_r(info);
131         avsys_assert_r(info->m);
132
133         switch (pa_context_get_state(c)) {
134         case PA_CONTEXT_READY:
135                 if (info->cmd == AVSYS_PA_CTL_CMD_VOLUME) {
136                         pa_cvolume_set(&cv, info->ch, info->vol);
137                         pa_operation_unref(pa_context_set_sink_input_volume(c, info->idx, &cv, __avsys_audio_pa_ctrl_success_cb, (void *)info->m));
138                 } else if (info->cmd == AVSYS_PA_CTL_CMD_MUTE) {
139                         pa_operation_unref(pa_context_set_sink_input_mute(c, info->idx, info->mute, __avsys_audio_pa_ctrl_success_cb, (void *)info->m));
140                 } else if (info->cmd == AVSYS_PA_CTL_CMD_GET_SINK_INFO) {
141                         pa_operation_unref(pa_context_get_sink_info_list(c, __avsys_audio_pa_ctrl_get_sink_info_cb, (void *)info));
142                 } else if (info->cmd == AVSYS_PA_CTL_CMD_GET_DEFAULT_SINK) {
143                         pa_operation_unref(pa_context_get_server_info(c, __avsys_audio_pa_ctrl_get_server_info_cb, (void *)info));
144                 }
145                 break;
146         case PA_CONTEXT_TERMINATED:
147         case PA_CONTEXT_FAILED:
148                 pa_threaded_mainloop_signal(info->m, 0);
149                 break;
150
151         case PA_CONTEXT_UNCONNECTED:
152         case PA_CONTEXT_CONNECTING:
153         case PA_CONTEXT_AUTHORIZING:
154         case PA_CONTEXT_SETTING_NAME:
155                 break;
156         }
157 }
158
159 int avsys_audio_pa_ctrl_volume_by_index(unsigned int idx, int volume, int ch)
160 {
161         pa_threaded_mainloop *mainloop = NULL;
162         pa_context *context = NULL;
163         int error = PA_ERR_INTERNAL;
164         avsys_pa_ctrl_info_t *info = NULL;
165
166         if (volume < 0 || volume > 65535) {
167                 avsys_error(AVAUDIO, "invalid volume value %d\n", volume);
168                 return AVSYS_STATE_ERR_INVALID_PARAMETER;
169         }
170         if (ch < 0) {
171                 avsys_error(AVAUDIO, "invalid channel value\n", ch);
172                 return AVSYS_STATE_ERR_INVALID_PARAMETER;
173         }
174
175         if (!(mainloop = pa_threaded_mainloop_new()))
176                 goto fail;
177
178         if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), NULL)))
179                 goto fail;
180
181         if (!(info = (avsys_pa_ctrl_info_t *)calloc(sizeof(avsys_pa_ctrl_info_t), 1)))
182                 goto fail;
183
184         info->m = mainloop;
185         info->cmd = AVSYS_PA_CTL_CMD_VOLUME;
186         info->idx = idx;
187         info->vol = volume;
188         info->ch = ch;
189         pa_context_set_state_callback(context, __avsys_audio_pa_ctrl_state_cb, (void *)info);
190
191         if (pa_context_connect(context, NULL, 0, NULL) < 0) {
192                 error = pa_context_errno(context);
193                 goto fail;
194         }
195
196         pa_threaded_mainloop_lock(mainloop);
197
198         if (pa_threaded_mainloop_start(mainloop) < 0)
199                 goto unlock_and_fail;
200
201         for (;;) {
202                 pa_context_state_t state;
203
204                 state = pa_context_get_state(context);
205
206                 if (state == PA_CONTEXT_READY)
207                         break;
208
209                 if (!PA_CONTEXT_IS_GOOD(state)) {
210                         error = pa_context_errno(context);
211                         goto unlock_and_fail;
212                 }
213
214                 /* Wait until the context is ready */
215                 pa_threaded_mainloop_wait(mainloop);
216         }
217
218         pa_threaded_mainloop_unlock(mainloop);
219
220         pa_threaded_mainloop_stop(mainloop);
221         pa_context_disconnect(context);
222         pa_context_unref(context);
223         pa_threaded_mainloop_free(mainloop);
224         free(info);
225
226         return AVSYS_STATE_SUCCESS;     /* for success */
227
228 unlock_and_fail:
229         pa_threaded_mainloop_unlock(mainloop);
230
231         if (mainloop)
232                 pa_threaded_mainloop_stop(mainloop);
233
234         if (context)
235                 pa_context_disconnect(context);
236
237 fail:
238         avsys_error(AVAUDIO, "pa error : %s\n", pa_strerror(error));
239
240         if (context)
241                 pa_context_unref(context);
242
243         if (mainloop)
244                 pa_threaded_mainloop_free(mainloop);
245
246         if (info)
247                 free(info);
248
249         return AVSYS_STATE_ERR_INTERNAL;
250 }
251
252 int avsys_audio_pa_ctrl_mute_by_index(unsigned int idx, int mute)
253 {
254         pa_threaded_mainloop *mainloop = NULL;
255         pa_context *context = NULL;
256         int error = PA_ERR_INTERNAL;
257         avsys_pa_ctrl_info_t *info = NULL;
258
259         if (mute != AVSYS_AUDIO_MUTE && mute != AVSYS_AUDIO_UNMUTE) {
260                 avsys_error(AVAUDIO, "invalid mute value %d\n", mute);
261                 return AVSYS_STATE_ERR_INVALID_PARAMETER;
262         }
263
264         if (!(mainloop = pa_threaded_mainloop_new()))
265                 goto fail;
266
267         if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), NULL)))
268                 goto fail;
269
270         if (!(info = (avsys_pa_ctrl_info_t *)calloc(sizeof(avsys_pa_ctrl_info_t), 1)))
271                 goto fail;
272
273         info->m = mainloop;
274         info->cmd = AVSYS_PA_CTL_CMD_MUTE;
275         info->idx = idx;
276         info->mute = mute;
277
278         pa_context_set_state_callback(context, __avsys_audio_pa_ctrl_state_cb, (void *)info);
279
280         if (pa_context_connect(context, NULL, 0, NULL) < 0) {
281                 error = pa_context_errno(context);
282                 goto fail;
283         }
284
285         pa_threaded_mainloop_lock(mainloop);
286
287         if (pa_threaded_mainloop_start(mainloop) < 0)
288                 goto unlock_and_fail;
289
290         for (;;) {
291                 pa_context_state_t state;
292
293                 state = pa_context_get_state(context);
294
295                 if (state == PA_CONTEXT_READY)
296                         break;
297
298                 if (!PA_CONTEXT_IS_GOOD(state)) {
299                         error = pa_context_errno(context);
300                         goto unlock_and_fail;
301                 }
302
303                 /* Wait until the context is ready */
304                 pa_threaded_mainloop_wait(mainloop);
305         }
306
307         pa_threaded_mainloop_unlock(mainloop);
308
309         pa_threaded_mainloop_stop(mainloop);
310         pa_context_disconnect(context);
311         pa_context_unref(context);
312         pa_threaded_mainloop_free(mainloop);
313         free(info);
314
315         return AVSYS_STATE_SUCCESS;     /* for success */
316
317 unlock_and_fail:
318         pa_threaded_mainloop_unlock(mainloop);
319
320         if (mainloop)
321                 pa_threaded_mainloop_stop(mainloop);
322
323         if (context)
324                 pa_context_disconnect(context);
325
326 fail:
327         avsys_error(AVAUDIO, "pa error : %s\n", pa_strerror(error));
328
329         if (context)
330                 pa_context_unref(context);
331
332         if (mainloop)
333                 pa_threaded_mainloop_free(mainloop);
334
335         if (info)
336                 free(info);
337
338         return AVSYS_STATE_ERR_INTERNAL;
339 }
340
341 int avsys_audio_pa_ctrl_get_default_sink(int *sink)
342 {
343         pa_threaded_mainloop *mainloop = NULL;
344         pa_context *context = NULL;
345         int error = PA_ERR_INTERNAL;
346         avsys_pa_ctrl_info_t *info = NULL;
347
348         if (!sink)
349                 return AVSYS_STATE_ERR_INVALID_PARAMETER;
350
351         if (!(mainloop = pa_threaded_mainloop_new()))
352                 goto fail;
353
354         if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), NULL)))
355                 goto fail;
356
357         if (!(info = (avsys_pa_ctrl_info_t *)calloc(sizeof(avsys_pa_ctrl_info_t), 1)))
358                 goto fail;
359
360         info->m = mainloop;
361         info->cmd = AVSYS_PA_CTL_CMD_GET_DEFAULT_SINK;
362
363         pa_context_set_state_callback(context, __avsys_audio_pa_ctrl_state_cb, (void *)info);
364
365         if (pa_context_connect(context, NULL, 0, NULL) < 0) {
366                 error = pa_context_errno(context);
367                 goto fail;
368         }
369
370         pa_threaded_mainloop_lock(mainloop);
371
372         if (pa_threaded_mainloop_start(mainloop) < 0)
373                 goto unlock_and_fail;
374
375         for (;;) {
376                 pa_context_state_t state;
377
378                 state = pa_context_get_state(context);
379
380                 if (state == PA_CONTEXT_READY)
381                         break;
382
383                 if (!PA_CONTEXT_IS_GOOD(state)) {
384                         error = pa_context_errno(context);
385                         goto unlock_and_fail;
386                 }
387
388                 /* Wait until the context is ready */
389                 pa_threaded_mainloop_wait(mainloop);
390         }
391
392         *sink = info->res;
393
394         pa_threaded_mainloop_unlock(mainloop);
395
396         pa_threaded_mainloop_stop(mainloop);
397         pa_context_disconnect(context);
398         pa_context_unref(context);
399         pa_threaded_mainloop_free(mainloop);
400         free(info);
401
402         return AVSYS_STATE_SUCCESS;     /* for success */
403
404 unlock_and_fail:
405         pa_threaded_mainloop_unlock(mainloop);
406
407         if (mainloop)
408                 pa_threaded_mainloop_stop(mainloop);
409
410         if (context)
411                 pa_context_disconnect(context);
412
413 fail:
414         avsys_error(AVAUDIO, "pa error : %s\n", pa_strerror(error));
415
416         if (context)
417                 pa_context_unref(context);
418
419         if (mainloop)
420                 pa_threaded_mainloop_free(mainloop);
421
422         if (info)
423                 free(info);
424
425         return AVSYS_STATE_ERR_INTERNAL;
426 }