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 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)
74 avsys_audio_pasimple_handle_t *device = NULL;
76 int err = AVSYS_STATE_SUCCESS;
77 int period_time = PA_SIMPLE_PERIOD_TIME_FOR_MID_LATENCY_MSEC;
79 int samples_per_period = PA_SIMPLE_SAMPLES_PER_PERIOD_DEFAULT;
80 int periods_per_buffer = PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT;
82 avsys_info(AVAUDIO, ">>>[%s] mode=%d, format=%d, channel=%d, samplerate=%d\n", __func__, mode, format, channel, samplerate);
83 avsys_assert(handle != NULL);
85 if (channel < 1 || channel > 2)
86 return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT;
88 device = (avsys_audio_pasimple_handle_t *)malloc(sizeof(avsys_audio_pasimple_handle_t));
90 avsys_critical(AVAUDIO, "PA Simple handle alloc fail\n");
91 return AVSYS_STATE_ERR_ALLOCATION;
95 ss.channels = channel;
98 case AVSYS_AUDIO_FORMAT_8BIT:
99 ss.format = PA_SAMPLE_U8;
100 device->samplesize = 1 * channel;
102 case AVSYS_AUDIO_FORMAT_16BIT:
104 ss.format = PA_SAMPLE_S16LE;
105 device->samplesize = 2 * channel;
109 avsys_error(AVAUDIO, "Invalid format\n");
110 return AVSYS_STATE_ERR_DEVICE_NOT_SUPPORT;
112 handle->device = (void *)device;
114 pa_proplist *proplist = pa_proplist_new();
116 /* Set policy property */
117 avsys_info(AVAUDIO, ">>>[%s] policy=[%d], vol_type=[%d]\n", __func__, policy, handle->gain_setting.vol_type);
118 if (policy == AVSYS_AUDIO_HANDLE_ROUTE_HANDSET_ONLY) {
119 avsys_info(AVAUDIO, ": set media plicy to PHONE\n");
120 pa_proplist_sets(proplist, PA_PROP_MEDIA_POLICY, "phone");
122 /* AVSYS_AUDIO_HANDLE_ROUTE_FOLLOWING_POLICY */
123 /* check stream type (vol type) */
124 if (handle->gain_setting.vol_type == AVSYS_AUDIO_VOLUME_TYPE_NOTIFICATION ||
125 handle->gain_setting.vol_type == AVSYS_AUDIO_VOLUME_TYPE_ALARM) {
126 avsys_info(AVAUDIO, ": set media plicy to ALL\n");
127 pa_proplist_sets(proplist, PA_PROP_MEDIA_POLICY, "all");
129 avsys_info(AVAUDIO, ": set media plicy to AUTO\n");
130 pa_proplist_sets(proplist, PA_PROP_MEDIA_POLICY, "auto");
134 handle->handle_route = policy;
136 memset(&attr, '\0', sizeof(attr));
139 case AVSYS_AUDIO_MODE_INPUT:
140 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_MID_LATENCY_MSEC,
141 MSEC_TO_SAMPLE(samplerate,period_time),
142 PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT,
143 0, -1, -1, -1, samples_per_period * device->samplesize);
145 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "CAPTURE", &ss, NULL, &attr, proplist, &err);
148 case AVSYS_AUDIO_MODE_INPUT_LOW_LATENCY:
149 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_ULOW_LATENCY_MSEC,
150 MSEC_TO_SAMPLE(samplerate,period_time),
151 PA_SIMPLE_PERIODS_PER_BUFFER_FASTMODE,
152 0, -1, -1, -1, samples_per_period * device->samplesize);
154 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "LOW LATENCY CAPTURE", &ss, NULL, &attr, proplist, &err);
157 case AVSYS_AUDIO_MODE_INPUT_HIGH_LATENCY:
158 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_HIGH_LATENCY_MSEC,
159 MSEC_TO_SAMPLE(samplerate,period_time),
160 PA_SIMPLE_PERIODS_PER_BUFFER_CAPTURE,
161 0, -1, -1, -1, samples_per_period * device->samplesize);
163 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "HIGH LATENCY CAPTURE", &ss, NULL, &attr, proplist, &err);
166 case AVSYS_AUDIO_MODE_OUTPUT: /* mid latency playback for normal audio case. */
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 -1, -1, periods_per_buffer * samples_per_period * device->samplesize, attr.tlength, 0);
172 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "PLAYBACK", &ss, NULL, &attr, proplist, &err);
175 case AVSYS_AUDIO_MODE_OUTPUT_LOW_LATENCY: /* This is special case for touch sound playback */
176 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC,
177 MSEC_TO_SAMPLE(samplerate,period_time),
178 PA_SIMPLE_PERIODS_PER_BUFFER_FASTMODE,
179 samples_per_period * device->samplesize, -1, samples_per_period * device->samplesize + 3430, (uint32_t)-1, 0);
181 s = pa_simple_new_proplist(NULL,"AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "LOW LATENCY PLAYBACK", &ss, NULL, &attr, proplist, &err);
183 case AVSYS_AUDIO_MODE_OUTPUT_CLOCK: /* high latency playback - lager buffer size */
184 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_HIGH_LATENCY_MSEC,
185 MSEC_TO_SAMPLE(samplerate,period_time),
186 PA_SIMPLE_PERIODS_PER_BUFFER_PLAYBACK,
187 (uint32_t) -1, (uint32_t) -1, periods_per_buffer * samples_per_period * device->samplesize, (uint32_t)-1, 0);
189 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "HIGH LATENCY PLAYBACK", &ss, NULL, &attr, proplist, &err);
192 case AVSYS_AUDIO_MODE_OUTPUT_VIDEO: /* low latency playback */
193 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC,
194 MSEC_TO_SAMPLE(samplerate,period_time),
195 PA_SIMPLE_PERIODS_PER_BUFFER_VIDEO,
196 4*(samples_per_period * device->samplesize), samples_per_period * device->samplesize, periods_per_buffer * samples_per_period * device->samplesize, (uint32_t)-1, 0);
198 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "LOW LATENCY PLAYBACK", &ss, NULL, &attr, proplist, &err);
201 case AVSYS_AUDIO_MODE_OUTPUT_AP_CALL:
202 #if defined(_MMFW_I386_ALL_SIMULATOR)
203 avsys_warning(AVAUDIO, "Does not support AP call mode at i386 simulator\n");
206 SET_PA_ATTR(PA_SIMPLE_PERIOD_TIME_FOR_LOW_LATENCY_MSEC,
207 MSEC_TO_SAMPLE(samplerate,period_time),
208 PA_SIMPLE_PERIODS_PER_BUFFER_DEFAULT,
209 (uint32_t) -1, (uint32_t) -1, periods_per_buffer * samples_per_period * device->samplesize, attr.tlength, 0);
212 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_PLAYBACK, NULL, "VoIP PLAYBACK", &ss, NULL, &attr, proplist, &err);
215 case AVSYS_AUDIO_MODE_INPUT_AP_CALL:
216 #if defined(_MMFW_I386_ALL_SIMULATOR)
217 avsys_warning(AVAUDIO, "Does not support AP call mode at i386 simulator\n");
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_DEFAULT,
223 0, (uint32_t) -1, (uint32_t) -1, (uint32_t) -1, samples_per_period * device->samplesize);
225 s = pa_simple_new_proplist(NULL, "AVSYSTEM", PA_STREAM_RECORD, NULL, "VoIP CAPTURE", &ss, NULL, &attr, proplist, &err);
228 case AVSYS_AUDIO_MODE_CALL_OUT:
229 case AVSYS_AUDIO_MODE_CALL_IN:
231 avsys_error(AVAUDIO, "Does not support call device handling\n");
235 avsys_critical_r(AVAUDIO, "Invalid open mode %d\n", mode);
237 return AVSYS_STATE_ERR_INVALID_MODE;
242 avsys_error_r(AVAUDIO, "Open pulseaudio handle has failed - %s\n", pa_strerror(err));
243 err = AVSYS_STATE_ERR_INTERNAL;
247 avsys_info(AVAUDIO, "Samples(per period) : %d\t Periods(per buffer) : %d\n", samples_per_period, periods_per_buffer);
249 device->pasimple_handle = (void *)s;
251 device->period_frames = samples_per_period;
252 device->buffer_frames = periods_per_buffer * device->period_frames;
253 device->periods_per_buffer = periods_per_buffer;
254 handle->period = device->period_frames * device->samplesize;
255 handle->msec_per_period = period_time;
256 if (0 > pa_simple_get_stream_index(s, &handle->stream_index, &err)) {
257 avsys_error(AVAUDIO, "Can not get stream index %s\n", pa_strerror(err));
258 err = AVSYS_STATE_ERR_INVALID_HANDLE;
263 pa_proplist_free(proplist);
268 int avsys_audio_pasimple_close_device(avsys_audio_handle_t *handle)
271 avsys_audio_pasimple_handle_t *device = NULL;
274 avsys_info(AVAUDIO, "%s\n", __func__);
276 avsys_assert(handle != NULL);
277 CHECK_VALID_HANDLE(handle);
279 switch (handle->mode) {
280 case AVSYS_AUDIO_MODE_CALL_OUT:
281 case AVSYS_AUDIO_MODE_CALL_IN:
282 avsys_warning(AVAUDIO, "Unsupported close mode in pa function\n");
283 return AVSYS_STATE_ERR_INVALID_MODE;
284 case AVSYS_AUDIO_MODE_OUTPUT_AP_CALL:
285 case AVSYS_AUDIO_MODE_INPUT_AP_CALL:
286 #if defined(_MMFW_I386_ALL_SIMULATOR)
287 avsys_warning(AVAUDIO, "Skip close call device in SDK");
288 return AVSYS_STATE_SUCCESS;
294 s = (pa_simple *)device->pasimple_handle;
295 avsys_assert(s != NULL);
297 switch (handle->mode) {
298 case AVSYS_AUDIO_MODE_OUTPUT:
299 case AVSYS_AUDIO_MODE_OUTPUT_CLOCK:
300 case AVSYS_AUDIO_MODE_OUTPUT_LOW_LATENCY:
301 case AVSYS_AUDIO_MODE_OUTPUT_AP_CALL:
302 case AVSYS_AUDIO_MODE_OUTPUT_VIDEO:
303 if (0 > pa_simple_flush(s, &err)) {
304 avsys_error(AVAUDIO, "pa_simple_flush() failed with %s\n", pa_strerror(err));
313 device->pasimple_handle = NULL;
316 return AVSYS_STATE_SUCCESS;
319 int avsys_audio_pasimple_write(avsys_audio_handle_t *handle, const void *buf, int size)
322 avsys_audio_pasimple_handle_t *device = NULL;
326 return AVSYS_STATE_ERR_NULL_POINTER;
327 CHECK_VALID_HANDLE(handle);
330 return AVSYS_STATE_ERR_INVALID_PARAMETER;
334 s = (pa_simple *)device->pasimple_handle;
336 if (0 > pa_simple_write(s, buf, size, &err)) {
337 avsys_error(AVAUDIO, "pa_simple_write() failed with %s\n", pa_strerror(err));
338 return AVSYS_STATE_ERR_INTERNAL;
344 int avsys_audio_pasimple_read(avsys_audio_handle_t *handle, void *buf, int size)
347 avsys_audio_pasimple_handle_t *device = NULL;
351 return AVSYS_STATE_ERR_NULL_POINTER;
352 CHECK_VALID_HANDLE(handle);
355 return AVSYS_STATE_ERR_INVALID_PARAMETER;
359 s = (pa_simple *)device->pasimple_handle;
361 if (0 > pa_simple_read(s, buf, size, &err)) {
362 avsys_error(AVAUDIO, "pa_simple_read() failed with %s\n", pa_strerror(err));
363 return AVSYS_STATE_ERR_INTERNAL;
369 int avsys_audio_pasimple_reset(avsys_audio_handle_t *handle)
372 avsys_audio_pasimple_handle_t *device = NULL;
375 CHECK_VALID_HANDLE(handle);
377 if (handle->mode == AVSYS_AUDIO_MODE_INPUT || handle->mode == AVSYS_AUDIO_MODE_INPUT_LOW_LATENCY) {
378 avsys_warning(AVAUDIO, "Skip pa_simple_flush() when input mode\n");
379 return AVSYS_STATE_SUCCESS;
382 s = (pa_simple *)device->pasimple_handle;
384 if (0 > pa_simple_flush(s, &err)) {
385 avsys_error(AVAUDIO, "pa_simple_flush() failed with %s\n", pa_strerror(err));
386 return AVSYS_STATE_ERR_INTERNAL;
389 return AVSYS_STATE_SUCCESS;
392 int avsys_audio_pasimple_drain(avsys_audio_handle_t *handle)
395 avsys_audio_pasimple_handle_t *device = NULL;
398 CHECK_VALID_HANDLE(handle);
400 s = (pa_simple *)device->pasimple_handle;
402 if (0 > pa_simple_drain(s, &err)) {
403 avsys_error(AVAUDIO, "pa_simple_drain() failed with %s\n", pa_strerror(err));
404 return AVSYS_STATE_ERR_INTERNAL;
407 return AVSYS_STATE_SUCCESS;
410 int avsys_audio_pasimple_set_volume(avsys_audio_handle_t *handle, int volume)
413 avsys_audio_pasimple_handle_t *device = NULL;
416 CHECK_VALID_HANDLE(handle);
418 s = (pa_simple *)device->pasimple_handle;
420 if (0 > pa_simple_set_volume(s, volume, &err)) {
421 avsys_error(AVAUDIO, "pa_simple_set_volume() failed with %s\n", pa_strerror(err));
422 return AVSYS_STATE_ERR_INTERNAL;
425 return AVSYS_STATE_SUCCESS;
428 #define USEC_TO_SAMPLE(usec, rate) ((usec*rate)/1000000)
429 #define SAMPLES_TO_USEC(samples,rate) ((samples*1000000)/rate)
430 #define BYTES_TO_USEC(bytes,size_per_sample,rate) ((bytes*1000000)/(size_per_sample*rate))
432 int avsys_audio_pasimple_delay(avsys_audio_handle_t *handle, int *delay)
435 avsys_audio_pasimple_handle_t *device = NULL;
437 pa_usec_t latency_time = 0;
438 unsigned int latency_frames = 0;
441 return AVSYS_STATE_ERR_NULL_POINTER;
443 CHECK_VALID_HANDLE(handle);
445 s = (pa_simple *)device->pasimple_handle;
447 latency_time = pa_simple_get_latency(s, &err);
448 if (err > 0 && latency_time == 0) {
449 avsys_error(AVAUDIO, "pa_simple_get_latency() failed with %s\n", pa_strerror(err));
450 return AVSYS_STATE_ERR_INTERNAL;
452 /* convert time to sample */
453 latency_frames = USEC_TO_SAMPLE(latency_time, handle->samplerate);
454 *delay = latency_frames;
456 return AVSYS_STATE_SUCCESS;
459 int avsys_audio_pasimple_get_period_buffer_time(avsys_audio_handle_t *handle, unsigned int *period_time, unsigned int *buffer_time)
461 avsys_audio_pasimple_handle_t *device = NULL;
463 if ((period_time == NULL) || (buffer_time == NULL))
464 return AVSYS_STATE_ERR_INTERNAL;
466 CHECK_VALID_HANDLE(handle);
468 *period_time = SAMPLES_TO_USEC(device->period_frames,handle->samplerate);
469 *buffer_time = *period_time * device->periods_per_buffer;
471 avsys_info(AVAUDIO, "[%s][%d] period = %d, buffer = %d\n", __func__, __LINE__, *period_time, *buffer_time);
473 return AVSYS_STATE_SUCCESS;