• 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 #include <gdk/gdkx.h>
55 static const gchar* _gtk_window_get_default_icon_name(void) PA_GCC_WEAKREF(gtk_window_get_default_icon_name);
56 static Display *_gdk_display PA_GCC_WEAKREF(gdk_display);
57 #endif
58 
59 #include "proplist-util.h"
60 
add_glib_properties(pa_proplist * p)61 static void add_glib_properties(pa_proplist *p) {
62 
63 #if defined(HAVE_GLIB) && defined(PA_GCC_WEAKREF)
64 
65     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))
66         if (_g_get_application_name) {
67             const gchar *t;
68 
69             /* We ignore the tiny race condition here. */
70 
71             if ((t = _g_get_application_name()))
72                 pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t);
73         }
74 
75 #endif
76 }
77 
add_gtk_properties(pa_proplist * p)78 static void add_gtk_properties(pa_proplist *p) {
79 
80 #if defined(HAVE_GTK) && defined(PA_GCC_WEAKREF)
81 
82     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_ICON_NAME))
83         if (_gtk_window_get_default_icon_name) {
84             const gchar *t;
85 
86             /* We ignore the tiny race condition here. */
87 
88             if ((t = _gtk_window_get_default_icon_name()))
89                 pa_proplist_sets(p, PA_PROP_APPLICATION_ICON_NAME, t);
90         }
91 
92     if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY))
93         if (&_gdk_display && _gdk_display) {
94             const char *t;
95 
96             /* We ignore the tiny race condition here. */
97 
98             if ((t = DisplayString(_gdk_display)))
99                 pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, t);
100         }
101 
102 #endif
103 }
104 
pa_init_proplist(pa_proplist * p)105 void pa_init_proplist(pa_proplist *p) {
106     char **e;
107     const char *pp;
108 
109     pa_assert(p);
110 
111     if (environ) {
112 
113         /* Some applications seem to reset environ to NULL for various
114          * reasons, hence we need to check for this explicitly. See
115          * rhbz #473080 */
116 
117         for (e = environ; *e; e++) {
118 
119             if (pa_startswith(*e, "PULSE_PROP_")) {
120                 size_t kl, skip;
121                 char *k;
122                 bool override;
123 
124                 if (pa_startswith(*e, "PULSE_PROP_OVERRIDE_")) {
125                     skip = 20;
126                     override = true;
127                 } else {
128                     skip = 11;
129                     override = false;
130                 }
131 
132                 kl = strcspn(*e+skip, "=");
133 
134                 if ((*e)[skip+kl] != '=')
135                     continue;
136 
137                 k = pa_xstrndup(*e+skip, kl);
138 
139                 if (!pa_streq(k, "OVERRIDE"))
140                     if (override || !pa_proplist_contains(p, k))
141                         pa_proplist_sets(p, k, *e+skip+kl+1);
142                 pa_xfree(k);
143             }
144         }
145     }
146 
147     if ((pp = getenv("PULSE_PROP"))) {
148         pa_proplist *t;
149 
150         if ((t = pa_proplist_from_string(pp))) {
151             pa_proplist_update(p, PA_UPDATE_MERGE, t);
152             pa_proplist_free(t);
153         }
154     }
155 
156     if ((pp = getenv("PULSE_PROP_OVERRIDE"))) {
157         pa_proplist *t;
158 
159         if ((t = pa_proplist_from_string(pp))) {
160             pa_proplist_update(p, PA_UPDATE_REPLACE, t);
161             pa_proplist_free(t);
162         }
163     }
164 
165     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
166         char t[32];
167         pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());
168         pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t);
169     }
170 
171     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) {
172         char *u;
173 
174         if ((u = pa_get_user_name_malloc())) {
175             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, u);
176             pa_xfree(u);
177         }
178     }
179 
180     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) {
181         char *h;
182 
183         if ((h = pa_get_host_name_malloc())) {
184             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, h);
185             pa_xfree(h);
186         }
187     }
188 
189     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY)) {
190         char *t;
191 
192         if ((t = pa_get_binary_name_malloc())) {
193             char *c = pa_utf8_filter(t);
194             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
195             pa_xfree(t);
196             pa_xfree(c);
197         }
198     }
199 
200     add_glib_properties(p);
201     add_gtk_properties(p);
202 
203     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_NAME)) {
204         const char *t;
205 
206         if ((t = pa_proplist_gets(p, PA_PROP_APPLICATION_PROCESS_BINARY)))
207             pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, t);
208     }
209 
210 #ifdef ENABLE_NLS
211     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
212         const char *l;
213 
214         if ((l = setlocale(LC_MESSAGES, NULL)))
215             pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
216     }
217 #endif
218 
219     if (!pa_proplist_contains(p, PA_PROP_WINDOW_X11_DISPLAY)) {
220         const char *t;
221 
222         if ((t = getenv("DISPLAY"))) {
223             char *c = pa_utf8_filter(t);
224             pa_proplist_sets(p, PA_PROP_WINDOW_X11_DISPLAY, c);
225             pa_xfree(c);
226         }
227     }
228 
229     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID)) {
230         char *m;
231 
232         if ((m = pa_machine_id())) {
233             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_MACHINE_ID, m);
234             pa_xfree(m);
235         }
236     }
237 
238     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_SESSION_ID)) {
239         char *s;
240 
241         if ((s = pa_session_id())) {
242             pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_SESSION_ID, s);
243             pa_xfree(s);
244         }
245     }
246 }
247 
pa_proplist_get_stream_group(pa_proplist * p,const char * prefix,const char * cache)248 char *pa_proplist_get_stream_group(pa_proplist *p, const char *prefix, const char *cache) {
249     const char *r;
250     char *t;
251 
252     if (!p)
253         return NULL;
254 
255     if (cache && (r = pa_proplist_gets(p, cache)))
256         return pa_xstrdup(r);
257 
258     if (!prefix)
259         prefix = "stream";
260 
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);
269     else
270         t = pa_sprintf_malloc("%s-fallback:%s", prefix, r);
271 
272     if (cache)
273         pa_proplist_sets(p, cache, t);
274 
275     return t;
276 }
277