• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2008 Lennart Poettering
5 
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.
10 
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.
15 
16   You should have received a copy of the GNU Lesser General Public
17   License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include <string.h>
25 #include <locale.h>
26 
27 #ifdef ENABLE_NLS
28 #include <libintl.h>
29 #endif
30 
31 #ifdef __APPLE__
32 #include <crt_externs.h>
33 #define environ (*_NSGetEnviron())
34 #elif !HAVE_DECL_ENVIRON
35 extern char **environ;
36 #endif
37 
38 #include <pulse/gccmacro.h>
39 #include <pulse/proplist.h>
40 #include <pulse/utf8.h>
41 #include <pulse/xmalloc.h>
42 #include <pulse/util.h>
43 
44 #include <pulsecore/core-util.h>
45 
46 #if defined(HAVE_GLIB) && defined(PA_GCC_WEAKREF)
47 #include <glib.h>
48 static const gchar* _g_get_application_name(void) PA_GCC_WEAKREF(g_get_application_name);
49 #endif
50 
51 #if defined(HAVE_GTK) && defined(PA_GCC_WEAKREF)
52 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
53 #include <gtk/gtk.h>
54 static const gchar* _gtk_window_get_default_icon_name(void) PA_GCC_WEAKREF(gtk_window_get_default_icon_name);
55 #ifdef GDK_WINDOWING_X11
56 #include <gdk/gdkx.h>
57 static Display *_gdk_display PA_GCC_WEAKREF(gdk_display);
58 #endif
59 #endif
60 
61 #include "proplist-util.h"
62 
add_glib_properties(pa_proplist * p)63 static void add_glib_properties(pa_proplist *p) {
64 
65 #if defined(HAVE_GLIB) && defined(PA_GCC_WEAKREF)
66 
67     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))
68         if (_g_get_application_name) {
69             const gchar *t;
70 
71             /* We ignore the tiny race condition here. */
72 
73             if ((t = _g_get_application_name()))
74                 pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t);
75         }
76 
77 #endif
78 }
79 
add_gtk_properties(pa_proplist * p)80 static void add_gtk_properties(pa_proplist *p) {
81 
82 #if defined(HAVE_GTK) && defined(PA_GCC_WEAKREF)
83 
84     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_ICON_NAME))
85         if (_gtk_window_get_default_icon_name) {
86             const gchar *t;
87 
88             /* We ignore the tiny race condition here. */
89 
90             if ((t = _gtk_window_get_default_icon_name()))
91                 pa_proplist_sets(p, PA_PROP_APPLICATION_ICON_NAME, t);
92         }
93 
94 #ifdef GDK_WINDOWING_X11
95     if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY))
96         if (&_gdk_display && _gdk_display) {
97             const char *t;
98 
99             /* We ignore the tiny race condition here. */
100 
101             if ((t = DisplayString(_gdk_display)))
102                 pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, t);
103         }
104 
105 #endif
106 #endif
107 }
108 
pa_init_proplist(pa_proplist * p)109 void pa_init_proplist(pa_proplist *p) {
110     char **e;
111     const char *pp;
112 
113     pa_assert(p);
114 
115     if (environ) {
116 
117         /* Some applications seem to reset environ to NULL for various
118          * reasons, hence we need to check for this explicitly. See
119          * rhbz #473080 */
120 
121         for (e = environ; *e; e++) {
122 
123             if (pa_startswith(*e, "PULSE_PROP_")) {
124                 size_t kl, skip;
125                 char *k;
126                 bool override;
127 
128                 if (pa_startswith(*e, "PULSE_PROP_OVERRIDE_")) {
129                     skip = 20;
130                     override = true;
131                 } else {
132                     skip = 11;
133                     override = false;
134                 }
135 
136                 kl = strcspn(*e+skip, "=");
137 
138                 if ((*e)[skip+kl] != '=')
139                     continue;
140 
141                 k = pa_xstrndup(*e+skip, kl);
142 
143                 if (!pa_streq(k, "OVERRIDE"))
144                     if (override || !pa_proplist_contains(p, k))
145                         pa_proplist_sets(p, k, *e+skip+kl+1);
146                 pa_xfree(k);
147             }
148         }
149     }
150 
151     if ((pp = getenv("PULSE_PROP"))) {
152         pa_proplist *t;
153 
154         if ((t = pa_proplist_from_string(pp))) {
155             pa_proplist_update(p, PA_UPDATE_MERGE, t);
156             pa_proplist_free(t);
157         }
158     }
159 
160     if ((pp = getenv("PULSE_PROP_OVERRIDE"))) {
161         pa_proplist *t;
162 
163         if ((t = pa_proplist_from_string(pp))) {
164             pa_proplist_update(p, PA_UPDATE_REPLACE, t);
165             pa_proplist_free(t);
166         }
167     }
168 
169     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
170         char t[32];
171         pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());
172         pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t);
173     }
174 
175     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) {
176         char *u;
177 
178         if ((u = pa_get_user_name_malloc())) {
179             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, u);
180             pa_xfree(u);
181         }
182     }
183 
184     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) {
185         char *h;
186 
187         if ((h = pa_get_host_name_malloc())) {
188             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, h);
189             pa_xfree(h);
190         }
191     }
192 
193     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY)) {
194         char *t;
195 
196         if ((t = pa_get_binary_name_malloc())) {
197             char *c = pa_utf8_filter(t);
198             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
199             pa_xfree(t);
200             pa_xfree(c);
201         }
202     }
203 
204     add_glib_properties(p);
205     add_gtk_properties(p);
206 
207     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) {
208         const char *t;
209 
210         if ((t = pa_proplist_gets(p, PA_PROP_APPLICATION_PROCESS_BINARY)))
211             pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t);
212     }
213 
214 #ifdef ENABLE_NLS
215     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
216         const char *l;
217 
218         if ((l = setlocale(LC_MESSAGES, NULL)))
219             pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
220     }
221 #endif
222 
223     if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY)) {
224         const char *t;
225 
226         if ((t = getenv("DISPLAY"))) {
227             char *c = pa_utf8_filter(t);
228             pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, c);
229             pa_xfree(c);
230         }
231     }
232 
233     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID)) {
234         char *m;
235 
236         if ((m = pa_machine_id())) {
237             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID, m);
238             pa_xfree(m);
239         }
240     }
241 
242     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_SESSION_ID)) {
243         char *s;
244 
245         if ((s = pa_session_id())) {
246             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_SESSION_ID, s);
247             pa_xfree(s);
248         }
249     }
250 }
251 
pa_proplist_get_stream_group(pa_proplist * p,const char * prefix,const char * cache)252 char *pa_proplist_get_stream_group(pa_proplist *p, const char *prefix, const char *cache) {
253     const char *r;
254     char *t;
255 
256     if (!p)
257         return NULL;
258 
259     if (cache && (r = pa_proplist_gets(p, cache)))
260         return pa_xstrdup(r);
261 
262     if (!prefix)
263         prefix = "stream";
264 
265     if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_ROLE)))
266         t = pa_sprintf_malloc("%s-by-media-role:%s", prefix, r);
267     else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_ID)))
268         t = pa_sprintf_malloc("%s-by-application-id:%s", prefix, r);
269     else if ((r = pa_proplist_gets(p, PA_PROP_APPLICATION_NAME)))
270         t = pa_sprintf_malloc("%s-by-application-name:%s", prefix, r);
271     else if ((r = pa_proplist_gets(p, PA_PROP_MEDIA_NAME)))
272         t = pa_sprintf_malloc("%s-by-media-name:%s", prefix, r);
273     else
274         t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
275 
276     if (cache)
277         pa_proplist_sets(p, cache, t);
278 
279     return t;
280 }
281