tunnel-sink(source)-new: modification for remote-audio 87/241187/10
authorSeungbae Shin <seungbae.shin@samsung.com>
Tue, 18 Aug 2020 09:56:15 +0000 (18:56 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Thu, 20 Aug 2020 07:04:09 +0000 (07:04 +0000)
- receive stream event to update access permission of the sink(source)
- set remote name from target device name vconf
- set default remote access permission as denied
- set device api property with 'tunnel'

[Version] 13.0-15
[Issue Type] Update

Change-Id: Iae64a8805b6befa088b0c5ffce678894114a8bba

configure.ac
packaging/pulseaudio.spec
src/Makefile.am
src/modules/module-tunnel-sink-new.c
src/modules/module-tunnel-source-new.c
src/pulse/def.h
src/pulsecore/proplist-util.c
src/pulsecore/proplist-util.h

index 796e994..e8d81de 100644 (file)
@@ -1053,6 +1053,12 @@ AC_SUBST(LIRC_CFLAGS)
 AC_SUBST(LIRC_LIBS)
 AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
 
+
+#### VCONF
+PKG_CHECK_MODULES(VCONF, vconf)
+AC_SUBST(VCONF_CFLAGS)
+AC_SUBST(VCONF_LIBS)
+
 #### D-Bus support (optional) ####
 
 AC_ARG_ENABLE([dbus],
index d3c15c0..e5275b0 100644 (file)
@@ -3,7 +3,7 @@
 Name:             pulseaudio
 Summary:          Improved Linux sound server
 Version:          13.0
-Release:          14
+Release:          15
 Group:            Multimedia/Audio
 License:          LGPL-2.1
 URL:              http://pulseaudio.org
@@ -28,6 +28,7 @@ BuildRequires:    pkgconfig(dlog)
 BuildRequires:    pkgconfig(cynara-client)
 BuildRequires:    pkgconfig(cynara-creds-socket)
 BuildRequires:    pkgconfig(cynara-session)
+BuildRequires:    pkgconfig(vconf)
 BuildRequires:    systemd-devel
 BuildRequires:    libcap-devel
 %if "%{tizen_profile_name}" == "tv"
index 89aeab5..e4eb0c8 100644 (file)
@@ -1942,13 +1942,13 @@ module_match_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_match
 
 module_tunnel_sink_new_la_SOURCES = modules/module-tunnel-sink-new.c
 module_tunnel_sink_new_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_tunnel_sink_new_la_LIBADD = $(MODULE_LIBADD)
-module_tunnel_sink_new_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_tunnel_sink_new
+module_tunnel_sink_new_la_LIBADD = $(MODULE_LIBADD) $(VCONF_LIBS)
+module_tunnel_sink_new_la_CFLAGS = $(AM_CFLAGS) $(VCONF_CFLAGS) -DPA_MODULE_NAME=module_tunnel_sink_new
 
 module_tunnel_source_new_la_SOURCES = modules/module-tunnel-source-new.c
 module_tunnel_source_new_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_tunnel_source_new_la_LIBADD = $(MODULE_LIBADD)
-module_tunnel_source_new_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_tunnel_source_new
+module_tunnel_source_new_la_LIBADD = $(MODULE_LIBADD) $(VCONF_LIBS)
+module_tunnel_source_new_la_CFLAGS = $(AM_CFLAGS) $(VCONF_CFLAGS) -DPA_MODULE_NAME=module_tunnel_source_new
 
 module_tunnel_sink_la_SOURCES = modules/module-tunnel.c
 module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS) $(X11_CFLAGS) -DPA_MODULE_NAME=module_tunnel_sink
index 802e6a5..dfd333f 100644 (file)
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/poll.h>
 #include <pulsecore/rtpoll.h>
+
+#ifdef __TIZEN__
 #include <pulsecore/proplist-util.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+#endif
 
 PA_MODULE_AUTHOR("Alexander Couzens");
 PA_MODULE_DESCRIPTION("Create a network sink which connects via a stream to a remote PulseAudio server");
@@ -60,11 +65,20 @@ PA_MODULE_USAGE(
 #define MAX_LATENCY_USEC (200 * PA_USEC_PER_MSEC)
 #define TUNNEL_THREAD_FAILED_MAINLOOP 1
 
+#ifdef __TIZEN__
+enum {
+    SINK_MESSAGE_STREAM_PROPLIST_UPDATED = PA_SINK_MESSAGE_MAX
+};
+#endif
+
 static void stream_state_cb(pa_stream *stream, void *userdata);
 static void stream_changed_buffer_attr_cb(pa_stream *stream, void *userdata);
 static void stream_set_buffer_attr_cb(pa_stream *stream, int success, void *userdata);
 static void context_state_cb(pa_context *c, void *userdata);
 static void sink_update_requested_latency_cb(pa_sink *s);
+#ifdef __TIZEN__
+static void stream_event_cb(pa_stream *stream, const char *name, pa_proplist *pl, void *userdata);
+#endif
 
 struct userdata {
     pa_module *module;
@@ -85,6 +99,9 @@ struct userdata {
     char *cookie_file;
     char *remote_server;
     char *remote_sink_name;
+#ifdef __TIZEN__
+    char *device_name;
+#endif
 };
 
 static const char* const valid_modargs[] = {
@@ -135,6 +152,9 @@ static pa_proplist* tunnel_new_proplist(struct userdata *u) {
     pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "PulseAudio");
     pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "org.PulseAudio.PulseAudio");
     pa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
+#ifdef __TIZEN__
+    pa_proplist_remote_init(proplist, u->device_name);
+#endif
     pa_init_proplist(proplist);
 
     return proplist;
@@ -287,6 +307,28 @@ static void stream_set_buffer_attr_cb(pa_stream *stream, int success, void *user
     stream_changed_buffer_attr_cb(stream, userdata);
 }
 
+#ifdef __TIZEN__
+static void stream_event_cb(pa_stream *stream, const char *name, pa_proplist *pl, void *userdata) {
+    char *t;
+    struct userdata *u = userdata;
+
+    pa_assert(stream);
+    pa_assert(name);
+    pa_assert(pl);
+
+    t = pa_proplist_to_string_sep(pl, ", ");
+    pa_log_info("Got event '%s', properties '%s'", name, t);
+
+    if (pa_safe_streq(name, PA_STREAM_EVENT_UPDATE_MEDIA_REMOTE_ACCESS)) {
+        pa_log_info("post message to update sink[%s] proplist[%s]", u->sink->name, t);
+        pa_asyncmsgq_post(u->thread_mq->outq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_STREAM_PROPLIST_UPDATED,
+                          pa_proplist_copy(pl), 0, NULL, NULL);
+    }
+
+    pa_xfree(t);
+}
+#endif
+
 static void context_state_cb(pa_context *c, void *userdata) {
     struct userdata *u = userdata;
     pa_assert(u);
@@ -335,6 +377,10 @@ static void context_state_cb(pa_context *c, void *userdata) {
 
             pa_stream_set_state_callback(u->stream, stream_state_cb, userdata);
             pa_stream_set_buffer_attr_callback(u->stream, stream_changed_buffer_attr_cb, userdata);
+#ifdef __TIZEN__
+            pa_stream_set_event_callback(u->stream, stream_event_cb, userdata);
+#endif
+
             if (pa_stream_connect_playback(u->stream,
                                            u->remote_sink_name,
                                            &bufferattr,
@@ -429,6 +475,28 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
             *((int64_t*) data) = remote_latency;
             return 0;
         }
+#ifdef __TIZEN__
+        case SINK_MESSAGE_STREAM_PROPLIST_UPDATED: {
+            pa_proplist *pl = (pa_proplist *)data;
+            void *s;
+            uint32_t idx;
+
+            pa_log_info("SINK_MESSAGE_STREAM_PROPLIST_UPDATED : %p", pl);
+
+            pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl);
+
+            if (!pa_proplist_remote_is_allowed(pl)) {
+                PA_IDXSET_FOREACH(s, u->sink->inputs, idx) {
+                    pa_log_info("  -- kill sink-input(%p, %u)", s, ((pa_sink_input *) s)->index);
+                    pa_sink_input_kill((pa_sink_input *) s);
+                }
+            }
+
+            pa_proplist_free(pl);
+
+            return 0;
+        }
+#endif
     }
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
@@ -509,6 +577,9 @@ int pa__init(pa_module *m) {
     u->thread_mainloop_api = pa_mainloop_get_api(u->thread_mainloop);
     u->cookie_file = pa_xstrdup(pa_modargs_get_value(ma, "cookie", NULL));
     u->remote_sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
+#ifdef __TIZEN__
+    u->device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
+#endif
 
     u->thread_mq = pa_xnew0(pa_thread_mq, 1);
 
@@ -544,6 +615,10 @@ int pa__init(pa_module *m) {
                      _("Tunnel to %s/%s"),
                      remote_server,
                      pa_strempty(u->remote_sink_name));
+#ifdef __TIZEN__
+    pa_proplist_remote_init(sink_data.proplist, u->device_name);
+    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_API, "tunnel");
+#endif
 
     if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
         pa_log("Invalid properties");
@@ -623,6 +698,11 @@ void pa__done(pa_module *m) {
     if (u->remote_server)
         pa_xfree(u->remote_server);
 
+#ifdef __TIZEN__
+    if (u->device_name)
+        pa_xfree(u->device_name);
+#endif
+
     if (u->sink)
         pa_sink_unref(u->sink);
 
index b41f53e..c25684b 100644 (file)
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/poll.h>
 #include <pulsecore/rtpoll.h>
+
+#ifdef __TIZEN__
 #include <pulsecore/proplist-util.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+#endif
 
 PA_MODULE_AUTHOR("Alexander Couzens");
 PA_MODULE_DESCRIPTION("Create a network source which connects via a stream to a remote PulseAudio server");
@@ -59,10 +64,19 @@ PA_MODULE_USAGE(
 
 #define TUNNEL_THREAD_FAILED_MAINLOOP 1
 
+#ifdef __TIZEN__
+enum {
+    SOURCE_MESSAGE_STREAM_PROPLIST_UPDATED = PA_SOURCE_MESSAGE_MAX
+};
+#endif
+
 static void stream_state_cb(pa_stream *stream, void *userdata);
 static void stream_read_cb(pa_stream *s, size_t length, void *userdata);
 static void context_state_cb(pa_context *c, void *userdata);
 static void source_update_requested_latency_cb(pa_source *s);
+#ifdef __TIZEN__
+static void stream_event_cb(pa_stream *s, const char *name, pa_proplist *pl, void *userdata);
+#endif
 
 struct userdata {
     pa_module *module;
@@ -83,6 +97,9 @@ struct userdata {
     char *cookie_file;
     char *remote_server;
     char *remote_source_name;
+#ifdef __TIZEN__
+    char *device_name;
+#endif
 };
 
 static const char* const valid_modargs[] = {
@@ -124,6 +141,9 @@ static pa_proplist* tunnel_new_proplist(struct userdata *u) {
     pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "PulseAudio");
     pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "org.PulseAudio.PulseAudio");
     pa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
+#ifdef __TIZEN__
+    pa_proplist_remote_init(proplist, u->device_name);
+#endif
     pa_init_proplist(proplist);
 
     return proplist;
@@ -134,6 +154,28 @@ static void stream_read_cb(pa_stream *s, size_t length, void *userdata) {
     u->new_data = true;
 }
 
+#ifdef __TIZEN__
+static void stream_event_cb(pa_stream *s, const char *name, pa_proplist *pl, void *userdata) {
+    char *t;
+    struct userdata *u = userdata;
+
+    pa_assert(s);
+    pa_assert(name);
+    pa_assert(pl);
+
+    t = pa_proplist_to_string_sep(pl, ", ");
+    pa_log("Got event '%s', properties '%s'", name, t);
+
+    if (pa_safe_streq(name, PA_STREAM_EVENT_UPDATE_MEDIA_REMOTE_ACCESS)) {
+        pa_log("post message to update source[%s] proplist[%s]", u->source->name, t);
+        pa_asyncmsgq_post(u->thread_mq->outq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_STREAM_PROPLIST_UPDATED,
+                          pa_proplist_copy(pl), 0, NULL, NULL);
+    }
+
+    pa_xfree(t);
+}
+#endif
+
 /* called from io context to read samples from the stream into our source */
 static void read_new_samples(struct userdata *u) {
     const void *p;
@@ -333,6 +375,10 @@ static void context_state_cb(pa_context *c, void *userdata) {
 
             pa_stream_set_state_callback(u->stream, stream_state_cb, userdata);
             pa_stream_set_read_callback(u->stream, stream_read_cb, userdata);
+#ifdef __TIZEN__
+            pa_stream_set_event_callback(u->stream, stream_event_cb, userdata);
+#endif
+
             if (pa_stream_connect_record(u->stream,
                                          u->remote_source_name,
                                          &bufferattr,
@@ -428,6 +474,29 @@ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t
 
             return 0;
         }
+
+#ifdef __TIZEN__
+        case SOURCE_MESSAGE_STREAM_PROPLIST_UPDATED: {
+            pa_proplist *pl = (pa_proplist *)data;
+            void *s;
+            uint32_t idx;
+
+            pa_log_info("SOURCE_MESSAGE_STREAM_PROPLIST_UPDATED : %p", pl);
+
+            pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl);
+
+            if (!pa_proplist_remote_is_allowed(pl)) {
+                PA_IDXSET_FOREACH(s, u->source->outputs, idx) {
+                    pa_log_info("  -- kill source-output(%p, %u)", s, ((pa_source_output *) s)->index);
+                    pa_source_output_kill((pa_source_output *) s);
+                }
+            }
+
+            pa_proplist_free(pl);
+
+            return 0;
+        }
+#endif
     }
     return pa_source_process_msg(o, code, data, offset, chunk);
 }
@@ -508,6 +577,9 @@ int pa__init(pa_module *m) {
     u->thread_mainloop_api = pa_mainloop_get_api(u->thread_mainloop);
     u->cookie_file = pa_xstrdup(pa_modargs_get_value(ma, "cookie", NULL));
     u->remote_source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));
+#ifdef __TIZEN__
+    u->device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
+#endif
 
     u->thread_mq = pa_xnew0(pa_thread_mq, 1);
 
@@ -540,6 +612,10 @@ int pa__init(pa_module *m) {
                      _("Tunnel to %s/%s"),
                      remote_server,
                      pa_strempty(u->remote_source_name));
+#ifdef __TIZEN__
+    pa_proplist_remote_init(source_data.proplist, u->device_name);
+    pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_API, "tunnel");
+#endif
 
     if (pa_modargs_get_proplist(ma, "source_properties", source_data.proplist, PA_UPDATE_REPLACE) < 0) {
         pa_log("Invalid properties");
@@ -617,6 +693,11 @@ void pa__done(pa_module *m) {
     if (u->remote_server)
         pa_xfree(u->remote_server);
 
+#ifdef __TIZEN__
+    if (u->device_name)
+        pa_xfree(u->device_name);
+#endif
+
     if (u->source)
         pa_source_unref(u->source);
 
index a06db2f..83e7a58 100644 (file)
@@ -1055,6 +1055,7 @@ typedef void (*pa_free_cb_t)(void *p);
 
 #ifdef __TIZEN__
 #define PA_STREAM_EVENT_POP_TIMEOUT "pop-timeout"
+#define PA_STREAM_EVENT_UPDATE_MEDIA_REMOTE_ACCESS "update-media-remote-access"
 #endif
 
 #ifndef __INCLUDED_FROM_PULSE_AUDIO
index 84a6c4b..20ebd32 100644 (file)
@@ -281,6 +281,14 @@ char *pa_proplist_get_stream_group(pa_proplist *p, const char *prefix, const cha
 
 static const char *access_str[] = { REMOTE_ACCESS_PERMISSION_DENIED, REMOTE_ACCESS_PERMISSION_ALLOWED };
 
+void pa_proplist_remote_init(pa_proplist *p, const char *remote_name) {
+    if (!p)
+        return;
+
+    pa_proplist_sets(p, PA_PROP_MEDIA_REMOTE_NAME, pa_strnull(remote_name));
+    pa_proplist_sets(p, PA_PROP_MEDIA_REMOTE_ACCESS, REMOTE_ACCESS_PERMISSION_DENIED);
+}
+
 bool pa_proplist_has_remote_name(pa_proplist *p) {
     bool is_remote = false;
 
index 3253f05..9d9ae4d 100644 (file)
@@ -29,6 +29,7 @@ void pa_init_proplist(pa_proplist *p);
 char *pa_proplist_get_stream_group(pa_proplist *pl, const char *prefix, const char *cache);
 
 #ifdef __TIZEN__
+void pa_proplist_remote_init(pa_proplist *p, const char *remote_name);
 bool pa_proplist_has_remote_name(pa_proplist *p);
 int pa_proplist_set_remote_access_permission(pa_proplist *p, bool allowed);
 bool pa_proplist_remote_is_allowed(pa_proplist *p);