1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 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 published
8 by the Free Software Foundation; either version 2.1 of the License,
9 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 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 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 <stdio.h>
25 #include <getopt.h>
26 #include <assert.h>
27 #include <locale.h>
28
29 #include <xcb/xcb.h>
30
31 #include <pulse/util.h>
32 #include <pulse/client-conf.h>
33
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/i18n.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/authkey.h>
38 #include <pulsecore/native-common.h>
39 #include <pulsecore/x11prop.h>
40
main(int argc,char * argv[])41 int main(int argc, char *argv[]) {
42 const char *dname = NULL, *sink = NULL, *source = NULL, *server = NULL, *cookie_file = PA_NATIVE_COOKIE_FILE;
43 int c, ret = 1, screen = 0;
44 xcb_connection_t *xcb = NULL;
45 enum { DUMP, EXPORT, IMPORT, REMOVE } mode = DUMP;
46
47 setlocale(LC_ALL, "");
48 #ifdef ENABLE_NLS
49 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
50 #endif
51
52 while ((c = getopt(argc, argv, "deiD:S:O:I:c:hr")) != -1) {
53 switch (c) {
54 case 'D' :
55 dname = optarg;
56 break;
57 case 'h':
58 printf(_("%s [-D display] [-S server] [-O sink] [-I source] [-c file] [-d|-e|-i|-r]\n\n"
59 " -d Show current PulseAudio data attached to X11 display (default)\n"
60 " -e Export local PulseAudio data to X11 display\n"
61 " -i Import PulseAudio data from X11 display to local environment variables and cookie file.\n"
62 " -r Remove PulseAudio data from X11 display\n"),
63 pa_path_get_filename(argv[0]));
64 ret = 0;
65 goto finish;
66 case 'd':
67 mode = DUMP;
68 break;
69 case 'e':
70 mode = EXPORT;
71 break;
72 case 'i':
73 mode = IMPORT;
74 break;
75 case 'r':
76 mode = REMOVE;
77 break;
78 case 'c':
79 cookie_file = optarg;
80 break;
81 case 'I':
82 source = optarg;
83 break;
84 case 'O':
85 sink = optarg;
86 break;
87 case 'S':
88 server = optarg;
89 break;
90 default:
91 fprintf(stderr, _("Failed to parse command line.\n"));
92 goto finish;
93 }
94 }
95
96 if (!(xcb = xcb_connect(dname, &screen))) {
97 pa_log(_("xcb_connect() failed"));
98 goto finish;
99 }
100
101 if (xcb_connection_has_error(xcb)) {
102 pa_log(_("xcb_connection_has_error() returned true"));
103 goto finish;
104 }
105
106 switch (mode) {
107 case DUMP: {
108 char t[1024];
109 if (pa_x11_get_prop(xcb, screen, "PULSE_SERVER", t, sizeof(t)))
110 printf(_("Server: %s\n"), t);
111 if (pa_x11_get_prop(xcb, screen, "PULSE_SOURCE", t, sizeof(t)))
112 printf(_("Source: %s\n"), t);
113 if (pa_x11_get_prop(xcb, screen, "PULSE_SINK", t, sizeof(t)))
114 printf(_("Sink: %s\n"), t);
115 if (pa_x11_get_prop(xcb, screen, "PULSE_COOKIE", t, sizeof(t)))
116 printf(_("Cookie: %s\n"), t);
117
118 break;
119 }
120
121 case IMPORT: {
122 char t[1024];
123 if (pa_x11_get_prop(xcb, screen, "PULSE_SERVER", t, sizeof(t)))
124 printf("PULSE_SERVER='%s'\nexport PULSE_SERVER\n", t);
125 if (pa_x11_get_prop(xcb, screen, "PULSE_SOURCE", t, sizeof(t)))
126 printf("PULSE_SOURCE='%s'\nexport PULSE_SOURCE\n", t);
127 if (pa_x11_get_prop(xcb, screen, "PULSE_SINK", t, sizeof(t)))
128 printf("PULSE_SINK='%s'\nexport PULSE_SINK\n", t);
129
130 if (pa_x11_get_prop(xcb, screen, "PULSE_COOKIE", t, sizeof(t))) {
131 uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
132 size_t l;
133 if ((l = pa_parsehex(t, cookie, sizeof(cookie))) != sizeof(cookie)) {
134 fprintf(stderr, _("Failed to parse cookie data\n"));
135 goto finish;
136 }
137
138 if (pa_authkey_save(cookie_file, cookie, l) < 0) {
139 fprintf(stderr, _("Failed to save cookie data\n"));
140 goto finish;
141 }
142 }
143
144 break;
145 }
146
147 case EXPORT: {
148 pa_client_conf *conf = pa_client_conf_new();
149 uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
150 char hx[PA_NATIVE_COOKIE_LENGTH*2+1];
151 assert(conf);
152
153 pa_client_conf_load(conf, false, true);
154
155 pa_x11_del_prop(xcb, screen, "PULSE_SERVER");
156 pa_x11_del_prop(xcb, screen, "PULSE_SINK");
157 pa_x11_del_prop(xcb, screen, "PULSE_SOURCE");
158 pa_x11_del_prop(xcb, screen, "PULSE_ID");
159 pa_x11_del_prop(xcb, screen, "PULSE_COOKIE");
160
161 if (server)
162 pa_x11_set_prop(xcb, screen, "PULSE_SERVER", server);
163 else if (conf->default_server)
164 pa_x11_set_prop(xcb, screen, "PULSE_SERVER", conf->default_server);
165 else {
166 char hn[256];
167 if (!pa_get_fqdn(hn, sizeof(hn))) {
168 fprintf(stderr, _("Failed to get FQDN.\n"));
169 goto finish;
170 }
171
172 pa_x11_set_prop(xcb, screen, "PULSE_SERVER", hn);
173 }
174
175 if (sink)
176 pa_x11_set_prop(xcb, screen, "PULSE_SINK", sink);
177 else if (conf->default_sink)
178 pa_x11_set_prop(xcb, screen, "PULSE_SINK", conf->default_sink);
179
180 if (source)
181 pa_x11_set_prop(xcb, screen, "PULSE_SOURCE", source);
182 if (conf->default_source)
183 pa_x11_set_prop(xcb, screen, "PULSE_SOURCE", conf->default_source);
184
185 pa_client_conf_free(conf);
186
187 if (pa_authkey_load(cookie_file, true, cookie, sizeof(cookie)) < 0) {
188 fprintf(stderr, _("Failed to load cookie data\n"));
189 goto finish;
190 }
191
192 pa_x11_set_prop(xcb, screen, "PULSE_COOKIE", pa_hexstr(cookie, sizeof(cookie), hx, sizeof(hx)));
193 break;
194 }
195
196 case REMOVE:
197 pa_x11_del_prop(xcb, screen, "PULSE_SERVER");
198 pa_x11_del_prop(xcb, screen, "PULSE_SINK");
199 pa_x11_del_prop(xcb, screen, "PULSE_SOURCE");
200 pa_x11_del_prop(xcb, screen, "PULSE_ID");
201 pa_x11_del_prop(xcb, screen, "PULSE_COOKIE");
202 pa_x11_del_prop(xcb, screen, "PULSE_SESSION_ID");
203 break;
204
205 default:
206 fprintf(stderr, _("Not yet implemented.\n"));
207 goto finish;
208 }
209
210 ret = 0;
211
212 finish:
213
214 if (xcb) {
215 xcb_flush(xcb);
216 xcb_disconnect(xcb);
217 }
218
219 return ret;
220 }
221