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 41int 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 212finish: 213 214 if (xcb) { 215 xcb_flush(xcb); 216 xcb_disconnect(xcb); 217 } 218 219 return ret; 220} 221