]> code.delx.au - pulseaudio/blob - src/modules/x11/module-x11-xsmp.c
Remove pa_bool_t and replace it with bool.
[pulseaudio] / src / modules / x11 / module-x11-xsmp.c
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, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <X11/Xlib.h>
31 #include <X11/SM/SMlib.h>
32
33 #include <pulse/xmalloc.h>
34 #include <pulse/util.h>
35
36 #include <pulsecore/modargs.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/x11wrap.h>
39
40 #include "module-x11-xsmp-symdef.h"
41
42 PA_MODULE_AUTHOR("Lennart Poettering");
43 PA_MODULE_DESCRIPTION("X11 session management");
44 PA_MODULE_VERSION(PACKAGE_VERSION);
45 PA_MODULE_LOAD_ONCE(false);
46 PA_MODULE_USAGE("session_manager=<session manager string> display=<X11 display>");
47
48 static bool ice_in_use = false;
49
50 static const char* const valid_modargs[] = {
51 "session_manager",
52 "display",
53 NULL
54 };
55
56 struct userdata {
57 pa_core *core;
58 pa_module *module;
59 pa_client *client;
60 SmcConn connection;
61 pa_x11_wrapper *x11;
62 };
63
64 static void die_cb(SmcConn connection, SmPointer client_data) {
65 struct userdata *u = client_data;
66 pa_assert(u);
67
68 pa_log_debug("Got die message from XSMP.");
69
70 pa_x11_wrapper_kill(u->x11);
71
72 pa_x11_wrapper_unref(u->x11);
73 u->x11 = NULL;
74
75 pa_module_unload_request(u->module, true);
76 }
77
78 static void save_complete_cb(SmcConn connection, SmPointer client_data) {
79 }
80
81 static void shutdown_cancelled_cb(SmcConn connection, SmPointer client_data) {
82 SmcSaveYourselfDone(connection, True);
83 }
84
85 static void save_yourself_cb(SmcConn connection, SmPointer client_data, int save_type, Bool _shutdown, int interact_style, Bool fast) {
86 SmcSaveYourselfDone(connection, True);
87 }
88
89 static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
90 IceConn connection = userdata;
91
92 if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) {
93 IceSetShutdownNegotiation(connection, False);
94 IceCloseConnection(connection);
95 }
96 }
97
98 static void new_ice_connection(IceConn connection, IcePointer client_data, Bool opening, IcePointer *watch_data) {
99 pa_core *c = client_data;
100
101 if (opening)
102 *watch_data = c->mainloop->io_new(
103 c->mainloop,
104 IceConnectionNumber(connection),
105 PA_IO_EVENT_INPUT,
106 ice_io_cb,
107 connection);
108 else
109 c->mainloop->io_free(*watch_data);
110 }
111
112 int pa__init(pa_module*m) {
113
114 pa_modargs *ma = NULL;
115 char t[256], *vendor, *client_id;
116 SmcCallbacks callbacks;
117 SmProp prop_program, prop_user;
118 SmProp *prop_list[2];
119 SmPropValue val_program, val_user;
120 struct userdata *u;
121 const char *e;
122 pa_client_new_data data;
123
124 pa_assert(m);
125
126 if (ice_in_use) {
127 pa_log("module-x11-xsmp may not be loaded twice.");
128 return -1;
129 }
130
131 IceAddConnectionWatch(new_ice_connection, m->core);
132 ice_in_use = true;
133
134 m->userdata = u = pa_xnew(struct userdata, 1);
135 u->core = m->core;
136 u->module = m;
137 u->client = NULL;
138 u->connection = NULL;
139 u->x11 = NULL;
140
141 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
142 pa_log("Failed to parse module arguments");
143 goto fail;
144 }
145
146 if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
147 goto fail;
148
149 e = pa_modargs_get_value(ma, "session_manager", NULL);
150
151 if (!e && !getenv("SESSION_MANAGER")) {
152 pa_log("X11 session manager not running.");
153 goto fail;
154 }
155
156 memset(&callbacks, 0, sizeof(callbacks));
157 callbacks.die.callback = die_cb;
158 callbacks.die.client_data = u;
159 callbacks.save_yourself.callback = save_yourself_cb;
160 callbacks.save_yourself.client_data = m->core;
161 callbacks.save_complete.callback = save_complete_cb;
162 callbacks.save_complete.client_data = m->core;
163 callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb;
164 callbacks.shutdown_cancelled.client_data = m->core;
165
166 if (!(u->connection = SmcOpenConnection(
167 (char*) e, m->core,
168 SmProtoMajor, SmProtoMinor,
169 SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
170 &callbacks, NULL, &client_id,
171 sizeof(t), t))) {
172
173 pa_log("Failed to open connection to session manager: %s", t);
174 goto fail;
175 }
176
177 prop_program.name = (char*) SmProgram;
178 prop_program.type = (char*) SmARRAY8;
179 val_program.value = (char*) PACKAGE_NAME;
180 val_program.length = (int) strlen(val_program.value);
181 prop_program.num_vals = 1;
182 prop_program.vals = &val_program;
183 prop_list[0] = &prop_program;
184
185 prop_user.name = (char*) SmUserID;
186 prop_user.type = (char*) SmARRAY8;
187 pa_get_user_name(t, sizeof(t));
188 val_user.value = t;
189 val_user.length = (int) strlen(val_user.value);
190 prop_user.num_vals = 1;
191 prop_user.vals = &val_user;
192 prop_list[1] = &prop_user;
193
194 SmcSetProperties(u->connection, PA_ELEMENTSOF(prop_list), prop_list);
195
196 pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->connection), client_id);
197
198 pa_client_new_data_init(&data);
199 data.module = m;
200 data.driver = __FILE__;
201 pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "XSMP Session on %s as %s", vendor, client_id);
202 pa_proplist_sets(data.proplist, "xsmp.vendor", vendor);
203 pa_proplist_sets(data.proplist, "xsmp.client.id", client_id);
204 u->client = pa_client_new(u->core, &data);
205 pa_client_new_data_done(&data);
206
207 free(vendor);
208 free(client_id);
209
210 if (!u->client)
211 goto fail;
212
213 pa_modargs_free(ma);
214
215 return 0;
216
217 fail:
218 if (ma)
219 pa_modargs_free(ma);
220
221 pa__done(m);
222
223 return -1;
224 }
225
226 void pa__done(pa_module*m) {
227 struct userdata *u;
228
229 pa_assert(m);
230
231 if ((u = m->userdata)) {
232
233 if (u->connection)
234 SmcCloseConnection(u->connection, 0, NULL);
235
236 if (u->client)
237 pa_client_free(u->client);
238
239 if (u->x11)
240 pa_x11_wrapper_unref(u->x11);
241
242 pa_xfree(u);
243 }
244
245 if (ice_in_use) {
246 IceRemoveConnectionWatch(new_ice_connection, m->core);
247 ice_in_use = false;
248 }
249 }