From 0368d6e22b9d7e6fec2474d158eaec16c90054f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2009 02:29:01 +0200 Subject: build-system: move x11 and jack modules into subdirectories --- src/modules/x11/module-x11-bell.c | 190 ++++++++++++++++++++++ src/modules/x11/module-x11-cork-request.c | 189 ++++++++++++++++++++++ src/modules/x11/module-x11-publish.c | 245 ++++++++++++++++++++++++++++ src/modules/x11/module-x11-xsmp.c | 254 ++++++++++++++++++++++++++++++ 4 files changed, 878 insertions(+) create mode 100644 src/modules/x11/module-x11-bell.c create mode 100644 src/modules/x11/module-x11-cork-request.c create mode 100644 src/modules/x11/module-x11-publish.c create mode 100644 src/modules/x11/module-x11-xsmp.c (limited to 'src/modules/x11') diff --git a/src/modules/x11/module-x11-bell.c b/src/modules/x11/module-x11-bell.c new file mode 100644 index 00000000..ac303c3b --- /dev/null +++ b/src/modules/x11/module-x11-bell.c @@ -0,0 +1,190 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "module-x11-bell-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("X11 bell interceptor"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE("sink= sample= display="); + +static const char* const valid_modargs[] = { + "sink", + "sample", + "display", + NULL +}; + +struct userdata { + pa_core *core; + pa_module *module; + + int xkb_event_base; + + char *sink_name; + char *scache_item; + + pa_x11_wrapper *x11_wrapper; + pa_x11_client *x11_client; +}; + +static int x11_event_cb(pa_x11_wrapper *w, XEvent *e, void *userdata) { + XkbBellNotifyEvent *bne; + struct userdata *u = userdata; + + pa_assert(w); + pa_assert(e); + pa_assert(u); + pa_assert(u->x11_wrapper == w); + + if (((XkbEvent*) e)->any.xkb_type != XkbBellNotify) + return 0; + + bne = (XkbBellNotifyEvent*) e; + + if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, ((pa_volume_t) bne->percent*PA_VOLUME_NORM)/100U, NULL, NULL) < 0) { + pa_log_info("Ringing bell failed, reverting to X11 device bell."); + XkbForceDeviceBell(pa_x11_wrapper_get_display(w), bne->device, bne->bell_class, bne->bell_id, bne->percent); + } + + return 1; +} + +static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) { + struct userdata *u = userdata; + + pa_assert(w); + pa_assert(u); + pa_assert(u->x11_wrapper == w); + + if (u->x11_client) + pa_x11_client_free(u->x11_client); + + if (u->x11_wrapper) + pa_x11_wrapper_unref(u->x11_wrapper); + + u->x11_client = NULL; + u->x11_wrapper = NULL; + + pa_module_unload_request(u->module, TRUE); +} + +int pa__init(pa_module*m) { + + struct userdata *u = NULL; + pa_modargs *ma = NULL; + int major, minor; + unsigned int auto_ctrls, auto_values; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments"); + goto fail; + } + + m->userdata = u = pa_xnew(struct userdata, 1); + u->core = m->core; + u->module = m; + u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "bell-window-system")); + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + u->x11_client = NULL; + + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) + goto fail; + + major = XkbMajorVersion; + minor = XkbMinorVersion; + + if (!XkbLibraryVersion(&major, &minor)) { + pa_log("XkbLibraryVersion() failed"); + goto fail; + } + + major = XkbMajorVersion; + minor = XkbMinorVersion; + + if (!XkbQueryExtension(pa_x11_wrapper_get_display(u->x11_wrapper), NULL, &u->xkb_event_base, NULL, &major, &minor)) { + pa_log("XkbQueryExtension() failed"); + goto fail; + } + + XkbSelectEvents(pa_x11_wrapper_get_display(u->x11_wrapper), XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); + auto_ctrls = auto_values = XkbAudibleBellMask; + XkbSetAutoResetControls(pa_x11_wrapper_get_display(u->x11_wrapper), XkbAudibleBellMask, &auto_ctrls, &auto_values); + XkbChangeEnabledControls(pa_x11_wrapper_get_display(u->x11_wrapper), XkbUseCoreKbd, XkbAudibleBellMask, 0); + + u->x11_client = pa_x11_client_new(u->x11_wrapper, x11_event_cb, x11_kill_cb, u); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + pa_xfree(u->scache_item); + pa_xfree(u->sink_name); + + if (u->x11_client) + pa_x11_client_free(u->x11_client); + + if (u->x11_wrapper) + pa_x11_wrapper_unref(u->x11_wrapper); + + pa_xfree(u); +} diff --git a/src/modules/x11/module-x11-cork-request.c b/src/modules/x11/module-x11-cork-request.c new file mode 100644 index 00000000..c1380c27 --- /dev/null +++ b/src/modules/x11/module-x11-cork-request.c @@ -0,0 +1,189 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "module-x11-cork-request-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("Synthesize X11 media key events when cork/uncork is requested"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE("display="); + +static const char* const valid_modargs[] = { + "display", + NULL +}; + +struct userdata { + pa_module *module; + + pa_x11_wrapper *x11_wrapper; + pa_x11_client *x11_client; + + pa_hook_slot *hook_slot; +}; + +static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) { + struct userdata *u = userdata; + + pa_assert(w); + pa_assert(u); + pa_assert(u->x11_wrapper == w); + + if (u->x11_client) { + pa_x11_client_free(u->x11_client); + u->x11_client = NULL; + } + + if (u->x11_wrapper) { + pa_x11_wrapper_unref(u->x11_wrapper); + u->x11_wrapper = NULL; + } + + pa_module_unload_request(u->module, TRUE); +} + +static pa_hook_result_t sink_input_send_event_hook_cb( + pa_core *c, + pa_sink_input_send_event_hook_data *data, + struct userdata *u) { + + KeySym sym; + KeyCode code; + Display *display; + + pa_assert(c); + pa_assert(data); + pa_assert(u); + + if (pa_streq(data->event, PA_STREAM_EVENT_REQUEST_CORK)) + sym = XF86XK_AudioPause; + else if (pa_streq(data->event, PA_STREAM_EVENT_REQUEST_UNCORK)) + sym = XF86XK_AudioPlay; + else + return PA_HOOK_OK; + + pa_log_debug("Triggering X11 keysym: %s", XKeysymToString(sym)); + + display = pa_x11_wrapper_get_display(u->x11_wrapper); + code = XKeysymToKeycode(display, sym); + + XTestFakeKeyEvent(display, code, True, CurrentTime); + XSync(display, False); + + XTestFakeKeyEvent(display, code, False, CurrentTime); + XSync(display, False); + + return PA_HOOK_OK; +} + +int pa__init(pa_module *m) { + struct userdata *u; + pa_modargs *ma; + int xtest_event_base, xtest_error_base; + int major_version, minor_version; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("failed to parse module arguments"); + goto fail; + } + + m->userdata = u = pa_xnew0(struct userdata, 1); + u->module = m; + + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) + goto fail; + + if (!XTestQueryExtension( + pa_x11_wrapper_get_display(u->x11_wrapper), + &xtest_event_base, &xtest_error_base, + &major_version, &minor_version)) { + + pa_log("XTest extension not supported."); + goto fail; + } + + pa_log_debug("XTest %i.%i supported.", major_version, minor_version); + + u->x11_client = pa_x11_client_new(u->x11_wrapper, NULL, x11_kill_cb, u); + + u->hook_slot = pa_hook_connect( + &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], + PA_HOOK_NORMAL, + (pa_hook_cb_t) sink_input_send_event_hook_cb, u); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata*u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->x11_client) + pa_x11_client_free(u->x11_client); + + if (u->x11_wrapper) + pa_x11_wrapper_unref(u->x11_wrapper); + + if (u->hook_slot) + pa_hook_slot_free(u->hook_slot); + + pa_xfree(u); +} diff --git a/src/modules/x11/module-x11-publish.c b/src/modules/x11/module-x11-publish.c new file mode 100644 index 00000000..2c7fdc12 --- /dev/null +++ b/src/modules/x11/module-x11-publish.c @@ -0,0 +1,245 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-x11-publish-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("X11 credential publisher"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE( + "display= " + "sink= " + "source= " + "cookie= "); + +static const char* const valid_modargs[] = { + "display", + "sink", + "source", + "cookie", + NULL +}; + +struct userdata { + pa_core *core; + pa_module *module; + pa_native_protocol *protocol; + + char *id; + pa_auth_cookie *auth_cookie; + + pa_x11_wrapper *x11_wrapper; + pa_x11_client *x11_client; + + pa_hook_slot *hook_slot; +}; + +static void publish_servers(struct userdata *u, pa_strlist *l) { + + if (l) { + char *s; + + l = pa_strlist_reverse(l); + s = pa_strlist_tostring(l); + l = pa_strlist_reverse(l); + + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s); + pa_xfree(s); + } else + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER"); +} + +static pa_hook_result_t servers_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_strlist *servers = call_data; + struct userdata *u = slot_data; + char t[256]; + + pa_assert(u); + + if (!pa_x11_get_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", t, sizeof(t)) || strcmp(t, u->id)) { + pa_log_warn("PulseAudio information vanished from X11!"); + return PA_HOOK_OK; + } + + publish_servers(u, servers); + return PA_HOOK_OK; +} + +static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) { + struct userdata *u = userdata; + + pa_assert(w); + pa_assert(u); + pa_assert(u->x11_wrapper == w); + + if (u->x11_client) + pa_x11_client_free(u->x11_client); + + if (u->x11_wrapper) + pa_x11_wrapper_unref(u->x11_wrapper); + + u->x11_client = NULL; + u->x11_wrapper = NULL; + + pa_module_unload_request(u->module, TRUE); +} + +int pa__init(pa_module*m) { + struct userdata *u; + pa_modargs *ma = NULL; + char *mid, *sid; + char hx[PA_NATIVE_COOKIE_LENGTH*2+1]; + const char *t; + + pa_assert(m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("failed to parse module arguments"); + goto fail; + } + + m->userdata = u = pa_xnew(struct userdata, 1); + u->core = m->core; + u->module = m; + u->protocol = pa_native_protocol_get(m->core); + u->id = NULL; + u->auth_cookie = NULL; + u->x11_client = NULL; + u->x11_wrapper = NULL; + + u->hook_slot = pa_hook_connect(&pa_native_protocol_hooks(u->protocol)[PA_NATIVE_HOOK_SERVERS_CHANGED], PA_HOOK_NORMAL, servers_changed_cb, u); + + if (!(u->auth_cookie = pa_auth_cookie_get(m->core, pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), PA_NATIVE_COOKIE_LENGTH))) + goto fail; + + if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) + goto fail; + + mid = pa_machine_id(); + u->id = pa_sprintf_malloc("%lu@%s/%lu", (unsigned long) getuid(), mid, (unsigned long) getpid()); + pa_xfree(mid); + + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", u->id); + + if ((sid = pa_session_id())) { + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SESSION_ID", sid); + pa_xfree(sid); + } + + publish_servers(u, pa_native_protocol_servers(u->protocol)); + + if ((t = pa_modargs_get_value(ma, "source", NULL))) + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SOURCE", t); + + if ((t = pa_modargs_get_value(ma, "sink", NULL))) + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SINK", t); + + pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE", + pa_hexstr(pa_auth_cookie_read(u->auth_cookie, PA_NATIVE_COOKIE_LENGTH), PA_NATIVE_COOKIE_LENGTH, hx, sizeof(hx))); + + u->x11_client = pa_x11_client_new(u->x11_wrapper, NULL, x11_kill_cb, u); + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata*u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->x11_client) + pa_x11_client_free(u->x11_client); + + if (u->x11_wrapper) { + char t[256]; + + /* Yes, here is a race condition */ + if (!pa_x11_get_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", t, sizeof(t)) || strcmp(t, u->id)) + pa_log_warn("PulseAudio information vanished from X11!"); + else { + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SINK"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SOURCE"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE"); + pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SESSION_ID"); + XSync(pa_x11_wrapper_get_display(u->x11_wrapper), False); + } + + pa_x11_wrapper_unref(u->x11_wrapper); + } + + if (u->auth_cookie) + pa_auth_cookie_unref(u->auth_cookie); + + if (u->hook_slot) + pa_hook_slot_free(u->hook_slot); + + if (u->protocol) + pa_native_protocol_unref(u->protocol); + + pa_xfree(u->id); + pa_xfree(u); +} diff --git a/src/modules/x11/module-x11-xsmp.c b/src/modules/x11/module-x11-xsmp.c new file mode 100644 index 00000000..28fd373a --- /dev/null +++ b/src/modules/x11/module-x11-xsmp.c @@ -0,0 +1,254 @@ +/*** + This file is part of PulseAudio. + + Copyright 2004-2006 Lennart Poettering + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module-x11-xsmp-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering"); +PA_MODULE_DESCRIPTION("X11 session management"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(FALSE); +PA_MODULE_USAGE("session_manager= display="); + +static pa_bool_t ice_in_use = FALSE; + +static const char* const valid_modargs[] = { + "session_manager", + "display", + NULL +}; + +struct userdata { + pa_core *core; + pa_module *module; + pa_client *client; + SmcConn connection; + pa_x11_wrapper *x11; +}; + +static void die_cb(SmcConn connection, SmPointer client_data){ + struct userdata *u = client_data; + pa_assert(u); + + pa_log_debug("Got die message from XSMP."); + + pa_x11_wrapper_kill(u->x11); + + pa_x11_wrapper_unref(u->x11); + u->x11 = NULL; + + pa_module_unload_request(u->module, TRUE); +} + +static void save_complete_cb(SmcConn connection, SmPointer client_data) { +} + +static void shutdown_cancelled_cb(SmcConn connection, SmPointer client_data) { + SmcSaveYourselfDone(connection, True); +} + +static void save_yourself_cb(SmcConn connection, SmPointer client_data, int save_type, Bool _shutdown, int interact_style, Bool fast) { + SmcSaveYourselfDone(connection, True); +} + +static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) { + IceConn connection = userdata; + + if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) { + IceSetShutdownNegotiation(connection, False); + IceCloseConnection(connection); + } +} + +static void new_ice_connection(IceConn connection, IcePointer client_data, Bool opening, IcePointer *watch_data) { + struct pa_core *c = client_data; + + if (opening) + *watch_data = c->mainloop->io_new( + c->mainloop, + IceConnectionNumber(connection), + PA_IO_EVENT_INPUT, + ice_io_cb, + connection); + else + c->mainloop->io_free(*watch_data); +} + +int pa__init(pa_module*m) { + + pa_modargs *ma = NULL; + char t[256], *vendor, *client_id; + SmcCallbacks callbacks; + SmProp prop_program, prop_user; + SmProp *prop_list[2]; + SmPropValue val_program, val_user; + struct userdata *u; + const char *e; + pa_client_new_data data; + + pa_assert(m); + + if (ice_in_use) { + pa_log("module-x11-xsmp may no be loaded twice."); + return -1; + } + + IceAddConnectionWatch(new_ice_connection, m->core); + ice_in_use = TRUE; + + m->userdata = u = pa_xnew(struct userdata, 1); + u->core = m->core; + u->module = m; + u->client = NULL; + u->connection = NULL; + u->x11 = NULL; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments"); + goto fail; + } + + if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) + goto fail; + + e = pa_modargs_get_value(ma, "session_manager", NULL); + + if (!e && !getenv("SESSION_MANAGER")) { + pa_log("X11 session manager not running."); + goto fail; + } + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.die.callback = die_cb; + callbacks.die.client_data = u; + callbacks.save_yourself.callback = save_yourself_cb; + callbacks.save_yourself.client_data = m->core; + callbacks.save_complete.callback = save_complete_cb; + callbacks.save_complete.client_data = m->core; + callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb; + callbacks.shutdown_cancelled.client_data = m->core; + + if (!(u->connection = SmcOpenConnection( + (char*) e, m->core, + SmProtoMajor, SmProtoMinor, + SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, + &callbacks, NULL, &client_id, + sizeof(t), t))) { + + pa_log("Failed to open connection to session manager: %s", t); + goto fail; + } + + prop_program.name = (char*) SmProgram; + prop_program.type = (char*) SmARRAY8; + val_program.value = (char*) PACKAGE_NAME; + val_program.length = (int) strlen(val_program.value); + prop_program.num_vals = 1; + prop_program.vals = &val_program; + prop_list[0] = &prop_program; + + prop_user.name = (char*) SmUserID; + prop_user.type = (char*) SmARRAY8; + pa_get_user_name(t, sizeof(t)); + val_user.value = t; + val_user.length = (int) strlen(val_user.value); + prop_user.num_vals = 1; + prop_user.vals = &val_user; + prop_list[1] = &prop_user; + + SmcSetProperties(u->connection, PA_ELEMENTSOF(prop_list), prop_list); + + pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->connection), client_id); + + pa_client_new_data_init(&data); + data.module = m; + data.driver = __FILE__; + pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "XSMP Session on %s as %s", vendor, client_id); + pa_proplist_sets(data.proplist, "xsmp.vendor", vendor); + pa_proplist_sets(data.proplist, "xsmp.client.id", client_id); + u->client = pa_client_new(u->core, &data); + pa_client_new_data_done(&data); + + free(vendor); + free(client_id); + + if (!u->client) + goto fail; + + pa_modargs_free(ma); + + return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + pa__done(m); + + return -1; +} + +void pa__done(pa_module*m) { + struct userdata *u; + + pa_assert(m); + + if ((u = m->userdata)) { + + if (u->connection) + SmcCloseConnection(u->connection, 0, NULL); + + if (u->client) + pa_client_free(u->client); + + if (u->x11) + pa_x11_wrapper_unref(u->x11); + + pa_xfree(u); + } + + if (ice_in_use) { + IceRemoveConnectionWatch(new_ice_connection, m->core); + ice_in_use = FALSE; + } +} -- cgit