- add tizen-audio-impl.h and tizen-audio-impl-xxx.c for implemetation layer that could be code variation as per HW
- rename files
- remove unused functions
- rename functions according to rules("__" prefix for static functions)
[Version] 0.1.3
[Profile] Common
[Issue Type] Refactoring
Change-Id: I95cc96d0e77ac75fc722ee16091e09d17410bbac
lib_LTLIBRARIES = libtizen-audio.la
libtizen_audio_la_SOURCES = tizen-audio.c \
- tizen-audio-device.c \
tizen-audio-volume.c \
+ tizen-audio-routing.c \
+ tizen-audio-stream.c \
+ tizen-audio-pcm.c \
+ tizen-audio-util.c \
tizen-audio-comm.c \
- tizen-audio-util.c
+ tizen-audio-impl-pcm.c \
+ tizen-audio-impl-ctrl.c
libtizen_audio_la_LDFLAGS = $(AM_LDFLAGS) -disable-static -avoid-version
if USE_TINYALSA
libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(TINYALSA_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS)
Name: audio-hal-emul
Summary: TIZEN Audio HAL for Emulator
-Version: 0.1.2
+Version: 0.1.3
Release: 0
Group: System/Libraries
License: Apache-2.0
/*
* audio-hal
*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "tizen-audio-internal.h"
-audio_return_t _audio_comm_send_message(audio_hal_t *ah, const char *name, int value)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(name, AUDIO_ERR_PARAMETER);
-
- AUDIO_LOG_DEBUG("send message : name(%s), value(%d)", name, value);
- if (ah->comm.msg_cb) {
- ah->comm.msg_cb(name, value, ah->comm.user_data);
- }
-
- return audio_ret;
-}
-
-audio_return_t _audio_comm_set_message_callback(audio_hal_t *ah, message_cb callback, void *user_data)
+static audio_return_t __set_message_callback(audio_hal_t *ah, message_cb callback, void *user_data)
{
audio_return_t audio_ret = AUDIO_RET_OK;
return audio_ret;
}
-audio_return_t _audio_comm_unset_message_callback(audio_hal_t *ah)
+static audio_return_t __unset_message_callback(audio_hal_t *ah)
{
audio_return_t audio_ret = AUDIO_RET_OK;
return audio_ret;
}
+
+audio_return_t _audio_comm_send_message(audio_hal_t *ah, const char *name, int value)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(name, AUDIO_ERR_PARAMETER);
+
+ AUDIO_LOG_DEBUG("send message : name(%s), value(%d)", name, value);
+ if (ah->comm.msg_cb) {
+ ah->comm.msg_cb(name, value, ah->comm.user_data);
+ }
+
+ return audio_ret;
+}
+
+audio_return_t audio_add_message_cb(void *audio_handle, message_cb callback, void *user_data)
+{
+ audio_return_t ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
+
+ /* NOTE: Management of several callbacks could be implemented.
+ But we do not care of it for now.*/
+ ret = __set_message_callback((audio_hal_t *)audio_handle, callback, user_data);
+
+ return ret;
+}
+
+audio_return_t audio_remove_message_cb(void *audio_handle, message_cb callback)
+{
+ audio_return_t ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
+
+ ret = __unset_message_callback((audio_hal_t *)audio_handle);
+
+ return ret;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "tizen-audio-internal.h"
+
+#ifdef __MIXER_PARAM_DUMP
+static void __dump_mixer_param(char *dump, long *param, int size)
+{
+ int i, len;
+
+ for (i = 0; i < size; i++) {
+ len = sprintf(dump, "%ld", *param);
+ if (len > 0)
+ dump += len;
+ if (i != size -1) {
+ *dump++ = ',';
+ }
+
+ param++;
+ }
+ *dump = '\0';
+}
+#endif
+
+audio_return_t _control_init(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ pthread_mutex_init(&(ah->mixer.mutex), NULL);
+ return AUDIO_RET_OK;
+}
+
+audio_return_t _control_deinit(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ pthread_mutex_destroy(&(ah->mixer.mutex));
+ return AUDIO_RET_OK;
+}
+
+audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ /* TODO. */
+ return AUDIO_RET_OK;
+}
+
+audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *card, const char *ctl_name, int *val)
+{
+ snd_ctl_t *handle;
+ snd_ctl_elem_value_t *control;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_type_t type;
+
+ int ret = 0, count = 0, i = 0;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(val, AUDIO_ERR_PARAMETER);
+
+ pthread_mutex_lock(&(ah->mixer.mutex));
+
+ ret = snd_ctl_open(&handle, card, 0);
+ if (ret < 0) {
+ AUDIO_LOG_ERROR("snd_ctl_open error, %s\n", snd_strerror(ret));
+ pthread_mutex_unlock(&(ah->mixer.mutex));
+ return AUDIO_ERR_IOCTL;
+ }
+
+ // Get Element Info
+
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_value_alloca(&control);
+
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+ snd_ctl_elem_id_set_name(id, ctl_name);
+
+ snd_ctl_elem_info_set_id(info, id);
+ if (snd_ctl_elem_info(handle, info) < 0) {
+ AUDIO_LOG_ERROR("Cannot find control element: %s\n", ctl_name);
+ goto close;
+ }
+ snd_ctl_elem_info_get_id(info, id);
+
+ type = snd_ctl_elem_info_get_type(info);
+ count = snd_ctl_elem_info_get_count(info);
+
+ snd_ctl_elem_value_set_id(control, id);
+
+ if (snd_ctl_elem_read(handle, control) < 0) {
+ AUDIO_LOG_ERROR("snd_ctl_elem_read failed \n");
+ goto close;
+}
+
+ switch (type) {
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
+ *val = snd_ctl_elem_value_get_boolean(control, i);
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ for (i = 0; i < count; i++)
+ *val = snd_ctl_elem_value_get_integer(control, i);
+ break;
+ case SND_CTL_ELEM_TYPE_ENUMERATED:
+ for (i = 0; i < count; i++)
+ *val = snd_ctl_elem_value_get_enumerated(control, i);
+ break;
+ default:
+ AUDIO_LOG_WARN("unsupported control element type\n");
+ goto close;
+ }
+
+ snd_ctl_close(handle);
+
+#ifdef AUDIO_DEBUG
+ AUDIO_LOG_INFO("get mixer(%s) = %d success", ctl_name, *val);
+#endif
+
+ pthread_mutex_unlock(&(ah->mixer.mutex));
+ return AUDIO_RET_OK;
+
+close:
+ AUDIO_LOG_ERROR("Error\n");
+ snd_ctl_close(handle);
+ pthread_mutex_unlock(&(ah->mixer.mutex));
+ return AUDIO_ERR_UNDEFINED;
+}
+
+audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *card, const char *ctl_name, int val)
+{
+ snd_ctl_t *handle;
+ snd_ctl_elem_value_t *control;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_type_t type;
+ int ret = 0, count = 0, i = 0;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
+
+ pthread_mutex_lock(&(ah->mixer.mutex));
+
+ ret = snd_ctl_open(&handle, card, 0);
+ if (ret < 0) {
+ AUDIO_LOG_ERROR("snd_ctl_open error, card: %s: %s", card, snd_strerror(ret));
+ pthread_mutex_unlock(&(ah->mixer.mutex));
+ return AUDIO_ERR_IOCTL;
+ }
+
+ // Get Element Info
+
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_value_alloca(&control);
+
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+ snd_ctl_elem_id_set_name(id, ctl_name);
+
+ snd_ctl_elem_info_set_id(info, id);
+ if (snd_ctl_elem_info(handle, info) < 0) {
+ AUDIO_LOG_ERROR("Cannot find control element: %s", ctl_name);
+ goto close;
+ }
+ snd_ctl_elem_info_get_id(info, id);
+
+ type = snd_ctl_elem_info_get_type(info);
+ count = snd_ctl_elem_info_get_count(info);
+
+ snd_ctl_elem_value_set_id(control, id);
+
+ snd_ctl_elem_read(handle, control);
+
+ switch (type) {
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
+ for (i = 0; i < count; i++)
+ snd_ctl_elem_value_set_boolean(control, i, val);
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ for (i = 0; i < count; i++)
+ snd_ctl_elem_value_set_integer(control, i, val);
+ break;
+ case SND_CTL_ELEM_TYPE_ENUMERATED:
+ for (i = 0; i < count; i++)
+ snd_ctl_elem_value_set_enumerated(control, i, val);
+ break;
+
+ default:
+ AUDIO_LOG_WARN("unsupported control element type");
+ goto close;
+ }
+
+ snd_ctl_elem_write(handle, control);
+
+ snd_ctl_close(handle);
+
+ AUDIO_LOG_INFO("set mixer(%s) = %d success", ctl_name, val);
+
+ pthread_mutex_unlock(&(ah->mixer.mutex));
+ return AUDIO_RET_OK;
+
+close:
+ AUDIO_LOG_ERROR("Error");
+ snd_ctl_close(handle);
+ pthread_mutex_unlock(&(ah->mixer.mutex));
+ return AUDIO_ERR_UNDEFINED;
+}
+
+audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
+
+ /* TODO. */
+ return AUDIO_RET_OK;
+}
+
+
+audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(elem, AUDIO_ERR_PARAMETER);
+
+ /* TODO. */
+ return AUDIO_RET_OK;
+}
\ No newline at end of file
/*
* audio-hal
*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <stdbool.h>
#include "tizen-audio-internal.h"
+#include "tizen-audio-impl.h"
-#ifndef __USE_TINYALSA__
+#ifdef __USE_TINYALSA__
+/* Convert pcm format from pulse to alsa */
+static const uint32_t g_format_convert_table[] = {
+ [AUDIO_SAMPLE_U8] = PCM_FORMAT_S8,
+ [AUDIO_SAMPLE_S16LE] = PCM_FORMAT_S16_LE,
+ [AUDIO_SAMPLE_S32LE] = PCM_FORMAT_S32_LE,
+ [AUDIO_SAMPLE_S24_32LE] = PCM_FORMAT_S24_LE
+};
+#else /* alsa-lib */
/* FIXME : To avoid build warning... */
int _snd_pcm_poll_descriptor(snd_pcm_t *pcm);
-#endif
-
-/* #define DEBUG_TIMING */
-
-static device_type_t outDeviceTypes[] = {
- { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
- { AUDIO_DEVICE_OUT_JACK, "Headphones" },
- { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
- { AUDIO_DEVICE_OUT_AUX, "Line" },
- { AUDIO_DEVICE_OUT_HDMI, "HDMI" },
- { 0, 0 },
-};
-
-static device_type_t inDeviceTypes[] = {
- { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" },
- { AUDIO_DEVICE_IN_JACK, "HeadsetMic" },
- { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
- { 0, 0 },
+/* Convert pcm format from pulse to alsa */
+static const uint32_t g_format_convert_table[] = {
+ [AUDIO_SAMPLE_U8] = SND_PCM_FORMAT_U8,
+ [AUDIO_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
+ [AUDIO_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
+ [AUDIO_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
+ [AUDIO_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
+ [AUDIO_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
+ [AUDIO_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
+ [AUDIO_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
+ [AUDIO_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
+ [AUDIO_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
+ [AUDIO_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
+ [AUDIO_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
+ [AUDIO_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE
};
+#endif
-static uint32_t convert_device_string_to_enum(const char* device_str, uint32_t direction)
-{
- uint32_t device = 0;
-
- if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
- device = AUDIO_DEVICE_OUT_SPEAKER;
- } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
- device = AUDIO_DEVICE_OUT_RECEIVER;
- } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
- device = AUDIO_DEVICE_OUT_JACK;
- } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
- device = AUDIO_DEVICE_OUT_BT_SCO;
- } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) {
- device = AUDIO_DEVICE_OUT_AUX;
- } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) {
- device = AUDIO_DEVICE_OUT_HDMI;
- } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
- device = AUDIO_DEVICE_IN_MAIN_MIC;
- } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
- device = AUDIO_DEVICE_IN_JACK;
- } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
- device = AUDIO_DEVICE_IN_BT_SCO;
- } else {
- device = AUDIO_DEVICE_NONE;
- }
- AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
- return device;
-}
-
-static audio_return_t set_devices(audio_hal_t *ah, device_info_t *devices, uint32_t num_of_devices)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
- uint32_t new_device = 0;
- const char *active_devices[MAX_DEVICES] = {NULL,};
- int i = 0, j = 0, dev_idx = 0;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
-
- if (num_of_devices > MAX_DEVICES) {
- num_of_devices = MAX_DEVICES;
- AUDIO_LOG_ERROR("error: num_of_devices");
- return AUDIO_ERR_PARAMETER;
- }
-
- if (devices[0].direction == AUDIO_DIRECTION_OUT) {
- ah->device.active_out &= 0x0;
- if (ah->device.active_in) {
- /* check the active in devices */
- for (j = 0; j < inDeviceTypes[j].type; j++) {
- if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
- active_devices[dev_idx++] = inDeviceTypes[j].name;
- }
- }
- } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
- ah->device.active_in &= 0x0;
- if (ah->device.active_out) {
- /* check the active out devices */
- for (j = 0; j < outDeviceTypes[j].type; j++) {
- if (ah->device.active_out & outDeviceTypes[j].type)
- active_devices[dev_idx++] = outDeviceTypes[j].name;
- }
- }
- }
-
- for (i = 0; i < num_of_devices; i++) {
- new_device = convert_device_string_to_enum(devices[i].type, devices[i].direction);
- if (new_device & AUDIO_DEVICE_IN) {
- for (j = 0; j < inDeviceTypes[j].type; j++) {
- if (new_device == inDeviceTypes[j].type) {
- active_devices[dev_idx++] = inDeviceTypes[j].name;
- ah->device.active_in |= new_device;
- }
- }
- } else {
- for (j = 0; j < outDeviceTypes[j].type; j++) {
- if (new_device == outDeviceTypes[j].type) {
- active_devices[dev_idx++] = outDeviceTypes[j].name;
- ah->device.active_out |= new_device;
- }
- }
- }
- }
-
- if (active_devices[0] == NULL) {
- AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
- return AUDIO_ERR_PARAMETER;
- }
-
- return audio_ret;
-}
-
-audio_return_t _audio_device_init(audio_hal_t *ah)
-{
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
- ah->device.active_in = 0x0;
- ah->device.active_out = 0x0;
- ah->device.pcm_in = NULL;
- ah->device.pcm_out = NULL;
- pthread_mutex_init(&ah->device.pcm_lock, NULL);
- ah->device.pcm_count = 0;
-
- return AUDIO_RET_OK;
-}
-
-audio_return_t _audio_device_deinit(audio_hal_t *ah)
-{
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
- return AUDIO_RET_OK;
-}
-
-static audio_return_t _update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
- device_info_t *devices = NULL;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
-
- devices = route_info->device_infos;
-
- AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
-
- audio_ret = set_devices(ah, devices, route_info->num_of_devices);
- if (audio_ret) {
- AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
- return audio_ret;
- }
-
- return audio_ret;
-}
-
-static audio_return_t _update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
-
- AUDIO_LOG_INFO("update_route_voip++");
-
- audio_ret = set_devices(ah, devices, num_of_devices);
- if (audio_ret) {
- AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
- return audio_ret;
- }
-
- return audio_ret;
-}
-
-static audio_return_t _update_route_reset(audio_hal_t *ah, uint32_t direction)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
- const char *active_devices[MAX_DEVICES] = {NULL,};
- int i = 0, dev_idx = 0;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
- AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
-
- if (direction == AUDIO_DIRECTION_OUT) {
- ah->device.active_out &= 0x0;
- if (ah->device.active_in) {
- /* check the active in devices */
- for (i = 0; i < inDeviceTypes[i].type; i++) {
- if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
- active_devices[dev_idx++] = inDeviceTypes[i].name;
- AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
- }
- }
- }
- } else {
- ah->device.active_in &= 0x0;
- if (ah->device.active_out) {
- /* check the active out devices */
- for (i = 0; i < outDeviceTypes[i].type; i++) {
- if (ah->device.active_out & outDeviceTypes[i].type) {
- active_devices[dev_idx++] = outDeviceTypes[i].name;
- AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
- }
- }
- }
- }
-
- if (active_devices[0] == NULL) {
- AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
- return AUDIO_RET_OK;
- }
-
- return audio_ret;
-}
-
-#define LOOPBACK_ARG_LATENCY_MSEC 30
-#define LOOPBACK_ARG_ADJUST_TIME_SEC 3
-audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
- audio_hal_t *ah = (audio_hal_t *)audio_handle;
- device_info_t *devices = NULL;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
-
- AUDIO_LOG_INFO("role:%s", info->role);
-
- devices = info->device_infos;
-
- if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
- audio_ret = _update_route_voip(ah, devices, info->num_of_devices);
- if (AUDIO_IS_ERROR(audio_ret)) {
- AUDIO_LOG_WARN("set voip route return 0x%x", audio_ret);
- }
- } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
- audio_ret = _update_route_reset(ah, devices->direction);
- if (AUDIO_IS_ERROR(audio_ret)) {
- AUDIO_LOG_WARN("set reset return 0x%x", audio_ret);
- }
- } else {
- /* send latency and adjust time for loopback */
- if (!strncmp("loopback", info->role, MAX_NAME_LEN)) {
- _audio_comm_send_message(ah, "loopback::latency", LOOPBACK_ARG_LATENCY_MSEC);
- _audio_comm_send_message(ah, "loopback::adjust_time", LOOPBACK_ARG_ADJUST_TIME_SEC);
- }
- /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
- audio_ret = _update_route_ap_playback_capture(ah, info);
- if (AUDIO_IS_ERROR(audio_ret)) {
- AUDIO_LOG_WARN("set playback route return 0x%x", audio_ret);
- }
- }
- return audio_ret;
-}
-
-audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
- audio_hal_t *ah = (audio_hal_t *)audio_handle;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
-
- AUDIO_LOG_INFO("role:%s, direction:%u, idx:%u, is_connected:%d", info->role, info->direction, info->idx, is_connected);
-
- return audio_ret;
-}
-
-audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option)
+static uint32_t __convert_format(audio_sample_format_t format)
{
- audio_return_t audio_ret = AUDIO_RET_OK;
- audio_hal_t *ah = (audio_hal_t *)audio_handle;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
-
- AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);
-
- return audio_ret;
+ return g_format_convert_table[format];
}
#ifdef __USE_TINYALSA__
return pcm;
}
+
+static int __tinyalsa_pcm_recover(struct pcm *pcm, int err)
+{
+ if (err > 0)
+ err = -err;
+ if (err == -EINTR) /* nothing to do, continue */
+ return 0;
+ if (err == -EPIPE) {
+ AUDIO_LOG_INFO("XRUN occurred");
+ err = pcm_prepare(pcm);
+ if (err < 0) {
+ AUDIO_LOG_ERROR("Could not recover from XRUN occurred, prepare failed : %d", err);
+ return err;
+ }
+ return 0;
+ }
+ if (err == -ESTRPIPE) {
+ /* tinyalsa does not support pcm resume, dont't care suspend case */
+ AUDIO_LOG_ERROR("Could not recover from suspend : %d", err);
+ return err;
+ }
+ return err;
+}
#endif
-audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
{
#ifdef __USE_TINYALSA__
- audio_hal_t *ah;
audio_pcm_sample_spec_t *ss;
int err;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER);
-
- ah = (audio_hal_t *)audio_handle;
ss = (audio_pcm_sample_spec_t *)sample_spec;
- ss->format = _convert_format((audio_sample_format_t)ss->format);
+ ss->format = __convert_format((audio_sample_format_t)ss->format);
*pcm_handle = __tinyalsa_open_device(ss, (size_t)period_size, (size_t)periods, direction);
if (*pcm_handle == NULL) {
AUDIO_LOG_ERROR("Error prepare PCM device : %d", err);
}
- ah->device.pcm_count++;
- AUDIO_LOG_INFO("Opening PCM handle 0x%x", *pcm_handle);
#else /* alsa-lib */
- audio_hal_t *ah;
int err, mode;
char *device_name = NULL;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER);
-
- ah = (audio_hal_t *)audio_handle;
mode = SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT;
if (direction == AUDIO_DIRECTION_OUT)
return AUDIO_ERR_RESOURCE;
}
- if ((err = audio_pcm_set_params(audio_handle, *pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) {
+ if ((err = _pcm_set_params(*pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) {
AUDIO_LOG_ERROR("Failed to set pcm parameters : %d", err);
return err;
}
- ah->device.pcm_count++;
- AUDIO_LOG_INFO("Opening PCM handle 0x%x, PCM device %s", *pcm_handle, device_name);
+ AUDIO_LOG_INFO("PCM device %s", device_name);
#endif
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle)
+audio_return_t _pcm_start(void *pcm_handle)
{
int err;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
#ifdef __USE_TINYALSA__
if ((err = pcm_start(pcm_handle)) < 0) {
AUDIO_LOG_ERROR("Error starting PCM handle : %d", err);
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle)
+audio_return_t _pcm_stop(void *pcm_handle)
{
int err;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
#ifdef __USE_TINYALSA__
if ((err = pcm_stop(pcm_handle)) < 0) {
AUDIO_LOG_ERROR("Error stopping PCM handle : %d", err);
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle)
+audio_return_t _pcm_close(void *pcm_handle)
{
- audio_hal_t *ah = (audio_hal_t *)audio_handle;
int err;
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
AUDIO_LOG_INFO("Try to close PCM handle 0x%x", pcm_handle);
#ifdef __USE_TINYALSA__
}
#endif
- pcm_handle = NULL;
- ah->device.pcm_count--;
- AUDIO_LOG_INFO("PCM handle close success (count:%d)", ah->device.pcm_count);
-
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail)
+audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail)
{
#ifdef __USE_TINYALSA__
struct timespec tspec;
unsigned int frames_avail = 0;
int err;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER);
-
err = pcm_get_htimestamp(pcm_handle, &frames_avail, &tspec);
if (err < 0) {
AUDIO_LOG_ERROR("Could not get avail and timespec at PCM handle 0x%x : %d", pcm_handle, err);
#else /* alsa-lib */
snd_pcm_sframes_t frames_avail;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER);
-
if ((frames_avail = snd_pcm_avail(pcm_handle)) < 0) {
AUDIO_LOG_ERROR("Could not get avail at PCM handle 0x%x : %d", pcm_handle, frames_avail);
return AUDIO_ERR_IOCTL;
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames)
+audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames)
{
#ifdef __USE_TINYALSA__
int err;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
err = pcm_write(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames));
if (err < 0) {
AUDIO_LOG_ERROR("Failed to write pcm : %d", err);
}
#ifdef DEBUG_TIMING
- AUDIO_LOG_DEBUG("audio_pcm_write = %d", frames);
+ AUDIO_LOG_DEBUG("_pcm_write = %d", frames);
#endif
#else /* alsa-lib */
snd_pcm_sframes_t frames_written;
}
#ifdef DEBUG_TIMING
- AUDIO_LOG_DEBUG("audio_pcm_write = (%d / %d)", frames_written, frames);
+ AUDIO_LOG_DEBUG("_pcm_write = (%d / %d)", frames_written, frames);
#endif
#endif
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames)
+audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames)
{
#ifdef __USE_TINYALSA__
int err;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
err = pcm_read(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames));
if (err < 0) {
AUDIO_LOG_ERROR("Failed to read pcm : %d", err);
#else /* alsa-lib */
snd_pcm_sframes_t frames_read;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
-
frames_read = snd_pcm_readi(pcm_handle, buffer, (snd_pcm_uframes_t)frames);
if (frames_read < 0) {
AUDIO_LOG_ERROR("Failed to read pcm : %d", frames_read);
}
#ifdef DEBUG_TIMING
- AUDIO_LOG_DEBUG("audio_pcm_read = (%d / %d)", frames_read, frames);
+ AUDIO_LOG_DEBUG("_pcm_read = (%d / %d)", frames_read, frames);
#endif
#endif
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd)
+audio_return_t _pcm_get_fd(void *pcm_handle, int *fd)
{
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(fd, AUDIO_ERR_PARAMETER);
/* we use an internal API of the (tiny)alsa library, so it causes warning message during compile */
#ifdef __USE_TINYALSA__
*fd = _pcm_poll_descriptor((struct pcm *)pcm_handle);
return AUDIO_RET_OK;
}
-#ifdef __USE_TINYALSA__
-static int __tinyalsa_pcm_recover(struct pcm *pcm, int err)
-{
- if (err > 0)
- err = -err;
- if (err == -EINTR) /* nothing to do, continue */
- return 0;
- if (err == -EPIPE) {
- AUDIO_LOG_INFO("XRUN occurred");
- err = pcm_prepare(pcm);
- if (err < 0) {
- AUDIO_LOG_ERROR("Could not recover from XRUN occurred, prepare failed : %d", err);
- return err;
- }
- return 0;
- }
- if (err == -ESTRPIPE) {
- /* tinyalsa does not support pcm resume, dont't care suspend case */
- AUDIO_LOG_ERROR("Could not recover from suspend : %d", err);
- return err;
- }
- return err;
-}
-#endif
-
-audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents)
+audio_return_t _pcm_recover(void *pcm_handle, int revents)
{
int state, err;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
if (revents & POLLERR)
}
#endif
- AUDIO_LOG_DEBUG("audio_pcm_recover");
+ AUDIO_LOG_DEBUG("_pcm_recover");
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods)
+audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods)
{
#ifdef __USE_TINYALSA__
audio_pcm_sample_spec_t *ss;
unsigned int _start_threshold, _stop_threshold, _silence_threshold;
struct pcm_config *config;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
ss = (audio_pcm_sample_spec_t *)*sample_spec;
/* we use an internal API of the tiny alsa library, so it causes warning message during compile */
_stop_threshold = config->stop_threshold;
_silence_threshold = config->silence_threshold;
- AUDIO_LOG_DEBUG("audio_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, config->format, config->rate, config->channels, config->period_size, config->period_count, _buffer_size);
+ AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, config->format, config->rate, config->channels, config->period_size, config->period_count, _buffer_size);
#else /* alsa-lib */
int err;
audio_pcm_sample_spec_t *ss;
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
ss = (audio_pcm_sample_spec_t *)*sample_spec;
snd_pcm_hw_params_alloca(&hwparams);
AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %s", err);
}
- AUDIO_LOG_DEBUG("audio_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, _period_size, _periods, _buffer_size);
+ AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, _period_size, _periods, _buffer_size);
#endif
return AUDIO_RET_OK;
}
-audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
{
#ifdef __USE_TINYALSA__
/* Parameters are only acceptable in pcm_open() function */
- AUDIO_LOG_DEBUG("audio_pcm_set_params");
+ AUDIO_LOG_DEBUG("_pcm_set_params");
#else /* alsa-lib */
int err;
audio_pcm_sample_spec_t ss;
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
ss = *(audio_pcm_sample_spec_t *)sample_spec;
snd_pcm_hw_params_alloca(&hwparams);
return AUDIO_ERR_PARAMETER;
}
- ss.format = _convert_format((audio_sample_format_t)ss.format);
+ ss.format = __convert_format((audio_sample_format_t)ss.format);
if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, ss.format)) < 0) {
AUDIO_LOG_ERROR("snd_pcm_hw_params_set_format() failed : %d", err);
return AUDIO_ERR_PARAMETER;
return AUDIO_ERR_IOCTL;
}
- AUDIO_LOG_DEBUG("audio_pcm_set_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods, _buffer_size);
+ AUDIO_LOG_DEBUG("_pcm_set_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods, _buffer_size);
#endif
return AUDIO_RET_OK;
}
+
+/* Generic snd pcm interface APIs */
+audio_return_t _pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size)
+{
+ audio_return_t ret = AUDIO_RET_OK;
+ snd_pcm_hw_params_t *hwparams;
+ int err = 0;
+ int dir;
+ unsigned int val = 0;
+ snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
+ snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
+ uint8_t _use_mmap = use_mmap && *use_mmap;
+ uint32_t channels = 0;
+
+ AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+ snd_pcm_hw_params_alloca(&hwparams);
+
+ /* Skip parameter setting to null device. */
+ if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
+ return AUDIO_ERR_IOCTL;
+
+ /* Allocate a hardware parameters object. */
+ snd_pcm_hw_params_alloca(&hwparams);
+
+ /* Fill it in with default values. */
+ if (snd_pcm_hw_params_any(pcm, hwparams) < 0) {
+ AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
+ goto error;
+ }
+
+ /* Set the desired hardware parameters. */
+
+ if (_use_mmap) {
+
+ if (snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
+
+ /* mmap() didn't work, fall back to interleaved */
+
+ if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+ goto error;
+ }
+
+ _use_mmap = 0;
+ }
+
+ } else if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+ goto error;
+ }
+ AUDIO_LOG_DEBUG("setting rate - %d", sample_spec->rate);
+ err = snd_pcm_hw_params_set_rate(pcm, hwparams, sample_spec->rate, 0);
+ if (err < 0) {
+ AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
+ }
+
+ err = snd_pcm_hw_params(pcm, hwparams);
+ if (err < 0) {
+ AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
+ goto error;
+ }
+
+ /* Dump current param */
+
+ if ((ret = snd_pcm_hw_params_current(pcm, hwparams)) < 0) {
+ AUDIO_LOG_INFO("snd_pcm_hw_params_current() failed: %s", snd_strerror(ret));
+ goto error;
+ }
+
+ if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
+ (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
+ AUDIO_LOG_INFO("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", snd_strerror(ret));
+ goto error;
+ }
+
+ snd_pcm_hw_params_get_access(hwparams, (snd_pcm_access_t *) &val);
+ AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
+
+ snd_pcm_hw_params_get_format(hwparams, &sample_spec->format);
+ AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
+ snd_pcm_format_name((snd_pcm_format_t)sample_spec->format),
+ snd_pcm_format_description((snd_pcm_format_t)sample_spec->format));
+
+ snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val);
+ AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
+ snd_pcm_subformat_name((snd_pcm_subformat_t)val),
+ snd_pcm_subformat_description((snd_pcm_subformat_t)val));
+
+ snd_pcm_hw_params_get_channels(hwparams, &channels);
+ sample_spec->channels = (uint8_t)channels;
+ AUDIO_LOG_DEBUG("channels = %d\n", sample_spec->channels);
+
+ if (buffer_size)
+ *buffer_size = _buffer_size;
+
+ if (period_size)
+ *period_size = _period_size;
+
+ if (use_mmap)
+ *use_mmap = _use_mmap;
+
+ return AUDIO_RET_OK;
+
+error:
+ return AUDIO_ERR_RESOURCE;
+}
+
+audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event)
+{
+ snd_pcm_sw_params_t *swparams;
+ snd_pcm_uframes_t boundary;
+ int err;
+
+ AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
+
+ snd_pcm_sw_params_alloca(&swparams);
+
+ if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) {
+ AUDIO_LOG_WARN("Unable to determine current swparams: %s\n", snd_strerror(err));
+ goto error;
+ }
+ if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
+ AUDIO_LOG_WARN("Unable to disable period event: %s\n", snd_strerror(err));
+ goto error;
+ }
+ if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
+ AUDIO_LOG_WARN("Unable to enable time stamping: %s\n", snd_strerror(err));
+ goto error;
+ }
+ if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
+ AUDIO_LOG_WARN("Unable to get boundary: %s\n", snd_strerror(err));
+ goto error;
+ }
+ if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
+ AUDIO_LOG_WARN("Unable to set stop threshold: %s\n", snd_strerror(err));
+ goto error;
+ }
+ if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) avail_min)) < 0) {
+ AUDIO_LOG_WARN("Unable to set start threshold: %s\n", snd_strerror(err));
+ goto error;
+ }
+ if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
+ AUDIO_LOG_WARN("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err));
+ goto error;
+ }
+ if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
+ AUDIO_LOG_WARN("Unable to set sw params: %s\n", snd_strerror(err));
+ goto error;
+ }
+ return AUDIO_RET_OK;
+error:
+ return err;
+}
--- /dev/null
+#ifndef footizenaudioimplfoo
+#define footizenaudioimplfoo
+
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/* PCM */
+audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
+audio_return_t _pcm_start(void *pcm_handle);
+audio_return_t _pcm_stop(void *pcm_handle);
+audio_return_t _pcm_close(void *pcm_handle);
+audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail);
+audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames);
+audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames);
+audio_return_t _pcm_get_fd(void *pcm_handle, int *fd);
+audio_return_t _pcm_recover(void *pcm_handle, int revents);
+audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods);
+audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
+audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event);
+audio_return_t _pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size);
+
+/* Control */
+audio_return_t _control_init(audio_hal_t *ah);
+audio_return_t _control_deinit(audio_hal_t *ah);
+audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size);
+audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char* card, const char *ctl_name, int val);
+audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value);
+audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *card, const char *ctl_name, int *val);
+audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem);
+
+#endif
/*
* audio-hal
*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/* type definitions */
typedef signed char int8_t;
-/* pcm */
+/* PCM */
typedef struct {
snd_pcm_format_t format;
uint32_t rate;
uint8_t channels;
} audio_pcm_sample_spec_t;
-/* Device */
-typedef enum audio_device_api {
- AUDIO_DEVICE_API_UNKNOWN,
- AUDIO_DEVICE_API_ALSA,
- AUDIO_DEVICE_API_BLUEZ,
-} audio_device_api_t;
-
-typedef struct audio_device_alsa_info {
- char *card_name;
- uint32_t card_idx;
- uint32_t device_idx;
-} audio_device_alsa_info_t;
-
-typedef struct audio_device_bluz_info {
- char *protocol;
- uint32_t nrec;
-} audio_device_bluez_info_t;
-
-typedef struct audio_device_info {
- audio_device_api_t api;
- audio_direction_t direction;
- char *name;
- uint8_t is_default_device;
- union {
- audio_device_alsa_info_t alsa;
- audio_device_bluez_info_t bluez;
- };
-} audio_device_info_t;
-
typedef struct audio_hal_device {
uint32_t active_in;
uint32_t active_out;
uint32_t pcm_count;
} audio_hal_device_t;
-/* Stream */
+/* Volume */
#define AUDIO_VOLUME_LEVEL_MAX 16
typedef enum audio_volume {
audio_volume_value_table_t *volume_value_table;
} audio_hal_volume_t;
+/* Mixer */
typedef struct audio_hal_mixer {
snd_mixer_t *mixer;
pthread_mutex_t mutex;
audio_hal_comm_t comm;
} audio_hal_t;
-typedef struct {
- unsigned short is_open; /* if is_open is true, open device; else close device.*/
- unsigned short is_headphone;
- unsigned int is_downlink_mute;
- unsigned int is_uplink_mute;
-} device_ctrl_t;
-
-typedef struct samplerate_ctrl {
- unsigned int samplerate; /* change samplerate.*/
-} set_samplerate_t;
-
audio_return_t _audio_volume_init(audio_hal_t *ah);
audio_return_t _audio_volume_deinit(audio_hal_t *ah);
-audio_return_t _audio_device_init(audio_hal_t *ah);
-audio_return_t _audio_device_deinit(audio_hal_t *ah);
+audio_return_t _audio_routing_init(audio_hal_t *ah);
+audio_return_t _audio_routing_deinit(audio_hal_t *ah);
+audio_return_t _audio_stream_init(audio_hal_t *ah);
+audio_return_t _audio_stream_deinit(audio_hal_t *ah);
+audio_return_t _audio_pcm_init(audio_hal_t *ah);
+audio_return_t _audio_pcm_deinit(audio_hal_t *ah);
audio_return_t _audio_comm_init(audio_hal_t *ah);
audio_return_t _audio_comm_deinit(audio_hal_t *ah);
-audio_return_t _audio_util_init(audio_hal_t *ah);
-audio_return_t _audio_util_deinit(audio_hal_t *ah);
audio_return_t _audio_comm_send_message(audio_hal_t *ah, const char *name, int value);
-audio_return_t _audio_comm_set_message_callback(audio_hal_t *ah, message_cb callback, void *user_data);
-audio_return_t _audio_comm_unset_message_callback(audio_hal_t *ah);
-audio_return_t _audio_mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size);
-audio_return_t _audio_mixer_control_set_value(audio_hal_t *ah, const char *card, const char *ctl_name, int val);
-audio_return_t _audio_mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value);
-audio_return_t _audio_mixer_control_get_value(audio_hal_t *ah, const char *card, const char *ctl_name, int *val);
-audio_return_t _audio_mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem);
-audio_return_t _audio_pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event);
-audio_return_t _audio_pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size);
-uint32_t _convert_format(audio_sample_format_t format);
typedef struct _dump_data {
char *strbuf;
char *p;
} dump_data_t;
-dump_data_t* dump_new(int length);
-void dump_add_str(dump_data_t *dump, const char *fmt, ...);
-char* dump_get_str(dump_data_t *dump);
-void dump_free(dump_data_t *dump);
+dump_data_t* _audio_dump_new(int length);
+void _audio_dump_add_str(dump_data_t *dump, const char *fmt, ...);
+char* _audio_dump_get_str(dump_data_t *dump);
+void _audio_dump_free(dump_data_t *dump);
#endif
--- /dev/null
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "tizen-audio-internal.h"
+#include "tizen-audio-impl.h"
+
+audio_return_t _audio_pcm_init(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ ah->device.pcm_in = NULL;
+ ah->device.pcm_out = NULL;
+ pthread_mutex_init(&ah->device.pcm_lock, NULL);
+ ah->device.pcm_count = 0;
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t _audio_pcm_deinit(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ pthread_mutex_destroy(&ah->device.pcm_lock);
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_hal_t *ah = NULL;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER);
+
+ if ((audio_ret = _pcm_open(pcm_handle, direction, sample_spec, period_size, periods)))
+ return audio_ret;
+
+ ah = (audio_hal_t*)audio_handle;
+ ah->device.pcm_count++;
+ AUDIO_LOG_INFO("Opening PCM handle 0x%x", *pcm_handle);
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_start(pcm_handle);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_stop(pcm_handle);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_hal_t *ah = NULL;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+ if ((audio_ret = _pcm_close(pcm_handle)))
+ return audio_ret;
+
+ pcm_handle = NULL;
+ ah = (audio_hal_t*)audio_handle;
+ ah->device.pcm_count--;
+
+ AUDIO_LOG_INFO("PCM handle close success (count:%d)", ah->device.pcm_count);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_avail(pcm_handle, avail);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_write(pcm_handle, buffer, frames);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_read(pcm_handle, buffer, frames);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(fd, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_get_fd(pcm_handle, fd);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_recover(pcm_handle, revents);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_get_params(pcm_handle, direction, sample_spec, period_size, periods);
+
+ return audio_ret;
+}
+
+audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER);
+
+ audio_ret = _pcm_set_params(pcm_handle, direction, sample_spec, period_size, periods);
+
+ return audio_ret;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "tizen-audio-internal.h"
+#include "tizen-audio-impl.h"
+
+/* #define DEBUG_TIMING */
+
+static device_type_t outDeviceTypes[] = {
+ { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
+ { AUDIO_DEVICE_OUT_JACK, "Headphones" },
+ { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
+ { AUDIO_DEVICE_OUT_AUX, "Line" },
+ { AUDIO_DEVICE_OUT_HDMI, "HDMI" },
+ { 0, 0 },
+};
+
+static device_type_t inDeviceTypes[] = {
+ { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" },
+ { AUDIO_DEVICE_IN_JACK, "HeadsetMic" },
+ { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
+ { 0, 0 },
+};
+
+static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction)
+{
+ uint32_t device = 0;
+
+ if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
+ device = AUDIO_DEVICE_OUT_SPEAKER;
+ } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
+ device = AUDIO_DEVICE_OUT_RECEIVER;
+ } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
+ device = AUDIO_DEVICE_OUT_JACK;
+ } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
+ device = AUDIO_DEVICE_OUT_BT_SCO;
+ } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) {
+ device = AUDIO_DEVICE_OUT_AUX;
+ } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) {
+ device = AUDIO_DEVICE_OUT_HDMI;
+ } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
+ device = AUDIO_DEVICE_IN_MAIN_MIC;
+ } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
+ device = AUDIO_DEVICE_IN_JACK;
+ } else if ((!strncmp(device_str, "bt", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
+ device = AUDIO_DEVICE_IN_BT_SCO;
+ } else {
+ device = AUDIO_DEVICE_NONE;
+ }
+ AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
+ return device;
+}
+
+static audio_return_t __set_devices(audio_hal_t *ah, device_info_t *devices, uint32_t num_of_devices)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ uint32_t new_device = 0;
+ const char *active_devices[MAX_DEVICES] = {NULL,};
+ int i = 0, j = 0, dev_idx = 0;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
+
+ if (num_of_devices > MAX_DEVICES) {
+ num_of_devices = MAX_DEVICES;
+ AUDIO_LOG_ERROR("error: num_of_devices");
+ return AUDIO_ERR_PARAMETER;
+ }
+
+ if (devices[0].direction == AUDIO_DIRECTION_OUT) {
+ ah->device.active_out &= 0x0;
+ if (ah->device.active_in) {
+ /* check the active in devices */
+ for (j = 0; j < inDeviceTypes[j].type; j++) {
+ if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
+ active_devices[dev_idx++] = inDeviceTypes[j].name;
+ }
+ }
+ } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
+ ah->device.active_in &= 0x0;
+ if (ah->device.active_out) {
+ /* check the active out devices */
+ for (j = 0; j < outDeviceTypes[j].type; j++) {
+ if (ah->device.active_out & outDeviceTypes[j].type)
+ active_devices[dev_idx++] = outDeviceTypes[j].name;
+ }
+ }
+ }
+
+ for (i = 0; i < num_of_devices; i++) {
+ new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction);
+ if (new_device & AUDIO_DEVICE_IN) {
+ for (j = 0; j < inDeviceTypes[j].type; j++) {
+ if (new_device == inDeviceTypes[j].type) {
+ active_devices[dev_idx++] = inDeviceTypes[j].name;
+ ah->device.active_in |= new_device;
+ }
+ }
+ } else {
+ for (j = 0; j < outDeviceTypes[j].type; j++) {
+ if (new_device == outDeviceTypes[j].type) {
+ active_devices[dev_idx++] = outDeviceTypes[j].name;
+ ah->device.active_out |= new_device;
+ }
+ }
+ }
+ }
+
+ if (active_devices[0] == NULL) {
+ AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
+ return AUDIO_ERR_PARAMETER;
+ }
+
+ return audio_ret;
+}
+
+static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ device_info_t *devices = NULL;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
+
+ devices = route_info->device_infos;
+
+ AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
+
+ audio_ret = __set_devices(ah, devices, route_info->num_of_devices);
+ if (audio_ret) {
+ AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
+ return audio_ret;
+ }
+
+ return audio_ret;
+}
+
+static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
+
+ AUDIO_LOG_INFO("update_route_voip++");
+
+ audio_ret = __set_devices(ah, devices, num_of_devices);
+ if (audio_ret) {
+ AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
+ return audio_ret;
+ }
+
+ return audio_ret;
+}
+
+static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ const char *active_devices[MAX_DEVICES] = {NULL,};
+ int i = 0, dev_idx = 0;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
+
+ if (direction == AUDIO_DIRECTION_OUT) {
+ ah->device.active_out &= 0x0;
+ if (ah->device.active_in) {
+ /* check the active in devices */
+ for (i = 0; i < inDeviceTypes[i].type; i++) {
+ if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
+ active_devices[dev_idx++] = inDeviceTypes[i].name;
+ AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
+ }
+ }
+ }
+ } else {
+ ah->device.active_in &= 0x0;
+ if (ah->device.active_out) {
+ /* check the active out devices */
+ for (i = 0; i < outDeviceTypes[i].type; i++) {
+ if (ah->device.active_out & outDeviceTypes[i].type) {
+ active_devices[dev_idx++] = outDeviceTypes[i].name;
+ AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
+ }
+ }
+ }
+ }
+
+ if (active_devices[0] == NULL) {
+ AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
+ return AUDIO_RET_OK;
+ }
+
+ return audio_ret;
+}
+
+audio_return_t _audio_routing_init(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ ah->device.active_in = 0x0;
+ ah->device.active_out = 0x0;
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t _audio_routing_deinit(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ return AUDIO_RET_OK;
+}
+
+#define LOOPBACK_ARG_LATENCY_MSEC 30
+#define LOOPBACK_ARG_ADJUST_TIME_SEC 3
+audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_hal_t *ah = (audio_hal_t *)audio_handle;
+ device_info_t *devices = NULL;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
+
+ AUDIO_LOG_INFO("role:%s", info->role);
+
+ devices = info->device_infos;
+
+ if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
+ if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices)))
+ AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret);
+
+ } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
+ if ((audio_ret = __update_route_reset(ah, devices->direction)))
+ AUDIO_LOG_WARN("update reset return 0x%x", audio_ret);
+
+ } else {
+ /* send latency and adjust time for loopback */
+ if (!strncmp("loopback", info->role, MAX_NAME_LEN)) {
+ _audio_comm_send_message(ah, "loopback::latency", LOOPBACK_ARG_LATENCY_MSEC);
+ _audio_comm_send_message(ah, "loopback::adjust_time", LOOPBACK_ARG_ADJUST_TIME_SEC);
+ }
+ /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
+ if ((audio_ret = __update_route_ap_playback_capture(ah, info)))
+ AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret);
+ }
+ return audio_ret;
+}
+
+audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_hal_t *ah = (audio_hal_t *)audio_handle;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
+
+ AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);
+
+ return audio_ret;
+}
--- /dev/null
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "tizen-audio-internal.h"
+
+/* Audio latency */
+static const char* AUDIO_LATENCY_LOW = "low";
+static const char* AUDIO_LATENCY_MID = "mid";
+static const char* AUDIO_LATENCY_HIGH = "high";
+static const char* AUDIO_LATENCY_VOIP = "voip";
+
+/* Latency msec */
+static const unsigned int PERIOD_TIME_FOR_ULOW_LATENCY_MSEC = 20;
+static const unsigned int PERIOD_TIME_FOR_LOW_LATENCY_MSEC = 25;
+static const unsigned int PERIOD_TIME_FOR_MID_LATENCY_MSEC = 50;
+static const unsigned int PERIOD_TIME_FOR_HIGH_LATENCY_MSEC = 75;
+static const unsigned int PERIOD_TIME_FOR_UHIGH_LATENCY_MSEC = 150;
+static const unsigned int PERIOD_TIME_FOR_VOIP_LATENCY_MSEC = 20;
+
+static const uint32_t g_size_table[] = {
+ [AUDIO_SAMPLE_U8] = 1,
+ [AUDIO_SAMPLE_ULAW] = 1,
+ [AUDIO_SAMPLE_ALAW] = 1,
+ [AUDIO_SAMPLE_S16LE] = 2,
+ [AUDIO_SAMPLE_S16BE] = 2,
+ [AUDIO_SAMPLE_FLOAT32LE] = 4,
+ [AUDIO_SAMPLE_FLOAT32BE] = 4,
+ [AUDIO_SAMPLE_S32LE] = 4,
+ [AUDIO_SAMPLE_S32BE] = 4,
+ [AUDIO_SAMPLE_S24LE] = 3,
+ [AUDIO_SAMPLE_S24BE] = 3,
+ [AUDIO_SAMPLE_S24_32LE] = 4,
+ [AUDIO_SAMPLE_S24_32BE] = 4
+};
+
+static int __sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
+{
+ if ((rate <= 0 ||
+ rate > (48000U*4U) ||
+ channels <= 0 ||
+ channels > 32U ||
+ format >= AUDIO_SAMPLE_MAX ||
+ format < AUDIO_SAMPLE_U8))
+ return 0;
+
+ AUDIO_LOG_ERROR("hal-latency - __sample_spec_valid() -> return true");
+
+ return 1;
+}
+
+static uint32_t __usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
+{
+ uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
+ AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
+ return ret;
+}
+
+static uint32_t __sample_size(audio_sample_format_t format)
+{
+ return g_size_table[format];
+}
+
+audio_return_t _audio_stream_init(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t _audio_stream_deinit(audio_hal_t *ah)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_hal_t *ah = (audio_hal_t *)audio_handle;
+
+ AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
+
+ AUDIO_LOG_INFO("role:%s, direction:%u, idx:%u, is_connected:%d", info->role, info->direction, info->idx, is_connected);
+
+ return audio_ret;
+}
+
+audio_return_t audio_get_buffer_attr(void *audio_handle,
+ uint32_t direction,
+ const char *latency,
+ uint32_t samplerate,
+ audio_sample_format_t format,
+ uint32_t channels,
+ uint32_t *maxlength,
+ uint32_t *tlength,
+ uint32_t *prebuf,
+ uint32_t *minreq,
+ uint32_t *fragsize)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(latency, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(maxlength, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(tlength, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(prebuf, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(minreq, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(fragsize, AUDIO_ERR_PARAMETER);
+
+ AUDIO_LOG_DEBUG("hal-latency - audio_get_buffer_attr(direction:%d, latency:%s, samplerate:%d, format:%d, channels:%d)", direction, latency, samplerate, format, channels);
+
+ uint32_t period_time = 0,
+ sample_per_period = 0;
+
+ if (__sample_spec_valid(samplerate, format, channels) == 0) {
+ return AUDIO_ERR_PARAMETER;
+ }
+
+ if (direction == AUDIO_DIRECTION_IN) {
+ if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_LOW");
+ period_time = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = -1;
+ *tlength = -1;
+ *maxlength = -1;
+ *fragsize = sample_per_period * __sample_size(format);
+ } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_MID");
+ period_time = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = -1;
+ *tlength = -1;
+ *maxlength = -1;
+ *fragsize = sample_per_period * __sample_size(format);
+ } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_HIGH");
+ period_time = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = -1;
+ *tlength = -1;
+ *maxlength = -1;
+ *fragsize = sample_per_period * __sample_size(format);
+ } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_VOIP");
+ period_time = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = -1;
+ *tlength = -1;
+ *maxlength = -1;
+ *fragsize = sample_per_period * __sample_size(format);
+ } else {
+ AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
+ return AUDIO_ERR_UNDEFINED;
+ }
+ } else { /* AUDIO_DIRECTION_OUT */
+ if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_LOW");
+ period_time = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = -1;
+ *tlength = (samplerate / 10) * __sample_size(format) * channels; /* 100ms */
+ *maxlength = -1;
+ *fragsize = 0;
+ } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_MID");
+ period_time = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = -1;
+ *tlength = (uint32_t) __usec_to_bytes(200000, samplerate, format, channels);
+ *maxlength = -1;
+ *fragsize = -1;
+ } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_HIGH");
+ period_time = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = -1;
+ *tlength = (uint32_t) __usec_to_bytes(400000, samplerate, format, channels);
+ *maxlength = -1;
+ *fragsize = -1;
+ } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
+ AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_VOIP");
+ period_time = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
+ sample_per_period = (samplerate * period_time) / 1000;
+ *prebuf = 0;
+ *minreq = __usec_to_bytes(20000, samplerate, format, channels);
+ *tlength = __usec_to_bytes(100000, samplerate, format, channels);
+ *maxlength = -1;
+ *fragsize = 0;
+ } else {
+ AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
+ return AUDIO_ERR_UNDEFINED;
+ }
+ }
+
+ AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);
+ return AUDIO_RET_OK;
+}
\ No newline at end of file
/*
* audio-hal
*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <pthread.h>
#include "tizen-audio-internal.h"
-audio_return_t _audio_util_init(audio_hal_t *ah)
-{
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
- pthread_mutex_init(&(ah->mixer.mutex), NULL);
- return AUDIO_RET_OK;
-}
-
-audio_return_t _audio_util_deinit(audio_hal_t *ah)
-{
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
- pthread_mutex_destroy(&(ah->mixer.mutex));
- return AUDIO_RET_OK;
-}
-
-#ifdef __MIXER_PARAM_DUMP
-
-static void __dump_mixer_param(char *dump, long *param, int size)
-{
- int i, len;
-
- for (i = 0; i < size; i++) {
- len = sprintf(dump, "%ld", *param);
- if (len > 0)
- dump += len;
- if (i != size -1) {
- *dump++ = ',';
- }
-
- param++;
- }
- *dump = '\0';
-}
-
-#endif
-
-audio_return_t _audio_mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size)
-{
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
-
- /* TODO. */
- return AUDIO_RET_OK;
-}
-
-audio_return_t audio_mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val)
-{
- audio_return_t audio_ret = AUDIO_RET_OK;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(val, AUDIO_ERR_PARAMETER);
-
- audio_ret = _audio_mixer_control_get_value(ah, ALSA_DEFAULT_CARD, ctl_name, val);
- return audio_ret;
-}
-
-audio_return_t _audio_mixer_control_get_value(audio_hal_t *ah, const char *card, const char *ctl_name, int *val)
-{
- snd_ctl_t *handle;
- snd_ctl_elem_value_t *control;
- snd_ctl_elem_id_t *id;
- snd_ctl_elem_info_t *info;
- snd_ctl_elem_type_t type;
-
- int ret = 0, count = 0, i = 0;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(val, AUDIO_ERR_PARAMETER);
-
- pthread_mutex_lock(&(ah->mixer.mutex));
-
- ret = snd_ctl_open(&handle, card, 0);
- if (ret < 0) {
- AUDIO_LOG_ERROR("snd_ctl_open error, %s\n", snd_strerror(ret));
- pthread_mutex_unlock(&(ah->mixer.mutex));
- return AUDIO_ERR_IOCTL;
- }
-
- // Get Element Info
-
- snd_ctl_elem_id_alloca(&id);
- snd_ctl_elem_info_alloca(&info);
- snd_ctl_elem_value_alloca(&control);
-
- snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
- snd_ctl_elem_id_set_name(id, ctl_name);
-
- snd_ctl_elem_info_set_id(info, id);
- if (snd_ctl_elem_info(handle, info) < 0) {
- AUDIO_LOG_ERROR("Cannot find control element: %s\n", ctl_name);
- goto close;
- }
- snd_ctl_elem_info_get_id(info, id);
-
- type = snd_ctl_elem_info_get_type(info);
- count = snd_ctl_elem_info_get_count(info);
-
- snd_ctl_elem_value_set_id(control, id);
-
- if (snd_ctl_elem_read(handle, control) < 0) {
- AUDIO_LOG_ERROR("snd_ctl_elem_read failed \n");
- goto close;
-}
-
- switch (type) {
- case SND_CTL_ELEM_TYPE_BOOLEAN:
- *val = snd_ctl_elem_value_get_boolean(control, i);
- break;
- case SND_CTL_ELEM_TYPE_INTEGER:
- for (i = 0; i < count; i++)
- *val = snd_ctl_elem_value_get_integer(control, i);
- break;
- case SND_CTL_ELEM_TYPE_ENUMERATED:
- for (i = 0; i < count; i++)
- *val = snd_ctl_elem_value_get_enumerated(control, i);
- break;
- default:
- AUDIO_LOG_WARN("unsupported control element type\n");
- goto close;
- }
-
- snd_ctl_close(handle);
-
-#ifdef AUDIO_DEBUG
- AUDIO_LOG_INFO("get mixer(%s) = %d success", ctl_name, *val);
-#endif
-
- pthread_mutex_unlock(&(ah->mixer.mutex));
- return AUDIO_RET_OK;
-
-close:
- AUDIO_LOG_ERROR("Error\n");
- snd_ctl_close(handle);
- pthread_mutex_unlock(&(ah->mixer.mutex));
- return AUDIO_ERR_UNDEFINED;
-}
-
-audio_return_t _audio_mixer_control_set_value(audio_hal_t *ah, const char *card, const char *ctl_name, int val)
-{
- snd_ctl_t *handle;
- snd_ctl_elem_value_t *control;
- snd_ctl_elem_id_t *id;
- snd_ctl_elem_info_t *info;
- snd_ctl_elem_type_t type;
-
- char *card_name = NULL;
- int ret = 0, count = 0, i = 0;
-
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
-
- pthread_mutex_lock(&(ah->mixer.mutex));
-
- ret = snd_ctl_open(&handle, card, 0);
- if (ret < 0) {
- AUDIO_LOG_ERROR("snd_ctl_open error, card: %s: %s", card_name, snd_strerror(ret));
- pthread_mutex_unlock(&(ah->mixer.mutex));
- return AUDIO_ERR_IOCTL;
- }
-
- // Get Element Info
-
- snd_ctl_elem_id_alloca(&id);
- snd_ctl_elem_info_alloca(&info);
- snd_ctl_elem_value_alloca(&control);
-
- snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
- snd_ctl_elem_id_set_name(id, ctl_name);
-
- snd_ctl_elem_info_set_id(info, id);
- if (snd_ctl_elem_info(handle, info) < 0) {
- AUDIO_LOG_ERROR("Cannot find control element: %s", ctl_name);
- goto close;
- }
- snd_ctl_elem_info_get_id(info, id);
-
- type = snd_ctl_elem_info_get_type(info);
- count = snd_ctl_elem_info_get_count(info);
-
- snd_ctl_elem_value_set_id(control, id);
-
- snd_ctl_elem_read(handle, control);
-
- switch (type) {
- case SND_CTL_ELEM_TYPE_BOOLEAN:
- for (i = 0; i < count; i++)
- snd_ctl_elem_value_set_boolean(control, i, val);
- break;
- case SND_CTL_ELEM_TYPE_INTEGER:
- for (i = 0; i < count; i++)
- snd_ctl_elem_value_set_integer(control, i, val);
- break;
- case SND_CTL_ELEM_TYPE_ENUMERATED:
- for (i = 0; i < count; i++)
- snd_ctl_elem_value_set_enumerated(control, i, val);
- break;
-
- default:
- AUDIO_LOG_WARN("unsupported control element type");
- goto close;
- }
-
- snd_ctl_elem_write(handle, control);
-
- snd_ctl_close(handle);
-
- AUDIO_LOG_INFO("set mixer(%s) = %d success", ctl_name, val);
-
- pthread_mutex_unlock(&(ah->mixer.mutex));
- return AUDIO_RET_OK;
-
-close:
- AUDIO_LOG_ERROR("Error");
- snd_ctl_close(handle);
- pthread_mutex_unlock(&(ah->mixer.mutex));
- return AUDIO_ERR_UNDEFINED;
-}
-
-audio_return_t _audio_mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value)
-{
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
-
- /* TODO. */
- return AUDIO_RET_OK;
-}
-
-
-audio_return_t _audio_mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem)
-{
- AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(elem, AUDIO_ERR_PARAMETER);
-
- /* TODO. */
- return AUDIO_RET_OK;
-}
-
-#ifdef __USE_TINYALSA__
-/* Convert pcm format from pulse to alsa */
-static const uint32_t g_format_convert_table[] = {
- [AUDIO_SAMPLE_U8] = PCM_FORMAT_S8,
- [AUDIO_SAMPLE_S16LE] = PCM_FORMAT_S16_LE,
- [AUDIO_SAMPLE_S32LE] = PCM_FORMAT_S32_LE,
- [AUDIO_SAMPLE_S24_32LE] = PCM_FORMAT_S24_LE
-};
-#else /* alsa-lib */
-/* Convert pcm format from pulse to alsa */
-static const uint32_t g_format_convert_table[] = {
- [AUDIO_SAMPLE_U8] = SND_PCM_FORMAT_U8,
- [AUDIO_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
- [AUDIO_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
- [AUDIO_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
- [AUDIO_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
- [AUDIO_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
- [AUDIO_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
- [AUDIO_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
- [AUDIO_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
- [AUDIO_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
- [AUDIO_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
- [AUDIO_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
- [AUDIO_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE
-};
-#endif
-
-uint32_t _convert_format(audio_sample_format_t format)
-{
- return g_format_convert_table[format];
-}
-
-/* Generic snd pcm interface APIs */
-audio_return_t _audio_pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size)
-{
- audio_return_t ret = AUDIO_RET_OK;
- snd_pcm_hw_params_t *hwparams;
- int err = 0;
- int dir;
- unsigned int val = 0;
- snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
- snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
- uint8_t _use_mmap = use_mmap && *use_mmap;
- uint32_t channels = 0;
-
- AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
-
- snd_pcm_hw_params_alloca(&hwparams);
-
- /* Skip parameter setting to null device. */
- if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
- return AUDIO_ERR_IOCTL;
-
- /* Allocate a hardware parameters object. */
- snd_pcm_hw_params_alloca(&hwparams);
-
- /* Fill it in with default values. */
- if (snd_pcm_hw_params_any(pcm, hwparams) < 0) {
- AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
- goto error;
- }
-
- /* Set the desired hardware parameters. */
-
- if (_use_mmap) {
-
- if (snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
-
- /* mmap() didn't work, fall back to interleaved */
-
- if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
- AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
- goto error;
- }
-
- _use_mmap = 0;
- }
-
- } else if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
- AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
- goto error;
- }
- AUDIO_LOG_DEBUG("setting rate - %d", sample_spec->rate);
- err = snd_pcm_hw_params_set_rate(pcm, hwparams, sample_spec->rate, 0);
- if (err < 0) {
- AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
- }
-
- err = snd_pcm_hw_params(pcm, hwparams);
- if (err < 0) {
- AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
- goto error;
- }
-
- /* Dump current param */
-
- if ((ret = snd_pcm_hw_params_current(pcm, hwparams)) < 0) {
- AUDIO_LOG_INFO("snd_pcm_hw_params_current() failed: %s", snd_strerror(ret));
- goto error;
- }
-
- if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
- (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
- AUDIO_LOG_INFO("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", snd_strerror(ret));
- goto error;
- }
-
- snd_pcm_hw_params_get_access(hwparams, (snd_pcm_access_t *) &val);
- AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
-
- snd_pcm_hw_params_get_format(hwparams, &sample_spec->format);
- AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
- snd_pcm_format_name((snd_pcm_format_t)sample_spec->format),
- snd_pcm_format_description((snd_pcm_format_t)sample_spec->format));
-
- snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val);
- AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
- snd_pcm_subformat_name((snd_pcm_subformat_t)val),
- snd_pcm_subformat_description((snd_pcm_subformat_t)val));
-
- snd_pcm_hw_params_get_channels(hwparams, &channels);
- sample_spec->channels = (uint8_t)channels;
- AUDIO_LOG_DEBUG("channels = %d\n", sample_spec->channels);
-
- if (buffer_size)
- *buffer_size = _buffer_size;
-
- if (period_size)
- *period_size = _period_size;
-
- if (use_mmap)
- *use_mmap = _use_mmap;
-
- return AUDIO_RET_OK;
-
-error:
- return AUDIO_ERR_RESOURCE;
-}
-
-audio_return_t _audio_pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event)
-{
- snd_pcm_sw_params_t *swparams;
- snd_pcm_uframes_t boundary;
- int err;
-
- AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER);
-
- snd_pcm_sw_params_alloca(&swparams);
-
- if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) {
- AUDIO_LOG_WARN("Unable to determine current swparams: %s\n", snd_strerror(err));
- goto error;
- }
- if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
- AUDIO_LOG_WARN("Unable to disable period event: %s\n", snd_strerror(err));
- goto error;
- }
- if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
- AUDIO_LOG_WARN("Unable to enable time stamping: %s\n", snd_strerror(err));
- goto error;
- }
- if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
- AUDIO_LOG_WARN("Unable to get boundary: %s\n", snd_strerror(err));
- goto error;
- }
- if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
- AUDIO_LOG_WARN("Unable to set stop threshold: %s\n", snd_strerror(err));
- goto error;
- }
- if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) avail_min)) < 0) {
- AUDIO_LOG_WARN("Unable to set start threshold: %s\n", snd_strerror(err));
- goto error;
- }
- if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
- AUDIO_LOG_WARN("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err));
- goto error;
- }
- if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
- AUDIO_LOG_WARN("Unable to set sw params: %s\n", snd_strerror(err));
- goto error;
- }
- return AUDIO_RET_OK;
-error:
- return err;
-}
-
/* ------ dump helper -------- */
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-dump_data_t* dump_new(int length)
+dump_data_t* _audio_dump_new(int length)
{
dump_data_t* dump = NULL;
return dump;
}
-void dump_add_str(dump_data_t *dump, const char *fmt, ...)
+void _audio_dump_add_str(dump_data_t *dump, const char *fmt, ...)
{
int len;
va_list ap;
dump->left -= MAX(0, len);
}
-char* dump_get_str(dump_data_t *dump)
+char* _audio_dump_get_str(dump_data_t *dump)
{
return (dump) ? dump->strbuf : NULL;
}
-void dump_free(dump_data_t *dump)
+void _audio_dump_free(dump_data_t *dump)
{
if (dump) {
if (dump->strbuf)
/*
* audio-hal
*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/*
* audio-hal
*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "tizen-audio-internal.h"
-/* audio latency */
-static const char* AUDIO_LATENCY_LOW = "low";
-static const char* AUDIO_LATENCY_MID = "mid";
-static const char* AUDIO_LATENCY_HIGH = "high";
-static const char* AUDIO_LATENCY_VOIP = "voip";
-
-audio_return_t audio_add_message_cb(void *audio_handle, message_cb callback, void *user_data)
-{
- audio_return_t ret = AUDIO_RET_OK;
-
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
-
- /* NOTE: Management of several callbacks could be implemented.
- But we do not care of it for now.*/
- ret = _audio_comm_set_message_callback((audio_hal_t *)audio_handle, callback, user_data);
-
- return ret;
-}
-
-audio_return_t audio_remove_message_cb(void *audio_handle, message_cb callback)
-{
- audio_return_t ret = AUDIO_RET_OK;
-
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(callback, AUDIO_ERR_PARAMETER);
-
- ret = _audio_comm_unset_message_callback((audio_hal_t *)audio_handle);
-
- return ret;
-}
-
audio_return_t audio_init(void **audio_handle)
{
audio_hal_t *ah;
AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
if (!(ah = malloc(sizeof(audio_hal_t)))) {
- AUDIO_LOG_ERROR("am malloc failed");
+ AUDIO_LOG_ERROR("failed to malloc()");
return AUDIO_ERR_RESOURCE;
}
- if (AUDIO_IS_ERROR((ret = _audio_device_init(ah)))) {
- AUDIO_LOG_ERROR("device init failed");
+ if ((ret = _audio_volume_init(ah))) {
+ AUDIO_LOG_ERROR("failed to _audio_volume_init(), ret(0x%x)", ret);
+ goto error_exit;
+ }
+ if ((ret = _audio_routing_init(ah))) {
+ AUDIO_LOG_ERROR("failed to _audio_routing_init(), ret(0x%x)", ret);
goto error_exit;
}
- if (AUDIO_IS_ERROR((ret = _audio_volume_init(ah)))) {
- AUDIO_LOG_ERROR("stream init failed");
+ if ((ret = _audio_stream_init(ah))) {
+ AUDIO_LOG_ERROR("failed to _audio_stream_init(), ret(0x%x)", ret);
goto error_exit;
}
- if (AUDIO_IS_ERROR((ret = _audio_util_init(ah)))) {
- AUDIO_LOG_ERROR("util init failed");
+ if ((ret = _audio_pcm_init(ah))) {
+ AUDIO_LOG_ERROR("failed to _audio_pcm_init(), ret(0x%x)", ret);
goto error_exit;
}
- if (AUDIO_IS_ERROR((ret = _audio_comm_init(ah)))) {
- AUDIO_LOG_ERROR("comm init failed");
+ if ((ret = _audio_comm_init(ah))) {
+ AUDIO_LOG_ERROR("failed to _audio_comm_init(), ret(0x%x)", ret);
goto error_exit;
}
AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
- _audio_device_deinit(ah);
_audio_volume_deinit(ah);
- _audio_util_deinit(ah);
+ _audio_routing_deinit(ah);
+ _audio_stream_deinit(ah);
+ _audio_pcm_deinit(ah);
_audio_comm_deinit(ah);
free(ah);
ah = NULL;
return AUDIO_RET_OK;
-}
-
-/* Latency msec */
-static const unsigned int PERIOD_TIME_FOR_ULOW_LATENCY_MSEC = 20;
-static const unsigned int PERIOD_TIME_FOR_LOW_LATENCY_MSEC = 25;
-static const unsigned int PERIOD_TIME_FOR_MID_LATENCY_MSEC = 50;
-static const unsigned int PERIOD_TIME_FOR_HIGH_LATENCY_MSEC = 75;
-static const unsigned int PERIOD_TIME_FOR_UHIGH_LATENCY_MSEC = 150;
-static const unsigned int PERIOD_TIME_FOR_VOIP_LATENCY_MSEC = 20;
-
-static const uint32_t g_size_table[] = {
- [AUDIO_SAMPLE_U8] = 1,
- [AUDIO_SAMPLE_ULAW] = 1,
- [AUDIO_SAMPLE_ALAW] = 1,
- [AUDIO_SAMPLE_S16LE] = 2,
- [AUDIO_SAMPLE_S16BE] = 2,
- [AUDIO_SAMPLE_FLOAT32LE] = 4,
- [AUDIO_SAMPLE_FLOAT32BE] = 4,
- [AUDIO_SAMPLE_S32LE] = 4,
- [AUDIO_SAMPLE_S32BE] = 4,
- [AUDIO_SAMPLE_S24LE] = 3,
- [AUDIO_SAMPLE_S24BE] = 3,
- [AUDIO_SAMPLE_S24_32LE] = 4,
- [AUDIO_SAMPLE_S24_32BE] = 4
-};
-
-int _sample_spec_valid(uint32_t rate, audio_sample_format_t format, uint32_t channels)
-{
- if ((rate <= 0 ||
- rate > (48000U*4U) ||
- channels <= 0 ||
- channels > 32U ||
- format >= AUDIO_SAMPLE_MAX ||
- format < AUDIO_SAMPLE_U8))
- return 0;
-
- AUDIO_LOG_ERROR("hal-latency - _sample_spec_valid() -> return true");
-
- return 1;
-}
-
-uint32_t _audio_usec_to_bytes(uint64_t t, uint32_t rate, audio_sample_format_t format, uint32_t channels)
-{
- uint32_t ret = (uint32_t) (((t * rate) / 1000000ULL)) * (g_size_table[format] * channels);
- AUDIO_LOG_DEBUG("hal-latency - return %d", ret);
- return ret;
-}
-
-uint32_t _audio_sample_size(audio_sample_format_t format)
-{
- return g_size_table[format];
-}
-audio_return_t audio_get_buffer_attr(void *audio_handle,
- uint32_t direction,
- const char *latency,
- uint32_t samplerate,
- audio_sample_format_t format,
- uint32_t channels,
- uint32_t *maxlength,
- uint32_t *tlength,
- uint32_t *prebuf,
- uint32_t *minreq,
- uint32_t *fragsize)
-{
- AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(latency, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(maxlength, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(tlength, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(prebuf, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(minreq, AUDIO_ERR_PARAMETER);
- AUDIO_RETURN_VAL_IF_FAIL(fragsize, AUDIO_ERR_PARAMETER);
-
- AUDIO_LOG_DEBUG("hal-latency - audio_get_buffer_attr(direction:%d, latency:%s, samplerate:%d, format:%d, channels:%d)", direction, latency, samplerate, format, channels);
-
- uint32_t period_time = 0,
- sample_per_period = 0;
-
- if (_sample_spec_valid(samplerate, format, channels) == 0) {
- return AUDIO_ERR_PARAMETER;
- }
-
- if (direction == AUDIO_DIRECTION_IN) {
- if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_LOW");
- period_time = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = -1;
- *tlength = -1;
- *maxlength = -1;
- *fragsize = sample_per_period * _audio_sample_size(format);
- } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_MID");
- period_time = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = -1;
- *tlength = -1;
- *maxlength = -1;
- *fragsize = sample_per_period * _audio_sample_size(format);
- } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_HIGH");
- period_time = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = -1;
- *tlength = -1;
- *maxlength = -1;
- *fragsize = sample_per_period * _audio_sample_size(format);
- } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_IN, AUDIO_LATENCY_VOIP");
- period_time = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = -1;
- *tlength = -1;
- *maxlength = -1;
- *fragsize = sample_per_period * _audio_sample_size(format);
- } else {
- AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
- return AUDIO_ERR_UNDEFINED;
- }
- } else { /* AUDIO_DIRECTION_OUT */
- if (!strcmp(latency, AUDIO_LATENCY_LOW)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_LOW");
- period_time = PERIOD_TIME_FOR_LOW_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = -1;
- *tlength = (samplerate / 10) * _audio_sample_size(format) * channels; /* 100ms */
- *maxlength = -1;
- *fragsize = 0;
- } else if (!strcmp(latency, AUDIO_LATENCY_MID)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_MID");
- period_time = PERIOD_TIME_FOR_MID_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = -1;
- *tlength = (uint32_t) _audio_usec_to_bytes(200000, samplerate, format, channels);
- *maxlength = -1;
- *fragsize = -1;
- } else if (!strcmp(latency, AUDIO_LATENCY_HIGH)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_HIGH");
- period_time = PERIOD_TIME_FOR_HIGH_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = -1;
- *tlength = (uint32_t) _audio_usec_to_bytes(400000, samplerate, format, channels);
- *maxlength = -1;
- *fragsize = -1;
- } else if (!strcmp(latency, AUDIO_LATENCY_VOIP)) {
- AUDIO_LOG_DEBUG("AUDIO_DIRECTION_OUT, AUDIO_LATENCY_VOIP");
- period_time = PERIOD_TIME_FOR_VOIP_LATENCY_MSEC;
- sample_per_period = (samplerate * period_time) / 1000;
- *prebuf = 0;
- *minreq = _audio_usec_to_bytes(20000, samplerate, format, channels);
- *tlength = _audio_usec_to_bytes(100000, samplerate, format, channels);
- *maxlength = -1;
- *fragsize = 0;
- } else {
- AUDIO_LOG_ERROR("hal-latency - The latency(%s) is undefined", latency);
- return AUDIO_ERR_UNDEFINED;
- }
- }
-
- AUDIO_LOG_INFO("hal-latency - return attr --> prebuf:%d, minreq:%d, tlength:%d, maxlength:%d, fragsize:%d", *prebuf, *minreq, *tlength, *maxlength, *fragsize);
- return AUDIO_RET_OK;
-}
+}
\ No newline at end of file
/*
* audio-hal
*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <stdint.h>
/* Error code */
-#define AUDIO_IS_ERROR(ret) (ret < 0)
typedef enum audio_return {
AUDIO_RET_OK = 0,
AUDIO_ERR_UNDEFINED = (int32_t)0x80001000,
audio_return_t (*update_route_option)(void *audio_handle, audio_route_option_t *option);
/* Stream */
audio_return_t (*notify_stream_connection_changed)(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected);
- /* Buffer attribute */
audio_return_t (*get_buffer_attr)(void *audio_handle, uint32_t direction, const char *latency, uint32_t samplerate, int format, uint32_t channels,
uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
- /* PCM device */
+ /* PCM */
audio_return_t (*pcm_open)(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
audio_return_t (*pcm_start)(void *audio_handle, void *pcm_handle);
audio_return_t (*pcm_stop)(void *audio_handle, void *pcm_handle);