2 This file is part of PulseAudio.
4 Copyright 2008 Lennart Poettering
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
34 #include <crt_externs.h>
35 #define environ (*_NSGetEnviron())
36 #elif !HAVE_DECL_ENVIRON
37 extern char **environ;
40 #include <pulse/gccmacro.h>
41 #include <pulse/proplist.h>
42 #include <pulse/utf8.h>
43 #include <pulse/xmalloc.h>
44 #include <pulse/util.h>
46 #include <pulsecore/core-util.h>
48 #if defined(HAVE_GLIB) && defined(PA_GCC_WEAKREF)
50 static G_CONST_RETURN gchar* _g_get_application_name(void) PA_GCC_WEAKREF(g_get_application_name);
53 #if defined(HAVE_GTK) && defined(PA_GCC_WEAKREF)
54 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
57 static G_CONST_RETURN gchar* _gtk_window_get_default_icon_name(void) PA_GCC_WEAKREF(gtk_window_get_default_icon_name);
58 static Display *_gdk_display PA_GCC_WEAKREF(gdk_display);
61 #include "proplist-util.h"
63 static void add_glib_properties(pa_proplist *p) {
65 #if defined(HAVE_GLIB) && defined(PA_GCC_WEAKREF)
67 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))
68 if (_g_get_application_name) {
71 /* We ignore the tiny race condition here. */
73 if ((t = _g_get_application_name()))
74 pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t);
80 static void add_gtk_properties(pa_proplist *p) {
82 #if defined(HAVE_GTK) && defined(PA_GCC_WEAKREF)
84 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_ICON_NAME))
85 if (_gtk_window_get_default_icon_name) {
88 /* We ignore the tiny race condition here. */
90 if ((t = _gtk_window_get_default_icon_name()))
91 pa_proplist_sets(p, PA_PROP_APPLICATION_ICON_NAME, t);
94 if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY))
95 if (&_gdk_display && _gdk_display) {
98 /* We ignore the tiny race condition here. */
100 if ((t = DisplayString(_gdk_display)))
101 pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, t);
107 void pa_init_proplist(pa_proplist *p) {
115 /* Some applications seem to reset environ to NULL for various
116 * reasons, hence we need to check for this explicitly. See
119 for (e = environ; *e; e++) {
121 if (pa_startswith(*e, "PULSE_PROP_")) {
126 if (pa_startswith(*e, "PULSE_PROP_OVERRIDE_")) {
134 kl = strcspn(*e+skip, "=");
136 if ((*e)[skip+kl] != '=')
139 k = pa_xstrndup(*e+skip, kl);
141 if (!pa_streq(k, "OVERRIDE"))
142 if (override || !pa_proplist_contains(p, k))
143 pa_proplist_sets(p, k, *e+skip+kl+1);
149 if ((pp = getenv("PULSE_PROP"))) {
152 if ((t = pa_proplist_from_string(pp))) {
153 pa_proplist_update(p, PA_UPDATE_MERGE, t);
158 if ((pp = getenv("PULSE_PROP_OVERRIDE"))) {
161 if ((t = pa_proplist_from_string(pp))) {
162 pa_proplist_update(p, PA_UPDATE_REPLACE, t);
167 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
169 pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());
170 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t);
173 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) {
176 if ((u = pa_get_user_name_malloc())) {
177 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, u);
182 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) {
185 if ((h = pa_get_host_name_malloc())) {
186 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, h);
191 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY)) {
194 if ((t = pa_get_binary_name_malloc())) {
195 char *c = pa_utf8_filter(t);
196 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
202 add_glib_properties(p);
203 add_gtk_properties(p);
205 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) {
208 if ((t = pa_proplist_gets(p, PA_PROP_APPLICATION_PROCESS_BINARY)))
209 pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t);
212 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
215 if ((l = setlocale(LC_MESSAGES, NULL)))
216 pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
219 if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY)) {
222 if ((t = getenv("DISPLAY"))) {
223 char *c = pa_utf8_filter(t);
224 pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, c);
229 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID)) {
232 if ((m = pa_machine_id())) {
233 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID, m);
238 if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_SESSION_ID)) {
241 if ((s = pa_session_id())) {
242 pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_SESSION_ID, s);
248 char *pa_proplist_get_stream_group(pa_proplist *p, const char *prefix, const char *cache) {
255 if (cache && (r = pa_proplist_gets(p, cache)))
256 return pa_xstrdup(r);
261 if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
262 t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
263 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
264 t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
265 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
266 t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
267 else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
268 t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
270 t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
273 pa_proplist_sets(p, cache, t);
278 char *pa_proplist_get_stream_group_extended(pa_proplist *p, const char *prefix, const char *cache, const char *preferred_stream_group) {
279 const char *r = NULL;
280 const char *q = NULL;
286 if (cache && (r = pa_proplist_gets(p, cache)))
287 return pa_xstrdup(r);
292 /* try first to get the preferred stream group, then fallback to hard coded order */
293 if (preferred_stream_group) {
294 if (!strcmp(preferred_stream_group, "media.role.within.application.name")) {
295 if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)) &&
296 (q = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE))) {
297 t = pa_sprintf_malloc("%s-by-media-role-within-application-name:%s-%s", prefix, q, r);
299 /* make r NULL to be able to fallback to "standard" stream restore code */
302 } else if ((r = pa_proplist_gets(p, preferred_stream_group))) {
303 if (!strcmp(preferred_stream_group, PA_PROP_MEDIA_ROLE))
304 t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
305 else if (!strcmp(preferred_stream_group, PA_PROP_APPLICATION_ID))
306 t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
307 else if (!strcmp(preferred_stream_group, PA_PROP_APPLICATION_NAME))
308 t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
309 else if (!strcmp(preferred_stream_group, PA_PROP_MEDIA_NAME))
310 t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
312 t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
317 if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
318 t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
319 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
320 t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
321 else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
322 t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
323 else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
324 t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
326 t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
330 pa_proplist_sets(p, cache, t);