Support various audio-hal interfaces such as file, socket, and so on 04/315104/14
authorJaechul Lee <jcsing.lee@samsung.com>
Wed, 9 Aug 2023 08:41:03 +0000 (17:41 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Thu, 22 Aug 2024 02:40:19 +0000 (11:40 +0900)
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 <jcsing.lee@samsung.com>
Makefile.am
hal-backend-audio.c
packaging/audio-hal-bcm2837.spec
tizen-audio-file.c [new file with mode: 0644]
tizen-audio-file.h [new file with mode: 0644]
tizen-audio-glue.c [new file with mode: 0644]
tizen-audio-glue.h [new file with mode: 0644]
tizen-audio-impl-pcm.c
tizen-audio-internal.h
tizen-audio-pcm.c
tizen-audio-pcm.h [new file with mode: 0644]

index fc8b23335f374f6d26e8cc13893e0b2788505d2e..f3b53c14a867e3589bdf2353a4e36cac39690f17 100644 (file)
@@ -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 \
index 224edf2c5544492070909123e3b8e1c3ccaa16b9..0ad2e0577a6801850b9230434beca6fa7fce0e75 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdint.h>
 #include <errno.h>
 #include <tizen-audio.h>
+#include <tizen-audio-glue.h>
 #include <hal/hal-common-interface.h>
 
 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;
index e00ce2036be9f7a986dfc896910563d194027cf2..aab49dec21d5d2374639b021baeef73e1397de79 100644 (file)
@@ -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 (file)
index 0000000..d32a174
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdatomic.h>
+#include <errno.h>
+
+#include <tizen-audio.h>
+#include <hal/hal-common-interface.h>
+#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 (file)
index 0000000..b5a91fb
--- /dev/null
@@ -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 <hal/hal-audio-interface.h>
+#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 (file)
index 0000000..7aadff0
--- /dev/null
@@ -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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#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 (file)
index 0000000..304175a
--- /dev/null
@@ -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 <tizen-audio.h>
+
+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
+
index 19df164dc7d3cea4764ec3081a7d0068f4aa4c1e..d538b1854b427fcf26ec648974154e2a042aec8e 100644 (file)
@@ -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;
 }
 
index 18d4563cbd313c66071be836f770b675fb343fdd..39795d5f18055102b5485201b55d96aaf3cd35f9 100644 (file)
@@ -30,6 +30,8 @@
 #include <pthread.h>
 #include <use-case.h>
 #include "tizen-audio.h"
+#include <hal/hal-audio-interface.h>
+#include <stdatomic.h>
 
 /* 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
+
index 7759bb66a173c888a3d507c401480b11c0db4128..51b34b9edffbbbf0a5f386154f50c9557f33b3b1 100644 (file)
@@ -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 (file)
index 0000000..8d8b137
--- /dev/null
@@ -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 <hal/hal-audio-interface.h>
+#include "tizen-audio-internal.h"
+
+DECLARE_HAL_INTERFACE(pcm);
+
+#endif