PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(true);
+#define SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY "SimplePlay"
+#define SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP "SimpleStop"
+#define SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL "SimpleStopAll"
+
#ifdef HAVE_DBUS
#define ARR_ARG_MAX 32
#define SOUND_PLAYER_OBJECT_PATH "/org/pulseaudio/SoundPlayer"
#define SOUND_PLAYER_INTERFACE "org.pulseaudio.SoundPlayer"
-#define SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY "SimplePlay"
#define SOUND_PLAYER_METHOD_NAME_SAMPLE_PLAY "SamplePlay"
#define SOUND_PLAYER_SIGNAL_EOS "EOS"
static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata);
static DBusHandlerResult handle_methods(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_simple_play(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_simple_stop(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_simple_stop_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
static void handle_sample_play(DBusConnection *conn, DBusMessage *msg, void *userdata);
enum method_handler_index {
METHOD_HANDLER_SIMPLE_PLAY,
+ METHOD_HANDLER_SIMPLE_STOP,
+ METHOD_HANDLER_SIMPLE_STOP_ALL,
METHOD_HANDLER_SAMPLE_PLAY,
METHOD_HANDLER_MAX
};
-static pa_dbus_arg_info simple_play_args[] = { { "uri", "s", "in" },
- { "role", "s", "in" },
- { "volume_gain", "s", "in" } };
-static pa_dbus_arg_info sample_play_args[] = { { "sample_name", "s", "in" },
- { "role", "s", "in" },
- { "volume_gain", "s", "in" } };
-
-static const char* signature_args_for_in[] = { "sss", "sss" };
+static pa_dbus_arg_info simple_play_args[] = { { "uri", "s", "in" },
+ { "role", "s", "in" },
+ { "volume_gain", "s", "in" } };
+static pa_dbus_arg_info simple_stop_args[] = { { "uri", "s", "in" } };
+static pa_dbus_arg_info sample_play_args[] = { { "sample_name", "s", "in" },
+ { "role", "s", "in" },
+ { "volume_gain", "s", "in" } };
+static const char* signature_args_for_in[] = { "sss", "s", NULL, "sss" };
static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
[METHOD_HANDLER_SIMPLE_PLAY] = {
.arguments = simple_play_args,
.n_arguments = sizeof(simple_play_args) / sizeof(pa_dbus_arg_info),
.receive_cb = handle_simple_play },
+ [METHOD_HANDLER_SIMPLE_STOP] = {
+ .method_name = SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP,
+ .arguments = simple_stop_args,
+ .n_arguments = sizeof(simple_stop_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_simple_stop },
+ [METHOD_HANDLER_SIMPLE_STOP_ALL] = {
+ .method_name = SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL,
+ .arguments = NULL,
+ .n_arguments = 0,
+ .receive_cb = handle_simple_stop_all },
[METHOD_HANDLER_SAMPLE_PLAY] = {
.method_name = SOUND_PLAYER_METHOD_NAME_SAMPLE_PLAY,
.arguments = sample_play_args,
" <arg name=\"role\" direction=\"in\" type=\"s\"/>" \
" <arg name=\"volume_gain\" direction=\"in\" type=\"s\"/>" \
" </method>" \
+ " <method name=\"SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP\">" \
+ " <arg name=\"uri\" direction=\"in\" type=\"s\"/>" \
+ " </method>" \
+ " <method name=\"SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL\" />" \
" <method name=\"SOUND_PLAYER_METHOD_NAME_SAMPLE_PLAY\">" \
" <arg name=\"sample_name\" direction=\"in\" type=\"s\"/>" \
" <arg name=\"role\" direction=\"in\" type=\"s\"/>" \
#endif
};
-#define FILE_FULL_PATH 1024 /* File path length */
-#define ROLE_NAME_LEN 64 /* Role name length */
-#define VOLUME_GAIN_TYPE_LEN 64 /* Volume gain type length */
+#define FILE_FULL_PATH 1024
+#define ROLE_NAME_LEN 64
+#define VOLUME_GAIN_TYPE_LEN 32
+#define METHOD_LEN 32
+
#define RETRY_NUM 100
struct ipc_data {
char filename[FILE_FULL_PATH];
char role[ROLE_NAME_LEN];
char volume_gain_type[VOLUME_GAIN_TYPE_LEN];
+ char method[METHOD_LEN];
};
+#define KEYTONE_PREFIX "SIMPLE_PLAY"
#define KEYTONE_PATH "/tmp/keytone" /* Keytone pipe path */
#define KEYTONE_GROUP 6526 /* Keytone group : assigned by security */
#define DEFAULT_IPC_TYPE IPC_TYPE_PIPE
-#define MAX_NAME_LEN 256
static int _simple_play(struct userdata *u, const char *file_path, const char *role, const char *vol_gain_type) {
int ret = 0;
- pa_sink *sink = NULL;
pa_proplist *p;
- const char *name_prefix = "SIMPLE_PLAY";
- char name[MAX_NAME_LEN] = {0};
+ char *scache_name = NULL;
uint32_t stream_idx = 0;
uint32_t scache_idx = 0;
+ /* Set role & volume gain type of stream to proplist */
p = pa_proplist_new();
-
- /* Set role type of stream */
if (role)
pa_proplist_sets(p, PA_PROP_MEDIA_ROLE, role);
-
- /* Set volume gain type of stream */
if (vol_gain_type)
pa_proplist_sets(p, PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE, vol_gain_type);
-
- sink = pa_namereg_get(u->module->core, NULL, PA_NAMEREG_SINK);
-
pa_log_debug("role[%s], volume_gain_type[%s]", role, vol_gain_type);
- snprintf(name, sizeof(name)-1, "%s_%s", name_prefix, file_path);
- scache_idx = pa_scache_get_id_by_name(u->module->core, name);
+
+ /* prepare scache */
+ scache_name = pa_sprintf_malloc("%s_%s", KEYTONE_PREFIX, file_path);
+ scache_idx = pa_scache_get_id_by_name(u->module->core, scache_name);
if (scache_idx != PA_IDXSET_INVALID) {
pa_log_debug("found cached index [%u] for name [%s]", scache_idx, file_path);
} else {
/* for more precision, need to update volume value here */
- if ((ret = pa_scache_add_file_lazy(u->module->core, name, file_path, &scache_idx)) != 0) {
+ if ((ret = pa_scache_add_file_lazy(u->module->core, scache_name, file_path, &scache_idx)) != 0) {
pa_log_error("failed to add file [%s]", file_path);
goto exit;
- } else {
- pa_log_debug("success to add file [%s], index [%u]", file_path, scache_idx);
}
+ pa_log_debug("success to add file [%s], index [%u]", file_path, scache_idx);
}
+ /* play scache */
pa_log_debug("pa_scache_play_item() start");
- ret = pa_scache_play_item(u->module->core, name, sink, PA_VOLUME_NORM, p, &stream_idx);
+ ret = pa_scache_play_item(u->module->core, scache_name,
+ pa_namereg_get(u->module->core, NULL, PA_NAMEREG_SINK),
+ PA_VOLUME_NORM, p, &stream_idx);
if (ret < 0) {
pa_log_error("pa_scache_play_item fail, ret[%d]", ret);
goto exit;
if (!ret)
ret = (int32_t)stream_idx;
exit:
+ pa_xfree(scache_name);
pa_proplist_free(p);
return ret;
}
+static void _simple_stop(struct userdata *u, const char *file_path) {
+ pa_sink_input *si;
+ uint32_t idx;
+ char *name_to_search = NULL;
+
+ pa_assert(u);
+
+ name_to_search = pa_sprintf_malloc("%s_%s", KEYTONE_PREFIX, file_path);
+
+ PA_IDXSET_FOREACH(si, u->module->core->sink_inputs, idx) {
+ if (pa_safe_streq(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME), name_to_search)) {
+ pa_log_info("unlink sink-input : %u", si->index);
+ pa_sink_input_unlink(si);
+ }
+ }
+
+ pa_xfree(name_to_search);
+}
+
+static void _simple_stop_all(struct userdata *u) {
+ pa_sink_input *si;
+ uint32_t idx;
+ const char *media_name = NULL;
+
+ pa_assert(u);
+
+ PA_IDXSET_FOREACH(si, u->module->core->sink_inputs, idx) {
+ media_name = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME);
+
+ if (media_name && pa_strneq(media_name, KEYTONE_PREFIX, strlen(KEYTONE_PREFIX))) {
+ pa_log_info("unlink sink-input : %u", si->index);
+ pa_sink_input_unlink(si);
+ }
+ }
+}
+
static int _sample_play(struct userdata *u, const char *sample_name, const char *role, const char *vol_gain_type) {
int ret = 0;
pa_sink *sink = NULL;
}
static void handle_simple_play(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- char *uri = NULL;
- char *role = NULL;
- char *volume_gain = NULL;
- dbus_int32_t result = 0;
- struct userdata *u = (struct userdata*)userdata;
+ const char *uri = NULL;
+ const char *role = NULL;
+ const char *volume_gain = NULL;
+ dbus_int32_t result = -1;
+ struct userdata *u = (struct userdata *)userdata;
+
pa_assert(conn);
pa_assert(msg);
pa_assert(u);
DBUS_TYPE_STRING, &volume_gain,
DBUS_TYPE_INVALID));
pa_log_info("uri[%s], role[%s], volume_gain[%s]", uri, role, volume_gain);
- if (uri)
+ if (uri) {
result = _simple_play(u, uri, role, volume_gain);
- else
- result = -1;
-
- if (result != -1) {
- uint32_t idx = 0;
- int32_t *stream_idx = NULL;
- stream_idx = pa_xmalloc0(sizeof(int32_t));
- *stream_idx = result;
- pa_idxset_put(u->stream_idxs, stream_idx, &idx);
+ if (result != -1) {
+ int32_t *stream_idx = pa_xmalloc0(sizeof(int32_t));
+ *stream_idx = result;
+ pa_idxset_put(u->stream_idxs, stream_idx, NULL);
+ }
}
+
pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_INT32, &result);
}
+static void handle_simple_stop(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *uri = NULL;
+ struct userdata *u = (struct userdata *)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(u);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &uri,
+ DBUS_TYPE_INVALID));
+ if (uri)
+ _simple_stop(u, uri);
+
+ pa_dbus_send_empty_reply(conn, msg);
+}
+
+static void handle_simple_stop_all(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ struct userdata *u = (struct userdata *)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(u);
+
+ _simple_stop_all(u);
+
+ pa_dbus_send_empty_reply(conn, msg);
+}
+
static void handle_sample_play(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- char *sample_name = NULL;
- char *role = NULL;
- char *volume_gain = NULL;
- dbus_int32_t result = 0;
- struct userdata *u = (struct userdata*)userdata;
+ const char *sample_name = NULL;
+ const char *role = NULL;
+ const char *volume_gain = NULL;
+ dbus_int32_t result = -1;
+ struct userdata *u = (struct userdata *)userdata;
pa_assert(conn);
pa_assert(msg);
pa_assert(u);
pa_log_info("sample_name[%s], role[%s], volume_gain[%s]", sample_name, role, volume_gain);
if (sample_name)
result = _sample_play(u, sample_name, role, volume_gain);
- else
- result = -1;
if (result != -1) {
- uint32_t idx = 0;
- int32_t *stream_idx = NULL;
- stream_idx = pa_xmalloc0(sizeof(int32_t));
+ int32_t *stream_idx = pa_xmalloc0(sizeof(int32_t));
*stream_idx = result;
- pa_idxset_put(u->stream_idxs, stream_idx, &idx);
+ pa_idxset_put(u->stream_idxs, stream_idx, NULL);
}
pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_INT32, &result);
read_sum += ret;
}
if (read_sum == data_size) {
- pa_log_info("name(%s), role(%s), volume_gain_type(%s)", data.filename, data.role, data.volume_gain_type);
- _simple_play(u, data.filename, data.role, data.volume_gain_type);
+ pa_log_info("name(%s), role(%s), volume_gain_type(%s), method(%s)",
+ data.filename, data.role, data.volume_gain_type, data.method);
+
+ if (pa_streq(data.method, SOUND_PLAYER_METHOD_NAME_SIMPLE_PLAY))
+ _simple_play(u, data.filename, data.role, data.volume_gain_type);
+ else if (pa_streq(data.method, SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP))
+ _simple_stop(u, data.filename);
+ else if (pa_streq(data.method, SOUND_PLAYER_METHOD_NAME_SIMPLE_STOP_ALL))
+ _simple_stop_all(u);
+ else
+ pa_log_error("Invalid method!!!");
} else {
pa_log_warn("Fail to read, retry_count(%d), read sum(%d), err(%s)", retry_count, read_sum, pa_cstrerror(errno));
}