1 From: Jaska Uimonen <jaska.uimonen@intel.com>
2 Date: Thu, 5 Sep 2013 12:21:19 +0300
3 Subject: add parameter to define key used in stream restore.
5 It is possible now to use preferred_stream_group
6 command line parameter when loading module stream
7 restore. This key will be searched from the stream's
8 proplist and if found it is used as key when
9 restoring the volumes and other values. There's also
10 special value media.role.within.appication.name you
11 can use to enable restoring stream roles within
12 application. So different streams with different
13 roles within application will save their volumes.
14 If the preferred stream group parameter is left out
15 module stream restore will fallback to old default
18 Change-Id: I636f47b43476f3d4cd6c14244eafcd050683bb69
19 Signed-off-by: Jaska Uimonen <jaska.uimonen@intel.com>
21 src/modules/module-stream-restore.c | 34 +++++++++++++---------
22 src/pulsecore/proplist-util.c | 58 +++++++++++++++++++++++++++++++++++++
23 src/pulsecore/proplist-util.h | 1 +
24 3 files changed, 80 insertions(+), 13 deletions(-)
26 diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
27 index 9689e79..68968c9 100644
28 --- a/src/modules/module-stream-restore.c
29 +++ b/src/modules/module-stream-restore.c
30 @@ -70,7 +70,8 @@ PA_MODULE_USAGE(
31 "restore_muted=<Save/restore muted states?> "
32 "on_hotplug=<When new device becomes available, recheck streams?> "
33 "on_rescue=<When device becomes unavailable, recheck streams?> "
34 - "fallback_table=<filename>");
35 + "fallback_table=<filename>"
36 + "preferred_stream_group=<prefer certain stream group in restore?> ");
38 #define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
39 #define IDENTIFICATION_PROPERTY "module-stream-restore.id"
40 @@ -87,6 +88,7 @@ static const char* const valid_modargs[] = {
44 + "preferred_stream_group",
48 @@ -112,6 +114,7 @@ struct userdata {
52 + char *preferred_stream_group;
54 pa_native_protocol *protocol;
55 pa_idxset *subscribed;
56 @@ -1277,7 +1280,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
57 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx)))
60 - if (!(name = pa_proplist_get_stream_group(sink_input->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
61 + if (!(name = pa_proplist_get_stream_group_extended(sink_input->proplist, "sink-input", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
64 if ((old = entry_read(u, name))) {
65 @@ -1327,7 +1330,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
66 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx)))
69 - if (!(name = pa_proplist_get_stream_group(source_output->proplist, "source-output", IDENTIFICATION_PROPERTY)))
70 + if (!(name = pa_proplist_get_stream_group_extended(source_output->proplist, "source-output", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
73 if ((old = entry_read(u, name))) {
74 @@ -1420,7 +1423,7 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
76 pa_assert(u->restore_device);
78 - if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
79 + if (!(name = pa_proplist_get_stream_group_extended(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
83 @@ -1462,7 +1465,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
85 pa_assert(u->restore_volume || u->restore_muted);
87 - if (!(name = pa_proplist_get_stream_group(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
88 + if (!(name = pa_proplist_get_stream_group_extended(new_data->proplist, "sink-input", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
91 if ((e = entry_read(u, name))) {
92 @@ -1516,7 +1519,7 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
93 if (new_data->direct_on_input)
96 - if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
97 + if (!(name = pa_proplist_get_stream_group_extended(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
100 if (new_data->source)
101 @@ -1559,7 +1562,7 @@ static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source
103 pa_assert(u->restore_volume || u->restore_muted);
105 - if (!(name = pa_proplist_get_stream_group(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY)))
106 + if (!(name = pa_proplist_get_stream_group_extended(new_data->proplist, "source-output", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
109 if ((e = entry_read(u, name))) {
110 @@ -1631,7 +1634,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct
111 if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
114 - if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
115 + if (!(name = pa_proplist_get_stream_group_extended(si->proplist, "sink-input", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
118 if ((e = entry_read(u, name))) {
119 @@ -1679,7 +1682,7 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
120 if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
123 - if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
124 + if (!(name = pa_proplist_get_stream_group_extended(so->proplist, "source-output", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
127 if ((e = entry_read(u, name))) {
128 @@ -1715,7 +1718,7 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, str
132 - if (!(name = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
133 + if (!(name = pa_proplist_get_stream_group_extended(si->proplist, "sink-input", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
136 if ((e = entry_read(u, name))) {
137 @@ -1761,7 +1764,7 @@ static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *sourc
141 - if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
142 + if (!(name = pa_proplist_get_stream_group_extended(so->proplist, "source-output", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
145 if ((e = entry_read(u, name))) {
146 @@ -1880,7 +1883,7 @@ static void entry_apply(struct userdata *u, const char *name, struct entry *e) {
150 - if (!(n = pa_proplist_get_stream_group(si->proplist, "sink-input", IDENTIFICATION_PROPERTY)))
151 + if (!(n = pa_proplist_get_stream_group_extended(si->proplist, "sink-input", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
154 if (!pa_streq(name, n)) {
155 @@ -1928,7 +1931,7 @@ static void entry_apply(struct userdata *u, const char *name, struct entry *e) {
159 - if (!(n = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
160 + if (!(n = pa_proplist_get_stream_group_extended(so->proplist, "source-output", IDENTIFICATION_PROPERTY, u->preferred_stream_group)))
163 if (!pa_streq(name, n)) {
164 @@ -2411,6 +2414,8 @@ int pa__init(pa_module*m) {
166 u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u);
168 + u->preferred_stream_group = pa_xstrdup(pa_modargs_get_value(ma, "preferred_stream_group", NULL));
170 if (restore_device) {
171 /* A little bit earlier than module-intended-roles ... */
172 u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_new_hook_callback, u);
173 @@ -2554,5 +2559,8 @@ void pa__done(pa_module*m) {
175 pa_idxset_free(u->subscribed, NULL);
177 + if (u->preferred_stream_group)
178 + pa_xfree(u->preferred_stream_group);
182 diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c
183 index 473290f..0a8dbca 100644
184 --- a/src/pulsecore/proplist-util.c
185 +++ b/src/pulsecore/proplist-util.c
186 @@ -274,3 +274,61 @@ char *pa_proplist_get_stream_group(pa_proplist *p, const char *prefix, const cha
191 +char *pa_proplist_get_stream_group_extended(pa_proplist *p, const char *prefix, const char *cache, const char *preferred_stream_group) {
192 + const char *r = NULL;
193 + const char *q = NULL;
199 + if (cache && (r = pa_proplist_gets(p, cache)))
200 + return pa_xstrdup(r);
205 + /* try first to get the preferred stream group, then fallback to hard coded order */
206 + if (preferred_stream_group) {
207 + if (!strcmp(preferred_stream_group, "media.role.within.application.name")) {
208 + if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)) &&
209 + (q = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE))) {
210 + t = pa_sprintf_malloc("%s-by-media-role-within-application-name:%s-%s", prefix, q, r);
212 + /* make r NULL to be able to fallback to "standard" stream restore code */
216 + else if ((r = pa_proplist_gets(p, preferred_stream_group))) {
217 + if (!strcmp(preferred_stream_group, PA_PROP_MEDIA_ROLE))
218 + t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
219 + else if (!strcmp(preferred_stream_group, PA_PROP_APPLICATION_ID))
220 + t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
221 + else if (!strcmp(preferred_stream_group, PA_PROP_APPLICATION_NAME))
222 + t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
223 + else if (!strcmp(preferred_stream_group, PA_PROP_MEDIA_NAME))
224 + t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
226 + t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
231 + if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
232 + t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
233 + else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
234 + t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
235 + else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
236 + t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
237 + else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
238 + t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
240 + t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
244 + pa_proplist_sets(p, cache, t);
248 diff --git a/src/pulsecore/proplist-util.h b/src/pulsecore/proplist-util.h
249 index 3d08776..47bdb57 100644
250 --- a/src/pulsecore/proplist-util.h
251 +++ b/src/pulsecore/proplist-util.h
254 void pa_init_proplist(pa_proplist *p);
255 char *pa_proplist_get_stream_group(pa_proplist *pl, const char *prefix, const char *cache);
256 +char *pa_proplist_get_stream_group_extended(pa_proplist *p, const char *prefix, const char *cache, const char *preferred_stream_group);