lirc: fix logic behind mute buttons
[profile/ivi/pulseaudio-panda.git] / src / modules / 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/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>
44
45 #include "module-x11-xsmp-symdef.h"
46
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>");
52
53 static pa_bool_t ice_in_use = FALSE;
54
55 static const char* const valid_modargs[] = {
56     "session_manager",
57     "display",
58     NULL
59 };
60
61 struct userdata {
62     pa_core *core;
63     pa_module *module;
64     pa_client *client;
65     SmcConn connection;
66     pa_x11_wrapper *x11;
67 };
68
69 static void die_cb(SmcConn connection, SmPointer client_data){
70     struct userdata *u = client_data;
71     pa_assert(u);
72
73     pa_log_debug("Got die message from XSMP.");
74
75     pa_x11_wrapper_kill(u->x11);
76
77     pa_x11_wrapper_unref(u->x11);
78     u->x11 = NULL;
79
80     pa_module_unload_request(u->module, TRUE);
81 }
82
83 static void save_complete_cb(SmcConn connection, SmPointer client_data) {
84 }
85
86 static void shutdown_cancelled_cb(SmcConn connection, SmPointer client_data) {
87     SmcSaveYourselfDone(connection, True);
88 }
89
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);
92 }
93
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;
96
97     if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) {
98         IceSetShutdownNegotiation(connection, False);
99         IceCloseConnection(connection);
100     }
101 }
102
103 static void new_ice_connection(IceConn connection, IcePointer client_data, Bool opening, IcePointer *watch_data) {
104     struct pa_core *c = client_data;
105
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);
115 }
116
117 int pa__init(pa_module*m) {
118
119     pa_modargs *ma = NULL;
120     char t[256], *vendor, *client_id;
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;
127     pa_client_new_data data;
128
129     pa_assert(m);
130
131     if (ice_in_use) {
132         pa_log("module-x11-xsmp may no be loaded twice.");
133         return -1;
134     }
135
136     IceAddConnectionWatch(new_ice_connection, m->core);
137     ice_in_use = TRUE;
138
139     m->userdata = u = pa_xnew(struct userdata, 1);
140     u->core = m->core;
141     u->module = m;
142     u->client = NULL;
143     u->connection = NULL;
144     u->x11 = NULL;
145
146     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
147         pa_log("Failed to parse module arguments");
148         goto fail;
149     }
150
151     if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
152         goto fail;
153
154     e = pa_modargs_get_value(ma, "session_manager", NULL);
155
156     if (!e && !getenv("SESSION_MANAGER")) {
157         pa_log("X11 session manager not running.");
158         goto fail;
159     }
160
161     memset(&callbacks, 0, sizeof(callbacks));
162     callbacks.die.callback = die_cb;
163     callbacks.die.client_data = u;
164     callbacks.save_yourself.callback = save_yourself_cb;
165     callbacks.save_yourself.client_data = m->core;
166     callbacks.save_complete.callback = save_complete_cb;
167     callbacks.save_complete.client_data = m->core;
168     callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb;
169     callbacks.shutdown_cancelled.client_data = m->core;
170
171     if (!(u->connection = SmcOpenConnection(
172                   (char*) e, m->core,
173                   SmProtoMajor, SmProtoMinor,
174                   SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
175                   &callbacks, NULL, &client_id,
176                   sizeof(t), t))) {
177
178         pa_log("Failed to open connection to session manager: %s", t);
179         goto fail;
180     }
181
182     prop_program.name = (char*) SmProgram;
183     prop_program.type = (char*) SmARRAY8;
184     val_program.value = (char*) PACKAGE_NAME;
185     val_program.length = (int) strlen(val_program.value);
186     prop_program.num_vals = 1;
187     prop_program.vals = &val_program;
188     prop_list[0] = &prop_program;
189
190     prop_user.name = (char*) SmUserID;
191     prop_user.type = (char*) SmARRAY8;
192     pa_get_user_name(t, sizeof(t));
193     val_user.value = t;
194     val_user.length = (int) strlen(val_user.value);
195     prop_user.num_vals = 1;
196     prop_user.vals = &val_user;
197     prop_list[1] = &prop_user;
198
199     SmcSetProperties(u->connection, PA_ELEMENTSOF(prop_list), prop_list);
200
201     pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->connection), client_id);
202
203     pa_client_new_data_init(&data);
204     data.module = m;
205     data.driver = __FILE__;
206     pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "XSMP Session on %s as %s", vendor, client_id);
207     pa_proplist_sets(data.proplist, "xsmp.vendor", vendor);
208     pa_proplist_sets(data.proplist, "xsmp.client.id", client_id);
209     u->client = pa_client_new(u->core, &data);
210     pa_client_new_data_done(&data);
211
212     free(vendor);
213     free(client_id);
214
215     if (!u->client)
216         goto fail;
217
218     pa_modargs_free(ma);
219
220     return 0;
221
222 fail:
223     if (ma)
224         pa_modargs_free(ma);
225
226     pa__done(m);
227
228     return -1;
229 }
230
231 void pa__done(pa_module*m) {
232     struct userdata *u;
233
234     pa_assert(m);
235
236     if ((u = m->userdata)) {
237
238         if (u->connection)
239             SmcCloseConnection(u->connection, 0, NULL);
240
241         if (u->client)
242             pa_client_free(u->client);
243
244         if (u->x11)
245             pa_x11_wrapper_unref(u->x11);
246
247         pa_xfree(u);
248     }
249
250     if (ice_in_use) {
251         IceRemoveConnectionWatch(new_ice_connection, m->core);
252         ice_in_use = FALSE;
253     }
254 }