4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jonghyuk Choi <jhchoi.choi@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #include "avsys-audio-pactrl.h"
26 #include "avsys-debug.h"
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,
36 typedef struct avsys_pa_ctrl_info {
37 pa_threaded_mainloop *m;
44 } avsys_pa_ctrl_info_t;
46 static void __avsys_audio_pa_ctrl_success_cb(pa_context *c, int success, void *userdata)
48 pa_threaded_mainloop *mainloop = (pa_threaded_mainloop *)userdata;
50 avsys_assert_r(mainloop);
53 avsys_error(AVAUDIO, "pa control failed\n");
55 avsys_info(AVAUDIO, "pa control success\n");
57 pa_threaded_mainloop_signal(mainloop, 0);
60 static void __avsys_audio_pa_ctrl_get_sink_info_cb(pa_context *c, const pa_sink_info *i, int is_last, void *userdata)
62 avsys_pa_ctrl_info_t *info = NULL;
63 avsys_assert_r(userdata);
64 info = (avsys_pa_ctrl_info_t *)userdata;
69 avsys_error(AVAUDIO, "Failed to get sink information: %s", pa_strerror(pa_context_errno(c)));
74 pa_threaded_mainloop_signal(info->m, 0);
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;
93 case PA_SINK_SUSPENDED:
94 sink_state = _DEACTIVE;
101 info->res |= ((1 << (sink_state + sink_name)));
104 static void __avsys_audio_pa_ctrl_get_server_info_cb(pa_context *c, const pa_server_info *i, void *userdata)
106 avsys_pa_ctrl_info_t *info = NULL;
107 avsys_assert_r(userdata);
108 info = (avsys_pa_ctrl_info_t *)userdata;
111 info->res = AVSYS_AUDIO_PA_CTL_SINK_UNKNOWN;
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;
118 info->res = AVSYS_AUDIO_PA_CTL_SINK_UNKNOWN;
120 pa_threaded_mainloop_signal(info->m, 0);
123 static void __avsys_audio_pa_ctrl_state_cb(pa_context *c, void *userdata)
126 avsys_pa_ctrl_info_t *info = NULL;
129 info = (avsys_pa_ctrl_info_t *)userdata;
130 avsys_assert_r(info);
131 avsys_assert_r(info->m);
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));
146 case PA_CONTEXT_TERMINATED:
147 case PA_CONTEXT_FAILED:
148 pa_threaded_mainloop_signal(info->m, 0);
151 case PA_CONTEXT_UNCONNECTED:
152 case PA_CONTEXT_CONNECTING:
153 case PA_CONTEXT_AUTHORIZING:
154 case PA_CONTEXT_SETTING_NAME:
159 int avsys_audio_pa_ctrl_volume_by_index(unsigned int idx, int volume, int ch)
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;
166 if (volume < 0 || volume > 65535) {
167 avsys_error(AVAUDIO, "invalid volume value %d\n", volume);
168 return AVSYS_STATE_ERR_INVALID_PARAMETER;
171 avsys_error(AVAUDIO, "invalid channel value\n", ch);
172 return AVSYS_STATE_ERR_INVALID_PARAMETER;
175 if (!(mainloop = pa_threaded_mainloop_new()))
178 if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), NULL)))
181 if (!(info = (avsys_pa_ctrl_info_t *)calloc(sizeof(avsys_pa_ctrl_info_t), 1)))
185 info->cmd = AVSYS_PA_CTL_CMD_VOLUME;
189 pa_context_set_state_callback(context, __avsys_audio_pa_ctrl_state_cb, (void *)info);
191 if (pa_context_connect(context, NULL, 0, NULL) < 0) {
192 error = pa_context_errno(context);
196 pa_threaded_mainloop_lock(mainloop);
198 if (pa_threaded_mainloop_start(mainloop) < 0)
199 goto unlock_and_fail;
202 pa_context_state_t state;
204 state = pa_context_get_state(context);
206 if (state == PA_CONTEXT_READY)
209 if (!PA_CONTEXT_IS_GOOD(state)) {
210 error = pa_context_errno(context);
211 goto unlock_and_fail;
214 /* Wait until the context is ready */
215 pa_threaded_mainloop_wait(mainloop);
218 pa_threaded_mainloop_unlock(mainloop);
220 pa_threaded_mainloop_stop(mainloop);
221 pa_context_disconnect(context);
222 pa_context_unref(context);
223 pa_threaded_mainloop_free(mainloop);
226 return AVSYS_STATE_SUCCESS; /* for success */
229 pa_threaded_mainloop_unlock(mainloop);
232 pa_threaded_mainloop_stop(mainloop);
235 pa_context_disconnect(context);
238 avsys_error(AVAUDIO, "pa error : %s\n", pa_strerror(error));
241 pa_context_unref(context);
244 pa_threaded_mainloop_free(mainloop);
249 return AVSYS_STATE_ERR_INTERNAL;
252 int avsys_audio_pa_ctrl_mute_by_index(unsigned int idx, int mute)
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;
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;
264 if (!(mainloop = pa_threaded_mainloop_new()))
267 if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), NULL)))
270 if (!(info = (avsys_pa_ctrl_info_t *)calloc(sizeof(avsys_pa_ctrl_info_t), 1)))
274 info->cmd = AVSYS_PA_CTL_CMD_MUTE;
278 pa_context_set_state_callback(context, __avsys_audio_pa_ctrl_state_cb, (void *)info);
280 if (pa_context_connect(context, NULL, 0, NULL) < 0) {
281 error = pa_context_errno(context);
285 pa_threaded_mainloop_lock(mainloop);
287 if (pa_threaded_mainloop_start(mainloop) < 0)
288 goto unlock_and_fail;
291 pa_context_state_t state;
293 state = pa_context_get_state(context);
295 if (state == PA_CONTEXT_READY)
298 if (!PA_CONTEXT_IS_GOOD(state)) {
299 error = pa_context_errno(context);
300 goto unlock_and_fail;
303 /* Wait until the context is ready */
304 pa_threaded_mainloop_wait(mainloop);
307 pa_threaded_mainloop_unlock(mainloop);
309 pa_threaded_mainloop_stop(mainloop);
310 pa_context_disconnect(context);
311 pa_context_unref(context);
312 pa_threaded_mainloop_free(mainloop);
315 return AVSYS_STATE_SUCCESS; /* for success */
318 pa_threaded_mainloop_unlock(mainloop);
321 pa_threaded_mainloop_stop(mainloop);
324 pa_context_disconnect(context);
327 avsys_error(AVAUDIO, "pa error : %s\n", pa_strerror(error));
330 pa_context_unref(context);
333 pa_threaded_mainloop_free(mainloop);
338 return AVSYS_STATE_ERR_INTERNAL;
341 int avsys_audio_pa_ctrl_get_default_sink(int *sink)
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;
349 return AVSYS_STATE_ERR_INVALID_PARAMETER;
351 if (!(mainloop = pa_threaded_mainloop_new()))
354 if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), NULL)))
357 if (!(info = (avsys_pa_ctrl_info_t *)calloc(sizeof(avsys_pa_ctrl_info_t), 1)))
361 info->cmd = AVSYS_PA_CTL_CMD_GET_DEFAULT_SINK;
363 pa_context_set_state_callback(context, __avsys_audio_pa_ctrl_state_cb, (void *)info);
365 if (pa_context_connect(context, NULL, 0, NULL) < 0) {
366 error = pa_context_errno(context);
370 pa_threaded_mainloop_lock(mainloop);
372 if (pa_threaded_mainloop_start(mainloop) < 0)
373 goto unlock_and_fail;
376 pa_context_state_t state;
378 state = pa_context_get_state(context);
380 if (state == PA_CONTEXT_READY)
383 if (!PA_CONTEXT_IS_GOOD(state)) {
384 error = pa_context_errno(context);
385 goto unlock_and_fail;
388 /* Wait until the context is ready */
389 pa_threaded_mainloop_wait(mainloop);
394 pa_threaded_mainloop_unlock(mainloop);
396 pa_threaded_mainloop_stop(mainloop);
397 pa_context_disconnect(context);
398 pa_context_unref(context);
399 pa_threaded_mainloop_free(mainloop);
402 return AVSYS_STATE_SUCCESS; /* for success */
405 pa_threaded_mainloop_unlock(mainloop);
408 pa_threaded_mainloop_stop(mainloop);
411 pa_context_disconnect(context);
414 avsys_error(AVAUDIO, "pa error : %s\n", pa_strerror(error));
417 pa_context_unref(context);
420 pa_threaded_mainloop_free(mainloop);
425 return AVSYS_STATE_ERR_INTERNAL;