From: Jaechul Lee Date: Wed, 9 Aug 2023 08:41:03 +0000 (+0900) Subject: Support various audio-hal interfaces such as file, socket, and so on X-Git-Tag: accepted/tizen/unified/20240905.164042~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=99f326da77c88b9df0bd8f2c46490d4f3d5a3227;p=platform%2Fadaptation%2Fap_broadcom%2Faudio-hal-bcm2837.git Support various audio-hal interfaces such as file, socket, and so on several interfaces could be added in device-map.json file like this. "device-string":"tizen2:file,/opt/usr/media/test.raw" "device-string":"tizen2:sock,192.168.0.1:8888" "device-string":"tizen2:sock,/tmp/uds" [Version] 0.2.0 [Issue Type] New feature Change-Id: I282f86d8ec1466669cf0745ef902a7f5e3bb5a57 Signed-off-by: Jaechul Lee --- diff --git a/Makefile.am b/Makefile.am index fc8b233..f3b53c1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,9 @@ lib_LTLIBRARIES = libhal-backend-audio.la -libhal_backend_audio_la_SOURCES = tizen-audio.c \ +libhal_backend_audio_la_SOURCES = \ + tizen-audio-file.c \ + tizen-audio-glue.c \ + tizen-audio.c \ tizen-audio-volume.c \ tizen-audio-routing.c \ tizen-audio-stream.c \ diff --git a/hal-backend-audio.c b/hal-backend-audio.c index 224edf2..0ad2e05 100644 --- a/hal-backend-audio.c +++ b/hal-backend-audio.c @@ -22,6 +22,7 @@ #include #include #include +#include #include static int audio_rpi_init(void **data) @@ -43,27 +44,24 @@ static int audio_rpi_init(void **data) funcs->set_volume_mute = audio_set_volume_mute; funcs->set_volume_ratio = audio_set_volume_ratio; funcs->notify_ducking_activation_changed = audio_notify_ducking_activation_changed; - + funcs->notify_stream_connection_changed = audio_notify_stream_connection_changed; funcs->update_route = audio_update_route; funcs->update_route_option = audio_update_route_option; - - funcs->notify_stream_connection_changed = audio_notify_stream_connection_changed; - - funcs->pcm_open = audio_pcm_open; - funcs->pcm_start = audio_pcm_start; - funcs->pcm_stop = audio_pcm_stop; - funcs->pcm_close = audio_pcm_close; - funcs->pcm_avail = audio_pcm_avail; - funcs->pcm_write = audio_pcm_write; - funcs->pcm_read = audio_pcm_read; - funcs->pcm_get_fd = audio_pcm_get_fd; - funcs->pcm_recover = audio_pcm_recover; - funcs->pcm_get_params = audio_pcm_get_params; - funcs->pcm_set_params = audio_pcm_set_params; - funcs->add_message_cb = audio_add_message_cb; funcs->remove_message_cb = audio_remove_message_cb; + funcs->pcm_open = audio_glue_open; + funcs->pcm_start = audio_glue_start; + funcs->pcm_stop = audio_glue_stop; + funcs->pcm_close = audio_glue_close; + funcs->pcm_avail = audio_glue_avail; + funcs->pcm_write = audio_glue_write; + funcs->pcm_read = audio_glue_read; + funcs->pcm_get_fd = audio_glue_get_fd; + funcs->pcm_recover = audio_glue_recover; + funcs->pcm_get_params = audio_glue_get_params; + funcs->pcm_set_params = audio_glue_set_params; + *data = (void *)funcs; return 0; diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index e00ce20..aab49de 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.23 +Version: 0.2.0 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-file.c b/tizen-audio-file.c new file mode 100644 index 0000000..d32a174 --- /dev/null +++ b/tizen-audio-file.c @@ -0,0 +1,202 @@ +/* + * audio-hal + * + * Copyright (c) 2024 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 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "tizen-audio-file.h" +#include "tizen-audio-internal.h" + +#define SUPPORT_SAMPLERATE 48000 +#define SUPPORT_CHANNELS 2 +typedef struct { + FILE *fp; + int direction; + uint32_t sample_size; + + uint32_t period_size; + uint32_t periods; +} audio_file_handle_t; + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +static audio_return_e audio_file_open(void *audio_handle, const char *type, const char *filename, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **handle) +{ + audio_file_handle_t *h; + audio_pcm_sample_spec_s ss; + + convert_hal_format_from_sample_spec(sample_spec, &ss); + + if (ss.rate != SUPPORT_SAMPLERATE) { + AUDIO_LOG_ERROR("not support rate"); + return AUDIO_ERR_PARAMETER; + } + + if (ss.channels != SUPPORT_CHANNELS) { + AUDIO_LOG_ERROR("not support channels"); + return AUDIO_ERR_PARAMETER; + } + + if (ss.format != SND_PCM_FORMAT_S16_LE) { + AUDIO_LOG_ERROR("not support format"); + return AUDIO_ERR_PARAMETER; + } + + h = (audio_file_handle_t *)calloc(sizeof(audio_file_handle_t), 1); + if (!h) { + AUDIO_LOG_ERROR("failed to allocate handle"); + return AUDIO_ERR_INTERNAL; + } + + h->fp = fopen(filename, "w"); + if (!h->fp) { + AUDIO_LOG_ERROR("failed to open file name(%s)", filename); + free(h); + return AUDIO_ERR_INTERNAL; + } + + h->direction = direction; + h->period_size = period_size; + h->periods = periods; + h->sample_size = SUPPORT_CHANNELS * 2; + + *handle = (void *)h; + + AUDIO_LOG_ERROR("file opened. filename(%s)", filename); + + return AUDIO_RET_OK; +} + +static audio_return_e audio_file_start(void *audio_handle, void *handle) +{ + return AUDIO_RET_OK; +} + +static audio_return_e audio_file_stop(void *audio_handle, void *handle) +{ + return AUDIO_RET_OK; +} + +static audio_return_e audio_file_close(void *audio_handle, void *handle) +{ + audio_file_handle_t *h = (audio_file_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(h, AUDIO_ERR_PARAMETER); + + fclose(h->fp); + + return AUDIO_RET_OK; +} + +static audio_return_e audio_file_avail(void *audio_handle, void *handle, uint32_t *avail) +{ + audio_file_handle_t *h = (audio_file_handle_t *)handle; + long cur, end; + + AUDIO_RETURN_VAL_IF_FAIL(h, AUDIO_ERR_PARAMETER); + + if (h->direction == AUDIO_DIRECTION_OUT) { + *avail = h->period_size * h->periods * h->sample_size; + return AUDIO_RET_OK; + } + + cur = ftell(h->fp); + if (cur < 0) { + AUDIO_LOG_ERROR("failed to get ftell(%d)", errno); + return AUDIO_ERR_INTERNAL; + } + + fseek(h->fp, 0L, SEEK_END); + end = ftell(h->fp); + if (end < 0) { + AUDIO_LOG_ERROR("failed to get ftell(%d)", errno); + return AUDIO_ERR_INTERNAL; + } + + fseek(h->fp, cur, SEEK_SET); + + *avail = (uint32_t)MAX(end - cur, 0); + + return AUDIO_RET_OK; +} + +static audio_return_e audio_file_write(void *audio_handle, void *handle, const void *buffer, uint32_t frames) +{ + audio_file_handle_t *h = (audio_file_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(h, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(buffer, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(frames != 0, AUDIO_ERR_PARAMETER); + + if ((fwrite(buffer, h->sample_size, frames, h->fp)) == 0) { + AUDIO_LOG_ERROR("failed to read(%d)", errno); + return AUDIO_ERR_INTERNAL; + } + + return AUDIO_RET_OK; +} + +static audio_return_e audio_file_read(void *audio_handle, void *handle, void *buffer, uint32_t frames) +{ + audio_file_handle_t *h = (audio_file_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(h, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(buffer, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(frames != 0, AUDIO_ERR_PARAMETER); + + if (fread(buffer, sizeof(short), frames, h->fp) == 0) { + AUDIO_LOG_ERROR("failed to read(%d)", errno); + return AUDIO_ERR_INTERNAL; + } + + return AUDIO_RET_OK; +} + +static audio_return_e audio_file_get_fd(void *audio_handle, void *handle, int *fd) +{ + return AUDIO_ERR_NOT_IMPLEMENTED; +} + +static audio_return_e audio_file_recover(void *audio_handle, void *handle, int revents) +{ + return AUDIO_ERR_NOT_IMPLEMENTED; +} + +static audio_return_e audio_file_get_params(void *audio_handle, void *handle, uint32_t direction, void *sample_spec, uint32_t *period_size, uint32_t *periods) +{ + return AUDIO_ERR_NOT_IMPLEMENTED; +} + +static audio_return_e audio_file_set_params(void *audio_handle, void *handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +{ + return AUDIO_ERR_NOT_IMPLEMENTED; +} + +DEFINE_HAL_INTERFACE_FUNCTIONS(file) diff --git a/tizen-audio-file.h b/tizen-audio-file.h new file mode 100644 index 0000000..b5a91fb --- /dev/null +++ b/tizen-audio-file.h @@ -0,0 +1,28 @@ +/* + * audio-hal + * + * Copyright (c) 2024 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. + * + */ + +#ifndef footizenaudiofilefoo +#define footizenaudiofilefoo + +#include +#include "tizen-audio-internal.h" + +DECLARE_HAL_INTERFACE(file); + +#endif diff --git a/tizen-audio-glue.c b/tizen-audio-glue.c new file mode 100644 index 0000000..7aadff0 --- /dev/null +++ b/tizen-audio-glue.c @@ -0,0 +1,274 @@ +/* + * audio-hal + * + * Copyright (c) 2024 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. + * + */ + +#include +#include +#include +#include "tizen-audio-glue.h" +#include "tizen-audio.h" +#include "tizen-audio-internal.h" +#include "tizen-audio-file.h" +#include "tizen-audio-pcm.h" + +typedef hal_backend_audio_funcs *(*get_interface_func)(void); + +typedef struct { + const char *name; + get_interface_func get_interface; +} interface_t; + +typedef struct { + hal_backend_audio_funcs *interface; + void *instance; +} interface_handle_t; + +static interface_t interfaces[] = +{ + HAL_INTERFACE(default, pcm), + HAL_INTERFACE(file, file), + { NULL, NULL }, +}; + +hal_backend_audio_funcs *audio_glue_interface_factory(const char *interface_name) { + int i; + + if (!interface_name) + return NULL; + + for (i=0; interfaces[i].name; i++) { + if (!strncmp(interfaces[i].name, interface_name, strlen(interfaces[i].name) + 1)) { + if (interfaces[i].get_interface == NULL) + return NULL; + + AUDIO_LOG_INFO("%s interface will be created", interface_name); + + return interfaces[i].get_interface(); + } + } + + AUDIO_LOG_INFO("default interface(alsa) will be created"); + + return interfaces[0].get_interface(); +} + +audio_return_e audio_glue_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **handle) +{ + interface_handle_t *ih; + hal_backend_audio_funcs *interface; + void *glue_handle = NULL; + audio_pcm_sample_spec_s *ss = (audio_pcm_sample_spec_s *)sample_spec; + int ret; + + /* the list of sub interface such as file, audio-share and pcm + * if you describe "device-string":"tizen2:file,/opt/usr/media/out" in device-map.json, + * card has "file" and device has "/opt/usr/media/out" */ + interface = audio_glue_interface_factory(card); + if (!interface) { + AUDIO_LOG_ERROR("failed to get interface. card(%s)", card); + return AUDIO_ERR_PARAMETER; + } + + if (interface->pcm_open) { + if ((ret = interface->pcm_open(audio_handle, card, device, direction, sample_spec, period_size, periods, &glue_handle)) != AUDIO_RET_OK) { + AUDIO_LOG_ERROR("Failed to open device. ret(%x)", ret); + return ret; + } + } + + ih = (interface_handle_t *)calloc(sizeof(interface_handle_t), 1); + if (!ih) { + AUDIO_LOG_ERROR("failed to alloc interface handle instance"); + return AUDIO_ERR_INTERNAL; + } + + ih->interface = interface; + ih->instance = glue_handle; + + *handle = (void *)ih; + + AUDIO_LOG_ERROR("open success. card(%s), device(%s), direction(%s), rate(%d), channels(%d), period_size(%u), periods(%u)", + card, device, direction == AUDIO_DIRECTION_OUT ? "playback" : "capture", + ss->rate, ss->channels, period_size, periods); + + return AUDIO_RET_OK; +} + +audio_return_e audio_glue_start(void *audio_handle, void *handle) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_start) + audio_ret = ih->interface->pcm_start(audio_handle, ih->instance); + + return audio_ret; +} + +audio_return_e audio_glue_stop(void *audio_handle, void *handle) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_stop) + audio_ret = ih->interface->pcm_stop(audio_handle, ih->instance); + + return audio_ret; +} + +audio_return_e audio_glue_close(void *audio_handle, void *handle) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_close) + audio_ret = ih->interface->pcm_close(audio_handle, ih->instance); + + ih->instance = NULL; + + free(ih); + + return audio_ret; +} + +audio_return_e audio_glue_avail(void *audio_handle, void *handle, uint32_t *avail) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_avail) + audio_ret = ih->interface->pcm_avail(audio_handle, ih->instance, avail); + + return audio_ret; +} + +audio_return_e audio_glue_write(void *audio_handle, void *handle, const void *buffer, uint32_t frames) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(buffer, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_write) + audio_ret = ih->interface->pcm_write(audio_handle, ih->instance, buffer, frames); + + return audio_ret; +} + +audio_return_e audio_glue_read(void *audio_handle, void *handle, void *buffer, uint32_t frames) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(buffer, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_read) + audio_ret = ih->interface->pcm_read(audio_handle, ih->instance, buffer, frames); + + return audio_ret; +} + +audio_return_e audio_glue_get_fd(void *audio_handle, void *handle, int *fd) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(fd, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_get_fd) + audio_ret = ih->interface->pcm_get_fd(audio_handle, ih->instance, fd); + + return audio_ret; +} + +audio_return_e audio_glue_recover(void *audio_handle, void *handle, int revents) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, AUDIO_ERR_PARAMETER); + + if (ih->interface->pcm_recover) + audio_ret = ih->interface->pcm_recover(audio_handle, ih->instance, revents); + + return audio_ret; +} + +audio_return_e audio_glue_get_params(void *audio_handle, void *handle, uint32_t direction, void *sample_spec, uint32_t *period_size, uint32_t *periods) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, 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); + + if (ih->interface->pcm_get_params) + audio_ret = ih->interface->pcm_get_params(audio_handle, ih->instance, direction, sample_spec, period_size, periods); + + return audio_ret; +} + +audio_return_e audio_glue_set_params(void *audio_handle, void *handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +{ + audio_return_e audio_ret = AUDIO_ERR_INTERNAL; + interface_handle_t *ih = (interface_handle_t *)handle; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ih->instance, 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); + + if (ih->interface->pcm_set_params) + audio_ret = ih->interface->pcm_set_params(audio_handle, ih->instance, direction, sample_spec, period_size, periods); + + return audio_ret; +} + diff --git a/tizen-audio-glue.h b/tizen-audio-glue.h new file mode 100644 index 0000000..304175a --- /dev/null +++ b/tizen-audio-glue.h @@ -0,0 +1,38 @@ +/* + * audio-hal + * + * Copyright (c) 2024 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. + * + */ + +#ifndef footizenaudiogluefoo +#define footizenaudiogluefoo + +#include + +audio_return_e audio_glue_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **handle); +audio_return_e audio_glue_start(void *audio_handle, void *handle); +audio_return_e audio_glue_stop(void *audio_handle, void *handle); +audio_return_e audio_glue_close(void *audio_handle, void *handle); +audio_return_e audio_glue_avail(void *audio_handle, void *handle, uint32_t *avail); +audio_return_e audio_glue_write(void *audio_handle, void *handle, const void *buffer, uint32_t frames); +audio_return_e audio_glue_read(void *audio_handle, void *handle, void *buffer, uint32_t frames); +audio_return_e audio_glue_get_fd(void *audio_handle, void *handle, int *fd); +audio_return_e audio_glue_recover(void *audio_handle, void *handle, int revents); +audio_return_e audio_glue_get_params(void *audio_handle, void *handle, uint32_t direction, void *sample_spec, uint32_t *period_size, uint32_t *periods); +audio_return_e audio_glue_set_params(void *audio_handle, void *handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); + +#endif + diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c index 19df164..d538b18 100644 --- a/tizen-audio-impl-pcm.c +++ b/tizen-audio-impl-pcm.c @@ -160,13 +160,16 @@ audio_return_e _pcm_open(const char *card, const char *device, uint32_t directio __make_alsa_device_name(card, device, device_name); mode = SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT; + AUDIO_LOG_INFO("sound device will be opened with device_name(%s)", device_name); + if ((err = snd_pcm_open((snd_pcm_t **)pcm_handle, device_name, (direction == AUDIO_DIRECTION_OUT) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, mode)) < 0) { AUDIO_LOG_ERROR("Error opening PCM device %s : %s", device_name, snd_strerror(err)); return AUDIO_ERR_RESOURCE; } if ((ret = _pcm_set_params(*pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) { - AUDIO_LOG_ERROR("Failed to set pcm parameters : %d", ret); + snd_pcm_close(*pcm_handle); + AUDIO_LOG_ERROR("Failed to set pcm parameters : %x", ret); return ret; } @@ -529,8 +532,10 @@ static int __set_format(void *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm }; int i; - if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, *format) >= 0) + if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, *format) >= 0) { + AUDIO_LOG_INFO("Selected format format(%d)", *format); return 0; + } /* Try to find appropriate format */ for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { @@ -541,6 +546,8 @@ static int __set_format(void *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm } } + AUDIO_LOG_INFO("Failed to set format(%d)", *format); + return -1; } diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h index 18d4563..39795d5 100644 --- a/tizen-audio-internal.h +++ b/tizen-audio-internal.h @@ -30,6 +30,8 @@ #include #include #include "tizen-audio.h" +#include +#include /* Debug */ @@ -280,4 +282,37 @@ const char *parser_getstring(const dictionary_t *dict, const char *key, const ch void parser_freedict(dictionary_t *dict); void dump_dictionary(const dictionary_t *dict); +#define HAL_INTERFACE(interface_name, interface) \ +{ "##interface_name##", audio_##interface##_get_interface } + +#define DECLARE_HAL_INTERFACE(interface) \ +hal_backend_audio_funcs *audio_##interface##_get_interface(void) + +#define DEFINE_HAL_INTERFACE_FUNCTIONS(interface) \ +static hal_backend_audio_funcs *g_##interface##_funcs; \ +static atomic_int once = ATOMIC_VAR_INIT(1); \ +hal_backend_audio_funcs *audio_##interface##_get_interface(void) \ +{ \ + if (atomic_load(&once)) { \ + g_##interface##_funcs = (hal_backend_audio_funcs *)calloc(sizeof(hal_backend_audio_funcs), 1); \ + if (!g_##interface##_funcs) { \ + AUDIO_LOG_ERROR("failed to alloc interface"); \ + return NULL; \ + } \ + g_##interface##_funcs->pcm_open = audio_##interface##_open; \ + g_##interface##_funcs->pcm_start = audio_##interface##_start; \ + g_##interface##_funcs->pcm_stop = audio_##interface##_stop; \ + g_##interface##_funcs->pcm_close = audio_##interface##_close; \ + g_##interface##_funcs->pcm_avail = audio_##interface##_avail; \ + g_##interface##_funcs->pcm_write = audio_##interface##_write; \ + g_##interface##_funcs->pcm_read = audio_##interface##_read; \ + g_##interface##_funcs->pcm_get_fd = audio_##interface##_get_fd; \ + g_##interface##_funcs->pcm_recover = audio_##interface##_recover; \ + g_##interface##_funcs->pcm_get_params = audio_##interface##_get_params; \ + g_##interface##_funcs->pcm_set_params = audio_##interface##_set_params; \ + } \ + return g_##interface##_funcs; \ +} + #endif + diff --git a/tizen-audio-pcm.c b/tizen-audio-pcm.c index 7759bb6..51b34b9 100644 --- a/tizen-audio-pcm.c +++ b/tizen-audio-pcm.c @@ -190,3 +190,6 @@ audio_return_e audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32 return audio_ret; } + +DEFINE_HAL_INTERFACE_FUNCTIONS(pcm) + diff --git a/tizen-audio-pcm.h b/tizen-audio-pcm.h new file mode 100644 index 0000000..8d8b137 --- /dev/null +++ b/tizen-audio-pcm.h @@ -0,0 +1,28 @@ +/* + * audio-hal + * + * Copyright (c) 2024 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. + * + */ + +#ifndef footizenaudiopcmfoo +#define footizenaudiopcmfoo + +#include +#include "tizen-audio-internal.h" + +DECLARE_HAL_INTERFACE(pcm); + +#endif