Add some more device properties to the sink properties list
[pulseaudio-mirror.git] / src / modules / module-x11-xsmp.c
blob57d182fd2873ab945c1a76e7d112c0e40fd62405
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 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 published
8 by the Free Software Foundation; either version 2 of the License,
9 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 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include <X11/Xlib.h>
31 #include <X11/SM/SMlib.h>
33 #include <pulse/xmalloc.h>
34 #include <pulse/util.h>
36 #include <pulsecore/iochannel.h>
37 #include <pulsecore/sink.h>
38 #include <pulsecore/core-scache.h>
39 #include <pulsecore/modargs.h>
40 #include <pulsecore/namereg.h>
41 #include <pulsecore/log.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/x11wrap.h>
45 #include "module-x11-xsmp-symdef.h"
47 PA_MODULE_AUTHOR("Lennart Poettering");
48 PA_MODULE_DESCRIPTION("X11 session management");
49 PA_MODULE_VERSION(PACKAGE_VERSION);
50 PA_MODULE_LOAD_ONCE(FALSE);
51 PA_MODULE_USAGE("session_manager=<session manager string> display=<X11 display>");
53 static pa_bool_t ice_in_use = FALSE;
55 static const char* const valid_modargs[] = {
56 "session_manager",
57 "display",
58 NULL
61 struct userdata {
62 pa_core *core;
63 pa_module *module;
64 pa_client *client;
65 SmcConn connection;
66 pa_x11_wrapper *x11;
69 static void die_cb(SmcConn connection, SmPointer client_data){
70 struct userdata *u = client_data;
71 pa_assert(u);
73 pa_log_debug("Got die message from XSMP.");
75 pa_x11_wrapper_kill(u->x11);
77 pa_x11_wrapper_unref(u->x11);
78 u->x11 = NULL;
80 pa_module_unload_request(u->module, TRUE);
83 static void save_complete_cb(SmcConn connection, SmPointer client_data) {
86 static void shutdown_cancelled_cb(SmcConn connection, SmPointer client_data) {
87 SmcSaveYourselfDone(connection, True);
90 static void save_yourself_cb(SmcConn connection, SmPointer client_data, int save_type, Bool _shutdown, int interact_style, Bool fast) {
91 SmcSaveYourselfDone(connection, True);
94 static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
95 IceConn connection = userdata;
97 if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) {
98 IceSetShutdownNegotiation(connection, False);
99 IceCloseConnection(connection);
103 static void new_ice_connection(IceConn connection, IcePointer client_data, Bool opening, IcePointer *watch_data) {
104 struct pa_core *c = client_data;
106 if (opening)
107 *watch_data = c->mainloop->io_new(
108 c->mainloop,
109 IceConnectionNumber(connection),
110 PA_IO_EVENT_INPUT,
111 ice_io_cb,
112 connection);
113 else
114 c->mainloop->io_free(*watch_data);
117 int pa__init(pa_module*m) {
119 pa_modargs *ma = NULL;
120 char t[256], *vendor, *client_id, *k;
121 SmcCallbacks callbacks;
122 SmProp prop_program, prop_user;
123 SmProp *prop_list[2];
124 SmPropValue val_program, val_user;
125 struct userdata *u;
126 const char *e;
128 pa_assert(m);
130 if (ice_in_use) {
131 pa_log("module-x11-xsmp may no be loaded twice.");
132 return -1;
135 IceAddConnectionWatch(new_ice_connection, m->core);
136 ice_in_use = TRUE;
138 m->userdata = u = pa_xnew(struct userdata, 1);
139 u->core = m->core;
140 u->module = m;
141 u->client = NULL;
142 u->connection = NULL;
143 u->x11 = NULL;
145 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
146 pa_log("Failed to parse module arguments");
147 goto fail;
150 if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
151 goto fail;
153 e = pa_modargs_get_value(ma, "session_manager", NULL);
155 if (!e && !getenv("SESSION_MANAGER")) {
156 pa_log("X11 session manager not running.");
157 goto fail;
160 memset(&callbacks, 0, sizeof(callbacks));
161 callbacks.die.callback = die_cb;
162 callbacks.die.client_data = u;
163 callbacks.save_yourself.callback = save_yourself_cb;
164 callbacks.save_yourself.client_data = m->core;
165 callbacks.save_complete.callback = save_complete_cb;
166 callbacks.save_complete.client_data = m->core;
167 callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb;
168 callbacks.shutdown_cancelled.client_data = m->core;
170 if (!(u->connection = SmcOpenConnection(
171 (char*) e, m->core,
172 SmProtoMajor, SmProtoMinor,
173 SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
174 &callbacks, NULL, &client_id,
175 sizeof(t), t))) {
177 pa_log("Failed to open connection to session manager: %s", t);
178 goto fail;
181 prop_program.name = (char*) SmProgram;
182 prop_program.type = (char*) SmARRAY8;
183 val_program.value = (char*) PACKAGE_NAME;
184 val_program.length = (int) strlen(val_program.value);
185 prop_program.num_vals = 1;
186 prop_program.vals = &val_program;
187 prop_list[0] = &prop_program;
189 prop_user.name = (char*) SmUserID;
190 prop_user.type = (char*) SmARRAY8;
191 pa_get_user_name(t, sizeof(t));
192 val_user.value = t;
193 val_user.length = (int) strlen(val_user.value);
194 prop_user.num_vals = 1;
195 prop_user.vals = &val_user;
196 prop_list[1] = &prop_user;
198 SmcSetProperties(u->connection, PA_ELEMENTSOF(prop_list), prop_list);
200 pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->connection), client_id);
201 k = pa_sprintf_malloc("XSMP Session on %s as %s", vendor, client_id);
202 u->client = pa_client_new(u->core, __FILE__, k);
203 pa_xfree(k);
205 pa_proplist_sets(u->client->proplist, "xsmp.vendor", vendor);
206 pa_proplist_sets(u->client->proplist, "xsmp.client.id", client_id);
208 free(vendor);
209 free(client_id);
211 pa_modargs_free(ma);
213 return 0;
215 fail:
216 if (ma)
217 pa_modargs_free(ma);
219 pa__done(m);
221 return -1;
224 void pa__done(pa_module*m) {
225 struct userdata *u;
227 pa_assert(m);
229 if ((u = m->userdata)) {
231 if (u->connection)
232 SmcCloseConnection(u->connection, 0, NULL);
234 if (u->client)
235 pa_client_free(u->client);
237 if (u->x11)
238 pa_x11_wrapper_unref(u->x11);
240 pa_xfree(u);
243 if (ice_in_use) {
244 IceRemoveConnectionWatch(new_ice_connection, m->core);
245 ice_in_use = FALSE;