From 545814bac2c83a55a310f416f7218370bbe6183f Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Wed, 15 Jul 2015 14:53:16 +0900 Subject: [PATCH] sound-player: Support EOS signal Send the end of stream dbus signal when the stream played by dbus method(SimplePlay/SamplePlay) is finished [Version] 0.5-22 [Profile] Common [Issue Type] feature enhancement Change-Id: I42cf7dd2630b90b14edf5ee02d5041851e954678 --- packaging/pulseaudio.spec | 2 +- src/modules/module-sound-player.c | 107 ++++++++++++++++++++++++++++++-------- 2 files changed, 86 insertions(+), 23 deletions(-) diff --git a/packaging/pulseaudio.spec b/packaging/pulseaudio.spec index daf92f1..7f256bb 100644 --- a/packaging/pulseaudio.spec +++ b/packaging/pulseaudio.spec @@ -11,7 +11,7 @@ Name: pulseaudio Summary: Improved Linux sound server Version: 5.0 -Release: 21 +Release: 22 Group: Multimedia/Audio License: GPL-2.0+ and LGPL-2.1+ URL: http://pulseaudio.org diff --git a/src/modules/module-sound-player.c b/src/modules/module-sound-player.c index 8f6f39d..8e77eb4 100644 --- a/src/modules/module-sound-player.c +++ b/src/modules/module-sound-player.c @@ -63,6 +63,7 @@ PA_MODULE_LOAD_ONCE(TRUE); #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 method_handler_for_vt(DBusConnection *c, DBusMessage *m, void *userdata); static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata); @@ -144,12 +145,14 @@ struct userdata { int fd; pa_io_event *io; pa_module *module; + pa_hook_slot *sink_input_unlink_slot; #ifdef HAVE_DBUS #ifdef USE_DBUS_PROTOCOL pa_dbus_protocol *dbus_protocol; #else pa_dbus_connection *dbus_conn; #endif + pa_idxset *stream_idxs; #endif }; @@ -177,7 +180,7 @@ static int _simple_play(struct userdata *u, const char *file_path, const char *r char name[MAX_NAME_LEN] = {0}; uint32_t stream_idx = 0; - uint32_t play_idx = 0; + uint32_t scache_idx = 0; p = pa_proplist_new(); @@ -189,24 +192,20 @@ static int _simple_play(struct userdata *u, const char *file_path, const char *r if (vol_gain_type) pa_proplist_sets(p, PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE, vol_gain_type); - /* Set policy type of stream */ - pa_proplist_sets(p, PA_PROP_MEDIA_POLICY, "auto"); - /* Set policy for selecting sink */ - pa_proplist_sets(p, PA_PROP_MEDIA_POLICY_IGNORE_PRESET_SINK, "yes"); sink = pa_namereg_get_default_sink(u->module->core); pa_log_debug("role[%s], volume_gain_type[%s]", role, vol_gain_type); snprintf(name, sizeof(name)-1, "%s_%s", name_prefix, file_path); - play_idx = pa_scache_get_id_by_name(u->module->core, name); - if (play_idx != PA_IDXSET_INVALID) { - pa_log_debug("found cached index [%u] for name [%s]", play_idx, file_path); + scache_idx = pa_scache_get_id_by_name(u->module->core, 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, &play_idx)) != 0) { + if ((ret = pa_scache_add_file_lazy(u->module->core, 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, play_idx); + pa_log_debug("success to add file [%s], index [%u]", file_path, scache_idx); } } @@ -215,8 +214,10 @@ static int _simple_play(struct userdata *u, const char *file_path, const char *r pa_log_error("pa_scache_play_item fail"); goto exit; } - pa_log_debug("pa_scache_play_item() end"); + pa_log_debug("pa_scache_play_item() end, stream_idx(%u)", stream_idx); + if (!ret) + ret = (int32_t)stream_idx; exit: pa_proplist_free(p); return ret; @@ -228,7 +229,7 @@ static int _sample_play(struct userdata *u, const char *sample_name, const char pa_proplist *p; uint32_t stream_idx = 0; - uint32_t play_idx = 0; + uint32_t scache_idx = 0; p = pa_proplist_new(); @@ -240,26 +241,24 @@ static int _sample_play(struct userdata *u, const char *sample_name, const char if (vol_gain_type) pa_proplist_sets(p, PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE, vol_gain_type); - /* Set policy type of stream */ - pa_proplist_sets(p, PA_PROP_MEDIA_POLICY, "auto"); - /* Set policy for selecting sink */ - pa_proplist_sets(p, PA_PROP_MEDIA_POLICY_IGNORE_PRESET_SINK, "yes"); sink = pa_namereg_get_default_sink(u->module->core); pa_log_debug("role[%s], volume_gain_type[%s]", role, vol_gain_type); - play_idx = pa_scache_get_id_by_name(u->module->core, sample_name); - if (play_idx != PA_IDXSET_INVALID) { - pa_log_debug("pa_scache_play_item() start, index [%u] for name [%s]", play_idx, sample_name); + scache_idx = pa_scache_get_id_by_name(u->module->core, sample_name); + if (scache_idx != PA_IDXSET_INVALID) { + pa_log_debug("pa_scache_play_item() start, scache idx[%u] for name[%s]", scache_idx, sample_name); /* for more precision, need to update volume value here */ if ((ret = pa_scache_play_item(u->module->core, sample_name, sink, PA_VOLUME_NORM, p, &stream_idx) < 0)) { pa_log_error("pa_scache_play_item fail"); goto exit; } - pa_log_debug("pa_scache_play_item() end"); + pa_log_debug("pa_scache_play_item() end, stream_idx(%u)", stream_idx); } else pa_log_error("could not find the scache item for [%s]", sample_name); + if (!ret) + ret = (int32_t)stream_idx; exit: pa_proplist_free(p); return ret; @@ -302,10 +301,18 @@ static void handle_simple_play(DBusConnection *conn, DBusMessage *msg, void *use DBUS_TYPE_INVALID)); pa_log_info("uri[%s], role[%s], volume_gain[%s]", uri, role, volume_gain); if (uri) - _simple_play(u, uri, role, volume_gain); + 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); + } + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_INT32, &result); } @@ -326,10 +333,18 @@ static void handle_sample_play(DBusConnection *conn, DBusMessage *msg, void *use DBUS_TYPE_INVALID)); pa_log_info("sample_name[%s], role[%s], volume_gain[%s]", sample_name, role, volume_gain); if (sample_name) - _sample_play(u, sample_name, role, volume_gain); + 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)); + *stream_idx = result; + pa_idxset_put(u->stream_idxs, stream_idx, &idx); + } + pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_INT32, &result); } @@ -381,6 +396,19 @@ static DBusHandlerResult method_handler_for_vt(DBusConnection *c, DBusMessage *m return DBUS_HANDLER_RESULT_HANDLED; } + +static void send_signal_for_eos(struct userdata *u, int32_t stream_idx) { + DBusMessage *signal_msg = NULL; + + pa_assert(u); + + pa_log_debug("Send EOS signal for stream_idx(%d)", stream_idx); + + pa_assert_se(signal_msg = dbus_message_new_signal(SOUND_PLAYER_OBJECT_PATH, SOUND_PLAYER_INTERFACE, SOUND_PLAYER_SIGNAL_EOS)); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_INT32, &stream_idx, DBUS_TYPE_INVALID)); + pa_assert_se(dbus_connection_send(pa_dbus_connection_get(u->dbus_conn), signal_msg, NULL)); + dbus_message_unref(signal_msg); +} #endif static int init_ipc (struct userdata *u) { @@ -514,6 +542,30 @@ fail: pa_module_unload_request(u->module, TRUE); } +static pa_hook_result_t sink_input_unlink_cb(pa_core *core, pa_sink_input *i, struct userdata *u) { + int32_t *stream_idx = NULL; + uint32_t *idx = NULL; + pa_core_assert_ref(core); + pa_sink_input_assert_ref(i); + + pa_log_info("start sink_input_unlink_cb, i(%p, index:%u)", i, i->index); + +#ifdef HAVE_DBUS + PA_IDXSET_FOREACH(stream_idx, u->stream_idxs, idx) { + if (*stream_idx == (int32_t)(i->index)) { +#ifndef USE_DBUS_PROTOCOL + /* Send EOS signal for this stream */ + send_signal_for_eos(u, *stream_idx); +#endif + pa_idxset_remove_by_data(u->stream_idxs, stream_idx, NULL); + pa_xfree(stream_idx); + } + } +#endif + + return PA_HOOK_OK; +} + int pa__init(pa_module *m) { struct userdata *u; @@ -529,10 +581,13 @@ int pa__init(pa_module *m) { #else u->dbus_conn = NULL; #endif + u->stream_idxs = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); #endif if (init_ipc(u)) goto fail; + u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_unlink_cb, u); + return 0; fail: @@ -547,6 +602,14 @@ void pa__done(pa_module *m) { if (!(u = m->userdata)) return; + if (u->sink_input_unlink_slot) + pa_hook_slot_free(u->sink_input_unlink_slot); + +#ifdef HAVE_DBUS + if (u->stream_idxs) + pa_idxset_free(u->stream_idxs, NULL); +#endif + deinit_ipc(u); pa_xfree(u); -- 2.7.4