#define SHARED_DEVICE_MANAGER "tizen-device-manager"
#define DEVICE_MAP_FILE "/etc/pulse/device-map.json"
-#define DEVICE_STR_MAX 30
+#define DEVICE_STR_MAX 40
#define DEVICE_DIRECTION_MAX 3
#define DEVICE_PARAM_STRING_MAX 150
#define DEVICE_AVAIL_COND_NUM_MAX 2
#define DEVICE_TYPE_PROP_ROLE "role"
#define DEVICE_TYPE_STR_MAX 20
+#define DEVICE_NAME_MAX 30
/* Properties of sink/sources */
}
}
-static const char* device_string_get_value(const char *device_string) {
- int len;
- const char *end_p, *value_p;
+/* device_string looks like "alsa:0,0"
+ * in this case name is "0,0" */
+static int device_string_get_name(const char *device_string, char *name) {
+ char *colon_p;
- if (!device_string) {
- return NULL;
+ if (!(colon_p = strchr(device_string, ':'))) {
+ pa_log_error("No Colon in device string");
+ return -1;
}
- len = strlen(device_string);
- end_p = device_string + len -1;
+ colon_p++;
+ if (*colon_p == '\0' || !strchr(colon_p, ',')) {
+ pa_log_error("No Comma or empty device name");
+ return -1;
+ }
- if (!(value_p = strchr(device_string, ':'))) {
- return NULL;
+ if (strlen(colon_p) >= DEVICE_NAME_MAX) {
+ pa_log_error("device name too long : %s", colon_p);
+ return -1;
}
- if (value_p < end_p) {
- return value_p + 1;
- } else {
- return NULL;
+
+ strncpy(name, colon_p, DEVICE_NAME_MAX);
+
+ return 0;
+}
+
+static int device_name_get_card(const char *device_name, char *card) {
+ const char *name_p;
+ char *card_p;
+
+ if (!strchr(device_name, ',')) {
+ pa_log_error("Failed to parse name : no comma");
+ return -1;
}
+
+ name_p = device_name;
+ card_p = card;
+ while (*name_p != ',')
+ *(card_p++) = *(name_p++);
+ *card_p = '\0';
+
+ return 0;
+}
+
+static int device_name_get_device(const char *device_name, char *device) {
+ const char *comma_p;
+ char *device_p;
+
+ if (!(comma_p = strchr(device_name, ','))) {
+ pa_log_error("Failed to parse name : no comma");
+ return -1;
+ }
+
+ comma_p++;
+ device_p = device;
+ while (*comma_p != '\0')
+ *(device_p++) = *(comma_p++);
+ *device_p = '\0';
+
+ return 0;
}
static pa_proplist* pulse_device_get_proplist(pa_object *pdevice) {
}
}
-static int pulse_device_get_alsa_device_string(pa_proplist *prop, char **device_string) {
- const char *device_string_prop = NULL;
- char *device_string_tmp;
+/* Actually this device_name is not exactly same with alsa's form (ex. "hw:0,1")
+ * this is part of that. (ex. "0,1") */
+static int pulse_device_get_device_name(pa_object *pdevice, char *device_name) {
+ pa_proplist *prop;
- if (!prop || !device_string) {
- pa_log_error("Invalid Parameter");
- return -1;
- }
+ prop = pulse_device_get_proplist(pdevice);
- if (!(device_string_prop = pa_proplist_gets(prop, "device.string"))) {
- pa_log_error("failed to get property 'device.string'");
- return -1;
- }
- if (!(device_string_tmp = strchr(device_string_prop, ':'))) {
- pa_log_error("failed to parse device string");
+ if (pulse_device_is_alsa(pdevice)) {
+ const char *device_string_prop;
+ char *name_p;
+
+ if (!(device_string_prop = pa_proplist_gets(prop, PA_PROP_DEVICE_STRING))) {
+ pa_log_error("failed to get property 'device.string'");
+ return -1;
+ }
+ if (!(name_p = strchr(device_string_prop, ':'))) {
+ pa_log_error("failed to parse device string");
+ return -1;
+ }
+ strncpy(device_name, name_p + 1, DEVICE_NAME_MAX);
+ } else if (pulse_device_is_tizenaudio(pdevice)) {
+ const char *card, *device;
+ if (!(card = pa_proplist_gets(prop, "tizen.card"))) {
+ pa_log_error("failed to get property 'tizen.card'");
+ return -1;
+ }
+ if (!(device = pa_proplist_gets(prop, "tizen.device"))) {
+ pa_log_error("failed to get property 'tizen.device'");
+ return -1;
+ }
+ snprintf(device_name, DEVICE_NAME_MAX, "%s,%s", card, device);
+ } else {
return -1;
}
-
- *device_string = device_string_tmp + 1;
-
return 0;
}
} else if (device_class == DM_DEVICE_CLASS_ALSA) {
return is_sink ? "module-alsa-sink" : "module-alsa-source";
} else if (device_class == DM_DEVICE_CLASS_TIZEN) {
- return is_sink ? "module-tizenaudio-sink" : NULL;
+ return is_sink ? "module-tizenaudio-sink" : "module-tizenaudio-source";
} else if (device_class == DM_DEVICE_CLASS_BT) {
return is_sink ? "module-bluez5-device" : NULL;
} else if (device_class == DM_DEVICE_CLASS_NULL) {
return NULL;
}
-static const char* build_params_to_load_device(const char *device_string, const char *params, dm_device_class_t device_class) {
- pa_strbuf *args_buf;
- static char args[DEVICE_PARAM_STRING_MAX] = {0,};
+static int build_params_to_load_device(const char *device_string, const char *params, dm_device_class_t device_class, char *target) {
+ char device_name[DEVICE_NAME_MAX];
- if (!device_string) {
- pa_log_error("device string null");
- return NULL;
+ pa_assert(device_string);
+ pa_assert(target);
+
+ if ((device_class != DM_DEVICE_CLASS_ALSA) && (device_class != DM_DEVICE_CLASS_TIZEN))
+ return -1;
+
+ if (device_string_get_name(device_string, device_name) < 0) {
+ pa_log_error("Invalid device string '%s'", device_string);
+ return -1;
}
- if (device_class == DM_DEVICE_CLASS_NULL) {
- return params;
- } else if (device_class == DM_DEVICE_CLASS_ALSA) {
- const char *alsa_device_name;
- if (!(alsa_device_name = device_string_get_value(device_string))) {
- pa_log_error("Invalid device string for alsa-device, '%s'", device_string);
- return NULL;
- }
- args_buf = pa_strbuf_new();
- pa_strbuf_printf(args_buf, "device=hw:%s ", alsa_device_name);
- if (params) {
- pa_strbuf_printf(args_buf, "%s", params);
- }
- pa_strlcpy(args, pa_strbuf_to_string_free(args_buf), DEVICE_PARAM_STRING_MAX);
- } else {
- return params;
+ if (device_class == DM_DEVICE_CLASS_ALSA) {
+ snprintf(target, DEVICE_PARAM_STRING_MAX, "device=hw:%s ", device_name);
+ } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
+ char card[DEVICE_NAME_MAX];
+ char device[DEVICE_NAME_MAX];
+
+ device_name_get_card(device_name, card);
+ device_name_get_device(device_name, device);
+
+ snprintf(target, DEVICE_PARAM_STRING_MAX, "card=%s device=%s ", card, device);
}
- return (const char*) args;
+ if (params)
+ strncat(target, params, DEVICE_PARAM_STRING_MAX - strlen(target));
+
+ return 0;
}
static bool device_params_is_equal(const char *params1, const char *params2) {
return device_params_is_equal(params, removed_module_args);
}
-static const char* pulse_device_get_device_string(pa_object *pdevice) {
+static int pulse_device_get_device_string(pa_object *pdevice, char *device_string) {
dm_device_class_t device_class;
- static char device_string[DEVICE_STR_MAX] = {0,};
- char *device_string_val = NULL;
- pa_proplist *prop;
+ char device_name[DEVICE_NAME_MAX];
pa_assert(pdevice);
+ pa_assert(device_string);
device_class = pulse_device_get_class(pdevice);
- prop = pulse_device_get_proplist(pdevice);
if (device_class == DM_DEVICE_CLASS_ALSA) {
- if (pulse_device_get_alsa_device_string(prop, &device_string_val) < 0)
- return NULL;
- snprintf(device_string, DEVICE_STR_MAX, "alsa:%s", device_string_val);
- return device_string;
+ if (pulse_device_get_device_name(pdevice, device_name) < 0)
+ return -1;
+ snprintf(device_string, DEVICE_STR_MAX, "alsa:%s", device_name);
+ return 0;
} else if (device_class == DM_DEVICE_CLASS_NULL) {
- return "null";
+ snprintf(device_string, DEVICE_STR_MAX, "null");
+ return 0;
} else if (device_class == DM_DEVICE_CLASS_TIZEN) {
- return "tizen";
+ if (pulse_device_get_device_name(pdevice, device_name) < 0)
+ return -1;
+ snprintf(device_string, DEVICE_STR_MAX, "tizen:%s", device_name);
+ return 0;
} else if (device_class == DM_DEVICE_CLASS_BT) {
- return "bt";
+ snprintf(device_string, DEVICE_STR_MAX, "bt");
+ return 0;
} else {
- return device_string;
+ return -1;
}
}
/* pdevice is sink or source */
static bool pulse_device_same_device_string(pa_object *pdevice, const char *device_string) {
- const char *_device_string;
+ char _device_string[DEVICE_STR_MAX];
pa_assert(pdevice);
pa_assert(device_string);
- if (!(_device_string = pulse_device_get_device_string(pdevice)))
+ if (pulse_device_get_device_string(pdevice, _device_string) < 0)
return false;
return pa_streq(_device_string, device_string);
return ctypes;
}
-static const char* pulse_device_get_device_name(pa_object *pdevice, const char *type) {
- pa_proplist *prop;
-
- pa_assert(pdevice);
- pa_assert(device_type_is_valid(type));
-
- prop = pulse_device_get_proplist(pdevice);
-
- if (pa_streq(type, DEVICE_TYPE_USB_AUDIO))
- return pa_proplist_gets(prop, "udev.id");
- else if (pa_streq(type, DEVICE_TYPE_BT_A2DP))
- return pa_proplist_gets(prop, "bluez.alias");
- else
- return NULL;
-}
-
/* If fails return -1 */
static int atoi_base16(const char *s) {
char *x = NULL;
if (is_loaded) {
pa_tz_device_new_data data;
int product_id, vendor_id;
+ pa_proplist *prop;
+
+ prop = pulse_device_get_proplist(pdevice);
+ name = pa_proplist_gets(prop, "udev.id");
- name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_USB_AUDIO);
vendor_id = pulse_device_get_vendor_id(pdevice);
product_id = pulse_device_get_product_id(pdevice);
pa_tz_device_new_data data;
const char *name;
- name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_BT_A2DP);
+ pa_proplist *prop;
+
+ prop = pulse_device_get_proplist(pdevice);
+ name = pa_proplist_gets(prop, "bluez.alias");
pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, dm->dbus_conn);
_fill_new_data_basic(&data, DEVICE_TYPE_BT_A2DP, direction, false, dm);
*/
static void* load_device(pa_core *c, bool is_sink, const char *device_string, const char *device_params) {
- const char *args = NULL;
const char *module_name;
pa_module *module;
pa_sink *sink;
pa_source *source;
uint32_t device_idx;
dm_device_class_t device_class;
+ char full_params[DEVICE_PARAM_STRING_MAX];
pa_assert(c);
pa_assert(device_string);
pa_log_warn("Invalid device_string '%s'", device_string);
return NULL;
}
+ pa_log_info("device class : %d", device_class);
if (!(module_name = device_class_get_module_name(device_class, is_sink))) {
pa_log_error("Get proper module name to load failed");
return NULL;
}
- if (!(args = build_params_to_load_device(device_string, device_params, device_class))) {
- pa_log_error("Get proper module name to load failed");
+ pa_log_info("module name : %s", module_name);
+
+ if (build_params_to_load_device(device_string, device_params, device_class, full_params) < 0) {
+ pa_log_error("build param to load module failed");
return NULL;
}
- if (!(module = pa_module_load(c, module_name, args))) {
- pa_log_error("Load module with name '%s' argu '%s' failed", module_name, args);
+ pa_log_info("argument : %s", full_params);
+
+ if (!(module = pa_module_load(c, module_name, full_params))) {
+ pa_log_error("Load module with name '%s' argu '%s' failed", module_name, full_params);
return NULL;
}
-
+ pa_log_info("module loaded : %s %u with '%s'", module->name, module->index, module->argument);
if (is_sink) {
PA_IDXSET_FOREACH(sink, c->sinks, device_idx) {
if (sink->module == module) {
+ pa_log_info("sink loaded : %s %u", sink->name, sink->index);
return sink;
}
}
} else {
PA_IDXSET_FOREACH(source, c->sources, device_idx) {
if (source->module == module) {
+ pa_log_info("source loaded : %s %u", source->name, source->index);
return source;
}
}
}
+ pa_log_warn("Failed to find matching %s after load module", is_sink ? "sink" : "source");
+
return NULL;
}
PA_MODULE_USAGE(
"sink_name=<name of sink> "
"sink_properties=<properties for the sink> "
+ "card=<card to use> "
+ "device=<device to use> "
"format=<sample format> "
"rate=<sample rate> "
"channels=<number of channels> "
pa_usec_t timestamp;
pa_usec_t timestamp_written;
+ char* card;
+ char* device;
bool first;
pa_rtpoll_item *rtpoll_item;
static const char* const valid_modargs[] = {
"sink_name",
"sink_properties",
+ "card",
+ "device",
"format",
"rate",
"channels",
u->rtpoll_item = NULL;
}
- pa_log_info("Device suspended...");
+ pa_log_info("Device suspended...[%s,%s]", u->card, u->device);
return 0;
}
}
ret = pa_hal_interface_pcm_open(u->hal_interface,
- (void **)&u->pcm_handle,
+ u->card,
+ u->device,
DIRECTION_OUT,
&sample_spec,
u->frag_size / frame_size,
- u->nfrags);
+ u->nfrags,
+ (void **)&u->pcm_handle);
if (ret) {
pa_log_error("Error opening PCM device %x", ret);
goto fail;
uint32_t alternate_sample_rate;
uint32_t block_msec;
uint32_t max_request_msec;
+ const char *card, *device;
pa_assert(m);
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
- u->frag_size = 0;
- u->nfrags = 0;
- pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size);
- pa_modargs_get_value_u32(ma, "fragments", &u->nfrags);
- if (u->frag_size == 0 || u->nfrags == 0) {
+ if (!(card = pa_modargs_get_value(ma, "card", NULL)) ||
+ !(device = pa_modargs_get_value(ma, "device", NULL))) {
+ pa_log_error("card or device are invalid");
+ goto fail;
+ }
+
+ u->card = pa_xstrdup(card);
+ u->device = pa_xstrdup(device);
+
+ u->frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
+ u->nfrags = m->core->default_n_fragments;
+ if (pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size) < 0 ||
+ pa_modargs_get_value_u32(ma, "fragments", &u->nfrags) < 0) {
pa_log_error("fragment_size or fragments are invalid.");
goto fail;
}
- pa_log_info("fragment_size(%u), fragments(%u)", u->frag_size, u->nfrags);
+ pa_log_info("card(%s) device(%s) fragment_size(%u), fragments(%u)", u->card, u->device, u->frag_size, u->nfrags);
/* Optional */
block_msec = DEFAULT_BLOCK_USEC / PA_USEC_PER_MSEC;
pa_sink_new_data_set_channel_map(&data, &map);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Tizen audio sink"));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, "tizen");
+ pa_proplist_sets(data.proplist, "tizen.card", u->card);
+ pa_proplist_sets(data.proplist, "tizen.device", u->device);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen");
if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
u->sink->userdata = u;
if (pa_hal_interface_pcm_open(u->hal_interface,
- (void **)&u->pcm_handle,
+ u->card,
+ u->device,
DIRECTION_OUT,
&u->sink->sample_spec,
u->frag_size / pa_frame_size(&u->sink->sample_spec),
- u->nfrags)) {
+ u->nfrags,
+ (void **)&u->pcm_handle)) {
pa_log_error("Error opening PCM device");
goto fail;
}
if (u->sink)
pa_sink_unref(u->sink);
+ pa_xfree(u->card);
+ pa_xfree(u->device);
+
if (u->rtpoll)
pa_rtpoll_free(u->rtpoll);
PA_MODULE_USAGE(
"source_name=<name of source> "
"source_properties=<properties for the source> "
+ "card=<card to use> "
+ "device=<device to use> "
"format=<sample format> "
"rate=<sample rate> "
"channels=<number of channels> "
pa_usec_t block_usec;
pa_usec_t timestamp;
+ char* card;
+ char* device;
bool first;
pa_rtpoll_item *rtpoll_item;
static const char* const valid_modargs[] = {
"source_name",
"source_properties",
+ "card",
+ "device",
"format",
"rate",
"channels",
u->rtpoll_item = NULL;
}
- pa_log_info("Device suspended...");
+ pa_log_info("Device suspended...[%s,%s]", u->card, u->device);
return 0;
}
}
ret = pa_hal_interface_pcm_open(u->hal_interface,
- (void **)&u->pcm_handle,
+ u->card,
+ u->device,
DIRECTION_IN,
&sample_spec,
u->frag_size / frame_size,
- u->nfrags);
+ u->nfrags,
+ (void **)&u->pcm_handle);
if (ret) {
pa_log_error("Error opening PCM device %x", ret);
goto fail;
pa_modargs *ma = NULL;
pa_source_new_data data;
uint32_t alternate_sample_rate;
+ const char *card, *device;
pa_assert(m);
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
- u->frag_size = 0;
- u->nfrags = 0;
- pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size);
- pa_modargs_get_value_u32(ma, "fragments", &u->nfrags);
- if (u->frag_size == 0 || u->nfrags == 0) {
+ if (!(card = pa_modargs_get_value(ma, "card", NULL)) ||
+ !(device = pa_modargs_get_value(ma, "device", NULL))) {
+ pa_log_error("card or device are invalid");
+ goto fail;
+ }
+
+ u->card = pa_xstrdup(card);
+ u->device = pa_xstrdup(device);
+
+ u->frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
+ u->nfrags = m->core->default_n_fragments;
+ if (pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size) < 0 ||
+ pa_modargs_get_value_u32(ma, "fragments", &u->nfrags) < 0) {
pa_log_error("fragment_size or fragments are invalid.");
goto fail;
}
+ pa_log_info("card(%s) device(%s) fragment_size(%u), fragments(%u)", u->card, u->device, u->frag_size, u->nfrags);
pa_source_new_data_init(&data);
data.driver = __FILE__;
pa_source_new_data_set_channel_map(&data, &map);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Tizen audio source"));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, "tizen");
+ pa_proplist_sets(data.proplist, "tizen.card", u->card);
+ pa_proplist_sets(data.proplist, "tizen.device", u->device);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen");
if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
u->source->userdata = u;
if (pa_hal_interface_pcm_open(u->hal_interface,
- (void **)&u->pcm_handle,
+ u->card,
+ u->device,
DIRECTION_IN,
&u->source->sample_spec,
u->frag_size / pa_frame_size(&u->source->sample_spec),
- u->nfrags)) {
+ u->nfrags,
+ (void **)&u->pcm_handle)) {
pa_log_error("Error opening PCM device");
goto fail;
}
if (u->source)
pa_source_unref(u->source);
+ pa_xfree(u->card);
+ pa_xfree(u->device);
+
if (u->rtpoll)
pa_rtpoll_free(u->rtpoll);