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-pasimple.h"
26 #include "avsys-types.h"
27 #include "avsys-error.h"
28 #include "avsys-debug.h"
30 #define PA_SIMPLE_SAMPLES_PER_PERIOD_DEFAULT 1536 /* frames */
31 #define PA_SIMPLE_PERIODS_PER_BUFFER_FASTMODE 4
32 #define PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT 6
33 #define PA_SIMPLE_PERIODS_PER_BUFFER_PLAYBACK 8
34 #define PA_SIMPLE_PERIODS_PER_BUFFER_CAPTURE 12
35 #define PA_SIMPLE_PERIODS_PER_BUFFER_VIDEO 10
37 #define PA_SIMPLE_PERIOD_TIME_FOR_ULOW_LATENCY_MSEC 20
38 #define PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC 25
39 #define PA_SIMPLE_PERIOD_TIME_FOR_MID_LATENCY_MSEC 50
40 #define PA_SIMPLE_PERIOD_TIME_FOR_HIGH_LATENCY_MSEC 75
42 #define MSEC_TO_SAMPLE(samplerate,period_time) (samplerate*period_time/1000)
44 #define CHECK_VALID_HANDLE(handle) \
46 if (handle == NULL) { \
47 return AVSYS_STATE_ERR_NULL_POINTER; \
49 device = (avsys_audio_pasimple_handle_t *)handle->device; \
50 if (device == NULL) { \
51 return AVSYS_STATE_ERR_NULL_POINTER; \
53 if (device->pasimple_handle == NULL) { \
54 return AVSYS_STATE_ERR_NULL_POINTER; \
58 #define SET_PA_ATTR(pt,spp,ppb,pb,mr,tl,ml,fs) \
61 samples_per_period = spp; \
62 periods_per_buffer = ppb; \
66 attr.maxlength = ml; \
70 #define MEDIA_POLICY_AUTO "auto"
71 #define MEDIA_POLICY_PHONE "phone"
72 #define MEDIA_POLICY_ALL "all"
74 int avsys_audio_pasimple_open_device(const int mode, const unsigned int format, const unsigned int channel, const unsigned int samplerate, avsys_audio_handle_t *handle, int policy)
78 avsys_audio_pasimple_handle_t *device = NULL;
80 int err = AVSYS_STATE_SUCCESS;
81 int period_time = PA_SIMPLE_PERIOD_TIME_FOR_MID_LATENCY_MSEC;
82 int samples_per_period = PA_SIMPLE_SAMPLES_PER_PERIOD_DEFAULT;
83 int periods_per_buffer = PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT;
84 int vol_conf_type = AVSYS_AUDIO_VOLUME_CONFIG_TYPE(handle->gain_setting.volume_config);
85 pa_channel_map channel_map;
87 int p_time = PA_SIMPLE_PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
88 int p_count = PA_SIMPLE_PERIODS_PER_BUFFER_PLAYBACK;
89 char *time = getenv("AVSYS_PERIOD_TIME");
90 char *count = getenv("AVSYS_PERIOD_COUNT");
94 p_count = atoi(count);
96 avsys_info(AVAUDIO, ">>>[%s] mode=%d, format=%d, channel=%d, samplerate=%d\n", __func__, mode, format, channel, samplerate);
97 avsys_assert(handle != NULL);
99 if (channel < AVSYS_CHANNEL_MIN || channel > AVSYS_CHANNEL_MAX)
100 return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT;
102 device = (avsys_audio_pasimple_handle_t *)malloc(sizeof(avsys_audio_pasimple_handle_t));
103 if (device == NULL) {
104 avsys_critical(AVAUDIO, "PA Simple handle alloc fail\n");
105 return AVSYS_STATE_ERR_ALLOCATION;
108 ss.rate = samplerate;
109 ss.channels = channel;
111 pa_channel_map_init_auto(&channel_map, ss.channels, PA_CHANNEL_MAP_ALSA);
114 case AVSYS_AUDIO_FORMAT_8BIT:
115 ss.format = PA_SAMPLE_U8;
116 device->samplesize = 1 * channel;
118 case AVSYS_AUDIO_FORMAT_16BIT:
120 ss.format = PA_SAMPLE_S16LE;
121 device->samplesize = 2 * channel;
125 avsys_error(AVAUDIO, "Invalid format\n");
126 return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT;
128 handle->device = (void *)device;
130 pa_proplist *proplist = pa_proplist_new();
132 /* Set policy property */
133 avsys_info(AVAUDIO, ">>>[%s] policy=[%d], vol_type=[%d]\n", __func__, policy, vol_conf_type);
134 if (policy == AVSYS_AUDIO_HANDLE_ROUTE_HANDSET_ONLY) {
135 avsys_info(AVAUDIO, ": set media plicy to PHONE\n");
136 pa_proplist_sets(proplist, PA_PROP_MEDIA_POLICY, MEDIA_POLICY_PHONE);
138 /* AVSYS_AUDIO_HANDLE_ROUTE_FOLLOWING_POLICY */
139 /* check stream type (vol type) */
141 switch (vol_conf_type)
143 case AVSYS_AUDIO_VOLUME_TYPE_NOTIFICATION:
144 case AVSYS_AUDIO_VOLUME_TYPE_ALARM:
145 avsys_info(AVAUDIO, ": set media plicy to ALL\n");
146 pa_proplist_sets(proplist, PA_PROP_MEDIA_POLICY, MEDIA_POLICY_ALL);
149 case AVSYS_AUDIO_VOLUME_TYPE_FIXED: /* Used for Emergency */
150 avsys_info(AVAUDIO, ": set media plicy to PHONE\n");
151 pa_proplist_sets(proplist, PA_PROP_MEDIA_POLICY, MEDIA_POLICY_PHONE);
155 avsys_info(AVAUDIO, ": set media plicy to AUTO\n");
156 pa_proplist_sets(proplist, PA_PROP_MEDIA_POLICY, MEDIA_POLICY_AUTO);
161 handle->handle_route = policy;
163 memset(&attr, '\0', sizeof(attr));
166 case AVSYS_AUDIO_MODE_INPUT:
167 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_MID_LATENCY_MSEC,
168 MSEC_TO_SAMPLE(samplerate,period_time),
169 PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT,
170 0, -1, -1, -1, samples_per_period * device->samplesize);
172 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "CAPTURE", &ss, &channel_map, &attr, proplist, &err);
175 case AVSYS_AUDIO_MODE_INPUT_LOW_LATENCY:
176 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_ULOW_LATENCY_MSEC,
177 MSEC_TO_SAMPLE(samplerate,period_time),
178 PA_SIMPLE_PERIODS_PER_BUFFER_FASTMODE,
179 0, -1, -1, -1, samples_per_period * device->samplesize);
181 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "LOW LATENCY CAPTURE", &ss, &channel_map, &attr, proplist, &err);
184 case AVSYS_AUDIO_MODE_INPUT_HIGH_LATENCY:
185 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_HIGH_LATENCY_MSEC,
186 MSEC_TO_SAMPLE(samplerate,period_time),
187 PA_SIMPLE_PERIODS_PER_BUFFER_CAPTURE,
188 0, -1, -1, -1, samples_per_period * device->samplesize);
190 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "HIGH LATENCY CAPTURE", &ss, &channel_map, &attr, proplist, &err);
193 case AVSYS_AUDIO_MODE_OUTPUT: /* mid latency playback for normal audio case. */
194 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_MID_LATENCY_MSEC,
195 MSEC_TO_SAMPLE(samplerate,period_time),
196 PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT,
197 -1, -1, periods_per_buffer * samples_per_period * device->samplesize, attr.tlength, 0);
199 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "PLAYBACK", &ss, &channel_map, &attr, proplist, &err);
202 case AVSYS_AUDIO_MODE_OUTPUT_LOW_LATENCY: /* This is special case for touch sound playback */
203 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC,
204 MSEC_TO_SAMPLE(samplerate,period_time),
205 PA_SIMPLE_PERIODS_PER_BUFFER_FASTMODE,
206 samples_per_period * device->samplesize, -1, samples_per_period * device->samplesize + 3430, (uint32_t)-1, 0);
208 s = pa_simple_new_proplist(NULL,"AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "LOW LATENCY PLAYBACK", &ss, &channel_map, &attr, proplist, &err);
210 case AVSYS_AUDIO_MODE_OUTPUT_CLOCK: /* high latency playback - lager buffer size */
212 MSEC_TO_SAMPLE(samplerate,period_time),
214 (uint32_t) -1, (uint32_t) -1, periods_per_buffer * samples_per_period * device->samplesize, (uint32_t)-1, 0);
216 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "HIGH LATENCY PLAYBACK", &ss, &channel_map, &attr, proplist, &err);
219 case AVSYS_AUDIO_MODE_OUTPUT_VIDEO: /* low latency playback */
220 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC,
221 MSEC_TO_SAMPLE(samplerate,period_time),
222 PA_SIMPLE_PERIODS_PER_BUFFER_VIDEO,
223 4*(samples_per_period * device->samplesize), samples_per_period * device->samplesize, periods_per_buffer * samples_per_period * device->samplesize, (uint32_t)-1, 0);
225 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "LOW LATENCY PLAYBACK", &ss, &channel_map, &attr, proplist, &err);
228 case AVSYS_AUDIO_MODE_OUTPUT_AP_CALL:
229 #if defined(_MMFW_I386_ALL_SIMULATOR)
230 avsys_warning(AVAUDIO, "Does not support AP call mode at i386 simulator\n");
233 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC,
234 MSEC_TO_SAMPLE(samplerate,period_time),
235 PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT,
236 (uint32_t) -1, (uint32_t) -1, periods_per_buffer * samples_per_period * device->samplesize, attr.tlength, 0);
239 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "VoIP PLAYBACK", &ss, &channel_map, &attr, proplist, &err);
242 case AVSYS_AUDIO_MODE_INPUT_AP_CALL:
243 #if defined(_MMFW_I386_ALL_SIMULATOR)
244 avsys_warning(AVAUDIO, "Does not support AP call mode at i386 simulator\n");
247 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC,
248 MSEC_TO_SAMPLE(samplerate,period_time),
249 PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT,
250 0, (uint32_t) -1, (uint32_t) -1, (uint32_t) -1, samples_per_period * device->samplesize);
252 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "VoIP CAPTURE", &ss, &channel_map, &attr, proplist, &err);
255 case AVSYS_AUDIO_MODE_CALL_OUT:
256 case AVSYS_AUDIO_MODE_CALL_IN:
258 avsys_error(AVAUDIO, "Does not support call device handling\n");
262 avsys_critical_r(AVAUDIO, "Invalid open mode %d\n", mode);
264 return AVSYS_STATE_ERR_INVALID_MODE;
269 avsys_error_r(AVAUDIO, "Open pulseaudio handle has failed - %s\n", pa_strerror(err));
270 err = AVSYS_STATE_ERR_INTERNAL;
274 avsys_info(AVAUDIO, "Samples(per period) : %d\t Periods(per buffer) : %d\n", samples_per_period, periods_per_buffer);
276 device->pasimple_handle = (void *)s;
278 device->period_frames = samples_per_period;
279 device->buffer_frames = periods_per_buffer * device->period_frames;
280 device->periods_per_buffer = periods_per_buffer;
281 handle->period = device->period_frames * device->samplesize;
282 handle->msec_per_period = period_time;
283 if (0 > pa_simple_get_stream_index(s, &handle->stream_index, &err)) {
284 avsys_error(AVAUDIO, "Can not get stream index %s\n", pa_strerror(err));
285 err = AVSYS_STATE_ERR_INVALID_HANDLE;
290 pa_proplist_free(proplist);
295 int avsys_audio_pasimple_close_device(avsys_audio_handle_t *handle)
298 avsys_audio_pasimple_handle_t *device = NULL;
301 avsys_info(AVAUDIO, "%s\n", __func__);
303 avsys_assert(handle != NULL);
304 CHECK_VALID_HANDLE(handle);
306 switch (handle->mode) {
307 case AVSYS_AUDIO_MODE_CALL_OUT:
308 case AVSYS_AUDIO_MODE_CALL_IN:
309 avsys_warning(AVAUDIO, "Unsupported close mode in pa function\n");
310 return AVSYS_STATE_ERR_INVALID_MODE;
311 case AVSYS_AUDIO_MODE_OUTPUT_AP_CALL:
312 case AVSYS_AUDIO_MODE_INPUT_AP_CALL:
313 #if defined(_MMFW_I386_ALL_SIMULATOR)
314 avsys_warning(AVAUDIO, "Skip close call device in SDK");
315 return AVSYS_STATE_SUCCESS;
321 s = (pa_simple *)device->pasimple_handle;
322 avsys_assert(s != NULL);
324 switch (handle->mode) {
325 case AVSYS_AUDIO_MODE_OUTPUT:
326 case AVSYS_AUDIO_MODE_OUTPUT_CLOCK:
327 case AVSYS_AUDIO_MODE_OUTPUT_LOW_LATENCY:
328 case AVSYS_AUDIO_MODE_OUTPUT_AP_CALL:
329 case AVSYS_AUDIO_MODE_OUTPUT_VIDEO:
330 if (0 > pa_simple_flush(s, &err)) {
331 avsys_error(AVAUDIO, "pa_simple_flush() failed with %s\n", pa_strerror(err));
340 device->pasimple_handle = NULL;
343 return AVSYS_STATE_SUCCESS;
346 int avsys_audio_pasimple_write(avsys_audio_handle_t *handle, const void *buf, int size)
349 avsys_audio_pasimple_handle_t *device = NULL;
353 return AVSYS_STATE_ERR_NULL_POINTER;
354 CHECK_VALID_HANDLE(handle);
357 return AVSYS_STATE_ERR_INVALID_PARAMETER;
361 s = (pa_simple *)device->pasimple_handle;
363 if (0 > pa_simple_write(s, buf, size, &err)) {
364 avsys_error(AVAUDIO, "pa_simple_write() failed with %s\n", pa_strerror(err));
365 return AVSYS_STATE_ERR_INTERNAL;
371 int avsys_audio_pasimple_read(avsys_audio_handle_t *handle, void *buf, int size)
374 avsys_audio_pasimple_handle_t *device = NULL;
378 return AVSYS_STATE_ERR_NULL_POINTER;
379 CHECK_VALID_HANDLE(handle);
382 return AVSYS_STATE_ERR_INVALID_PARAMETER;
386 s = (pa_simple *)device->pasimple_handle;
388 if (0 > pa_simple_read(s, buf, size, &err)) {
389 avsys_error(AVAUDIO, "pa_simple_read() failed with %s\n", pa_strerror(err));
390 return AVSYS_STATE_ERR_INTERNAL;
396 int avsys_audio_pasimple_reset(avsys_audio_handle_t *handle)
399 avsys_audio_pasimple_handle_t *device = NULL;
402 CHECK_VALID_HANDLE(handle);
404 if (handle->mode == AVSYS_AUDIO_MODE_INPUT || handle->mode == AVSYS_AUDIO_MODE_INPUT_LOW_LATENCY) {
405 avsys_warning(AVAUDIO, "Skip pa_simple_flush() when input mode\n");
406 return AVSYS_STATE_SUCCESS;
409 s = (pa_simple *)device->pasimple_handle;
411 if (0 > pa_simple_flush(s, &err)) {
412 avsys_error(AVAUDIO, "pa_simple_flush() failed with %s\n", pa_strerror(err));
413 return AVSYS_STATE_ERR_INTERNAL;
416 return AVSYS_STATE_SUCCESS;
419 int avsys_audio_pasimple_drain(avsys_audio_handle_t *handle)
422 avsys_audio_pasimple_handle_t *device = NULL;
425 CHECK_VALID_HANDLE(handle);
427 s = (pa_simple *)device->pasimple_handle;
429 if (0 > pa_simple_drain(s, &err)) {
430 avsys_error(AVAUDIO, "pa_simple_drain() failed with %s\n", pa_strerror(err));
431 return AVSYS_STATE_ERR_INTERNAL;
434 return AVSYS_STATE_SUCCESS;
437 int avsys_audio_pasimple_set_volume(avsys_audio_handle_t *handle, int volume)
440 avsys_audio_pasimple_handle_t *device = NULL;
443 CHECK_VALID_HANDLE(handle);
445 s = (pa_simple *)device->pasimple_handle;
447 if (0 > pa_simple_set_volume(s, volume, &err)) {
448 avsys_error(AVAUDIO, "pa_simple_set_volume() failed with %s\n", pa_strerror(err));
449 return AVSYS_STATE_ERR_INTERNAL;
452 return AVSYS_STATE_SUCCESS;
455 #define USEC_TO_SAMPLE(usec, rate) ((usec*rate)/1000000)
456 #define SAMPLES_TO_USEC(samples,rate) ((samples*1000000)/rate)
457 #define BYTES_TO_USEC(bytes,size_per_sample,rate) ((bytes*1000000)/(size_per_sample*rate))
459 int avsys_audio_pasimple_delay(avsys_audio_handle_t *handle, int *delay)
462 avsys_audio_pasimple_handle_t *device = NULL;
464 pa_usec_t latency_time = 0;
465 unsigned int latency_frames = 0;
468 return AVSYS_STATE_ERR_NULL_POINTER;
470 CHECK_VALID_HANDLE(handle);
472 s = (pa_simple *)device->pasimple_handle;
474 latency_time = pa_simple_get_latency(s, &err);
475 if (err > 0 && latency_time == 0) {
476 avsys_error(AVAUDIO, "pa_simple_get_latency() failed with %s\n", pa_strerror(err));
477 return AVSYS_STATE_ERR_INTERNAL;
479 /* convert time to sample */
480 latency_frames = USEC_TO_SAMPLE(latency_time, handle->samplerate);
481 *delay = latency_frames;
483 return AVSYS_STATE_SUCCESS;
486 int avsys_audio_pasimple_get_period_buffer_time(avsys_audio_handle_t *handle, unsigned int *period_time, unsigned int *buffer_time)
488 avsys_audio_pasimple_handle_t *device = NULL;
490 if ((period_time == NULL) || (buffer_time == NULL))
491 return AVSYS_STATE_ERR_INTERNAL;
493 CHECK_VALID_HANDLE(handle);
495 *period_time = SAMPLES_TO_USEC(device->period_frames,handle->samplerate);
496 *buffer_time = *period_time * device->periods_per_buffer;
498 avsys_info(AVAUDIO, "[%s][%d] period = %d, buffer = %d\n", __func__, __LINE__, *period_time, *buffer_time);
500 return AVSYS_STATE_SUCCESS;
503 int avsys_audio_pasimple_cork(avsys_audio_handle_t *handle, int cork)
506 avsys_audio_pasimple_handle_t *device = NULL;
509 CHECK_VALID_HANDLE(handle);
511 s = (pa_simple *)device->pasimple_handle;
513 if (0 > pa_simple_cork(s, cork, &err)) {
514 avsys_error(AVAUDIO, "pa_simple_cork() failed with %s\n", pa_strerror(err));
515 return AVSYS_STATE_ERR_INTERNAL;
518 return AVSYS_STATE_SUCCESS;
521 int avsys_audio_pasimple_is_corked(avsys_audio_handle_t *handle, int *is_corked)
524 avsys_audio_pasimple_handle_t *device = NULL;
527 if (is_corked == NULL)
528 return AVSYS_STATE_ERR_INTERNAL;
530 CHECK_VALID_HANDLE(handle);
532 s = (pa_simple *)device->pasimple_handle;
534 *is_corked = pa_simple_is_corked(s);
536 return AVSYS_STATE_SUCCESS;