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
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[] = {
69 static void die_cb(SmcConn connection, SmPointer client_data){
70 struct userdata *u = client_data;
73 pa_log_debug("Got die message from XSMP.");
75 pa_x11_wrapper_kill(u->x11);
77 pa_x11_wrapper_unref(u->x11);
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;
107 *watch_data = c->mainloop->io_new(
109 IceConnectionNumber(connection),
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;
131 pa_log("module-x11-xsmp may no be loaded twice.");
135 IceAddConnectionWatch(new_ice_connection, m->core);
138 m->userdata = u = pa_xnew(struct userdata, 1);
142 u->connection = NULL;
145 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
146 pa_log("Failed to parse module arguments");
150 if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
153 e = pa_modargs_get_value(ma, "session_manager", NULL);
155 if (!e && !getenv("SESSION_MANAGER")) {
156 pa_log("X11 session manager not running.");
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(
172 SmProtoMajor, SmProtoMinor,
173 SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
174 &callbacks, NULL, &client_id,
177 pa_log("Failed to open connection to session manager: %s", t);
181 prop_program.name = (char*) SmProgram;
182 prop_program.type = (char*) SmARRAY8;
183 val_program.value = (char*) PACKAGE_NAME;
184 val_program.length = 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));
193 val_user.length = 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);
205 pa_proplist_sets(u->client->proplist, "xsmp.vendor", vendor);
206 pa_proplist_sets(u->client->proplist, "xsmp.client.id", client_id);
224 void pa__done(pa_module*m) {
229 if ((u = m->userdata)) {
232 SmcCloseConnection(u->connection, 0, NULL);
235 pa_client_free(u->client);
238 pa_x11_wrapper_unref(u->x11);
244 IceRemoveConnectionWatch(new_ice_connection, m->core);