#include <modules/udev-util.h>
#endif
+#ifdef __TIZEN__
+#include <dlfcn.h>
+#endif
+
#include "alsa-util.h"
#include "alsa-ucm.h"
#include "alsa-sink.h"
"use_ucm=<load use case manager> "
"avoid_resampling=<use stream original sample rate if possible?> "
"control=<name of mixer control> "
+#ifdef __TIZEN__
+ "use_tizen_hal=<use tizen hal through tizenaudio-sink2/source2>"
+#endif
);
static const char* const valid_modargs[] = {
"use_ucm",
"avoid_resampling",
"control",
+#ifdef __TIZEN__
+ "use_tizen_hal",
+#endif
NULL
};
*/
#define PROFILE_PRIO_BONUS 0x8000
+#ifdef __TIZEN__
+#define DEFINE_TYPE(rtype, name, ...) \
+ typedef rtype (* name)(__VA_ARGS__)
+#define DEFINE_TYPE_WITH_PARAM(rtype, name) \
+ DEFINE_TYPE(rtype, name, \
+ pa_module *, pa_modargs *, \
+ const char *, pa_card *, char **, \
+ pa_sample_spec *, pa_channel_map *)
+
+#define PA_TIZEN_HAL_FILEPATH "libtizenaudio-util.so"
+#define PA_TIZEN_HAL_SINK2_NEW "pa_tizenaudio_sink2_new"
+#define PA_TIZEN_HAL_SOURCE2_NEW "pa_tizenaudio_source2_new"
+#define PA_TIZEN_HAL_SINK2_FREE "pa_tizenaudio_sink2_free"
+#define PA_TIZEN_HAL_SOURCE2_FREE "pa_tizenaudio_source2_free"
+
+DEFINE_TYPE_WITH_PARAM(pa_sink *, dl_sink_new_t);
+DEFINE_TYPE_WITH_PARAM(pa_source *, dl_source_new_t);
+DEFINE_TYPE(void, dl_sink_free_t, pa_sink *);
+DEFINE_TYPE(void, dl_source_free_t, pa_source *);
+#endif
+
struct userdata {
pa_core *core;
pa_module *module;
bool use_ucm;
pa_alsa_ucm_config ucm;
+#ifdef __TIZEN__
+ bool use_tizen_hal;
+#endif
};
struct profile_data {
pa_alsa_profile *profile;
};
+#ifdef __TIZEN__
+static void *pa_dl_get_tizenaudio_function(const char *func) {
+ void *ret = NULL, *h = NULL;
+ char *path = NULL;
+
+ path = pa_sprintf_malloc("%s/%s", PA_DLSEARCHPATH, PA_TIZEN_HAL_FILEPATH);
+ if (!path) {
+ pa_log_error("Failed to alloc path");
+ return NULL;
+ }
+
+ h = dlopen(path, RTLD_LAZY);
+ if (!h) {
+ pa_log_error("Failed to get dl handle (%s)", path);
+ goto out;
+ }
+
+ ret = dlsym(h, func);
+ if (!ret) {
+ pa_log_error("Failed to get symbol (%s)", func);
+ goto out;
+ }
+
+out:
+ if (h)
+ dlclose(h);
+ if (path)
+ pa_xfree(path);
+
+ return ret;
+}
+
+static pa_sink *pa_dl_alsa_sink_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *card, pa_alsa_mapping *mapping) {
+ pa_sink *s;
+ dl_sink_new_t dl_sink_new;
+ struct userdata *u = (struct userdata *)m->userdata;
+
+ if (!u->use_tizen_hal)
+ goto exit;
+
+ if (!(dl_sink_new = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SINK2_NEW))) {
+ pa_log_error("Failed to get sink_new function. Uses alsa-sink");
+ goto exit;
+ }
+
+ pa_log_info("Try to load sink. mapping name(%s), description(%s)", mapping->name, mapping->description);
+
+ s = dl_sink_new(m, ma, driver, card, mapping->device_strings,
+ &mapping->sample_spec, &mapping->channel_map);
+ if (!s) {
+ pa_log_error("Failed to create sink. Uses alsa-sink");
+ goto exit;
+ }
+
+ return s;
+
+exit:
+ return pa_alsa_sink_new(m, ma, driver, card, mapping);
+}
+
+static pa_source *pa_dl_alsa_source_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *card, pa_alsa_mapping *mapping) {
+ pa_source *s;
+ dl_source_new_t dl_source_new;
+ struct userdata *u = (struct userdata *)m->userdata;
+
+ if (!u->use_tizen_hal)
+ goto exit;
+
+ if (!(dl_source_new = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SOURCE2_NEW))) {
+ pa_log_error("Failed to get source_new function. Uses alsa-source");
+ goto exit;
+ }
+
+ pa_log_info("Try to load sink. mapping name(%s), description(%s)", mapping->name, mapping->description);
+
+ s = dl_source_new(m, ma, driver, card, mapping->device_strings,
+ &mapping->sample_spec, &mapping->channel_map);
+
+ if (!s) {
+ pa_log_error("Failed to create source. Uses alsa-source");
+ goto exit;
+ }
+
+ return s;
+
+exit:
+ return pa_alsa_source_new(m, ma, driver, card, mapping);
+}
+
+static void pa_dl_alsa_sink_free(pa_sink *s) {
+ pa_module *m;
+ struct userdata *u;
+ dl_sink_free_t dl_sink_free;
+
+ pa_assert(s);
+ pa_assert(s->module);
+ pa_assert(s->module->userdata);
+
+ m = s->module;
+ u = m->userdata;
+
+ if (u->use_tizen_hal) {
+ dl_sink_free = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SINK2_FREE);
+ dl_sink_free(s);
+ return;
+ }
+
+ pa_alsa_sink_free(s);
+}
+
+static void pa_dl_alsa_source_free(pa_source *s) {
+ pa_module *m;
+ struct userdata *u;
+ dl_source_free_t dl_source_free;
+
+ pa_assert(s);
+ pa_assert(s->module);
+ pa_assert(s->module->userdata);
+
+ m = s->module;
+ u = m->userdata;
+
+ if (u->use_tizen_hal) {
+ dl_source_free = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SOURCE2_FREE);
+ dl_source_free(s);
+ return;
+ }
+
+ pa_alsa_source_free(s);
+}
+#endif
+
static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) {
pa_alsa_profile *ap;
void *state;
continue;
sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs);
+#ifdef __TIZEN__
+ pa_dl_alsa_sink_free(am->sink);
+#else
pa_alsa_sink_free(am->sink);
+#endif
am->sink = NULL;
}
continue;
source_outputs = pa_source_move_all_start(am->source, source_outputs);
+#ifdef __TIZEN__
+ pa_dl_alsa_source_free(am->source);
+#else
pa_alsa_source_free(am->source);
+#endif
am->source = NULL;
}
PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) {
if (!am->sink)
+#ifdef __TIZEN__
+ am->sink = pa_dl_alsa_sink_new(c->module, u->modargs, __FILE__, c, am);
+#else
am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am);
+#endif
if (sink_inputs && am->sink) {
pa_sink_move_all_finish(am->sink, sink_inputs, false);
PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) {
if (!am->source)
+#ifdef __TIZEN__
+ am->source = pa_dl_alsa_source_new(c->module, u->modargs, __FILE__, c, am);
+#else
am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am);
+#endif
if (source_outputs && am->source) {
pa_source_move_all_finish(am->source, source_outputs, false);
if (d->profile && d->profile->output_mappings)
PA_IDXSET_FOREACH(am, d->profile->output_mappings, idx)
+#ifdef __TIZEN__
+ am->sink = pa_dl_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am);
+#else
am->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am);
+#endif
if (d->profile && d->profile->input_mappings)
PA_IDXSET_FOREACH(am, d->profile->input_mappings, idx)
+#ifdef __TIZEN__
+ am->source = pa_dl_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am);
+#else
am->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am);
+#endif
}
static pa_available_t calc_port_state(pa_device_port *p, struct userdata *u) {
goto fail;
}
+#ifdef __TIZEN__
+ if (pa_modargs_get_value_boolean(u->modargs, "use_tizen_hal", &u->use_tizen_hal) < 0) {
+ pa_log("Failed to parse use_tizen_hal= argument.");
+ goto fail;
+ }
+#endif
+
/* Force ALSA to reread its configuration. This matters if our device
* was hot-plugged after ALSA has already read its configuration - see
* https://bugs.freedesktop.org/show_bug.cgi?id=54029
pa_hashmap_free(u->jacks);
if (u->card && u->card->sinks)
+#ifdef __TIZEN__
+ pa_idxset_remove_all(u->card->sinks, (pa_free_cb_t) pa_dl_alsa_sink_free);
+#else
pa_idxset_remove_all(u->card->sinks, (pa_free_cb_t) pa_alsa_sink_free);
+#endif
if (u->card && u->card->sources)
+#ifdef __TIZEN__
+ pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_dl_alsa_source_free);
+#else
pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_alsa_source_free);
+#endif
if (u->card)
pa_card_free(u->card);