From c33db3ce68197cfe93f1fdf1b6459b1c7afb9057 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Jun 2008 16:58:00 +0000 Subject: don't exit when the XSM signals us a session exit. instead just unload all X11 modules git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2512 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/Makefile.am | 2 +- src/modules/module-x11-bell.c | 49 ++++++++++++++------ src/modules/module-x11-publish.c | 50 +++++++++++++++++---- src/modules/module-x11-xsmp.c | 96 +++++++++++++++++++++++++++++++--------- src/pulsecore/x11wrap.c | 41 +++++++++++++---- src/pulsecore/x11wrap.h | 10 ++++- 6 files changed, 193 insertions(+), 55 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c1f62ab8..e626d04e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1361,7 +1361,7 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX module_x11_xsmp_la_SOURCES = modules/module-x11-xsmp.c module_x11_xsmp_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS) module_x11_xsmp_la_LDFLAGS = -module -avoid-version -module_x11_xsmp_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libpulsecore.la +module_x11_xsmp_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS) libx11wrap.la libpulsecore.la # OSS diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c index 761b82a9..5d4d2b32 100644 --- a/src/modules/module-x11-bell.c +++ b/src/modules/module-x11-bell.c @@ -45,14 +45,24 @@ #include "module-x11-bell-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering"); -PA_MODULE_DESCRIPTION("X11 Bell interceptor"); +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; @@ -60,14 +70,7 @@ struct userdata { pa_x11_client *x11_client; }; -static const char* const valid_modargs[] = { - "sink", - "sample", - "display", - NULL -}; - -static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) { +static int x11_event_cb(pa_x11_wrapper *w, XEvent *e, void *userdata) { XkbBellNotifyEvent *bne; struct userdata *u = userdata; @@ -89,6 +92,25 @@ static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) { 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); +} + int pa__init(pa_module*m) { struct userdata *u = NULL; @@ -105,7 +127,8 @@ int pa__init(pa_module*m) { m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; - u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "x11-bell")); + 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; @@ -133,7 +156,7 @@ int pa__init(pa_module*m) { 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_callback, u); + u->x11_client = pa_x11_client_new(u->x11_wrapper, x11_event_cb, x11_kill_cb, u); pa_modargs_free(ma); @@ -153,11 +176,9 @@ void pa__done(pa_module*m) { pa_assert(m); - if (!m->userdata) + if (!(u = m->userdata)) return; - u = m->userdata; - pa_xfree(u->scache_item); pa_xfree(u->sink_name); diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c index 429c2a69..afe04822 100644 --- a/src/modules/module-x11-publish.c +++ b/src/modules/module-x11-publish.c @@ -54,7 +54,7 @@ #include "module-x11-publish-symdef.h" PA_MODULE_AUTHOR("Lennart Poettering"); -PA_MODULE_DESCRIPTION("X11 Credential Publisher"); +PA_MODULE_DESCRIPTION("X11 credential publisher"); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(FALSE); PA_MODULE_USAGE("display="); @@ -69,16 +69,39 @@ static const char* const valid_modargs[] = { struct userdata { pa_core *core; - pa_x11_wrapper *x11_wrapper; + pa_module *module; + char *id; uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; - int auth_cookie_in_property; + pa_bool_t auth_cookie_in_property; + + pa_x11_wrapper *x11_wrapper; + pa_x11_client *x11_client; }; +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); +} + static int load_key(struct userdata *u, const char*fn) { pa_assert(u); - u->auth_cookie_in_property = 0; + u->auth_cookie_in_property = FALSE; if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) { pa_log_debug("using already loaded auth cookie."); @@ -96,7 +119,7 @@ static int load_key(struct userdata *u, const char*fn) { pa_log_debug("Loading cookie from disk."); if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) - u->auth_cookie_in_property = 1; + u->auth_cookie_in_property = TRUE; return 0; } @@ -117,10 +140,13 @@ int pa__init(pa_module*m) { goto fail; } - m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; + u->module = m; u->id = NULL; - u->auth_cookie_in_property = 0; + u->auth_cookie_in_property = FALSE; + u->x11_client = NULL; + u->x11_wrapper = NULL; if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0) goto fail; @@ -152,7 +178,10 @@ int pa__init(pa_module*m) { pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), 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: @@ -160,6 +189,7 @@ fail: pa_modargs_free(ma); pa__done(m); + return -1; } @@ -171,6 +201,9 @@ void pa__done(pa_module*m) { if (!(u = m->userdata)) return; + if (u->x11_client) + pa_x11_client_free(u->x11_client); + if (u->x11_wrapper) { char t[256]; @@ -185,10 +218,9 @@ void pa__done(pa_module*m) { pa_x11_del_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE"); XSync(pa_x11_wrapper_get_display(u->x11_wrapper), False); } - } - if (u->x11_wrapper) pa_x11_wrapper_unref(u->x11_wrapper); + } if (u->auth_cookie_in_property) pa_authkey_prop_unref(m->core, PA_NATIVE_COOKIE_PROPERTY_NAME); diff --git a/src/modules/module-x11-xsmp.c b/src/modules/module-x11-xsmp.c index e9efa096..9994f99d 100644 --- a/src/modules/module-x11-xsmp.c +++ b/src/modules/module-x11-xsmp.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "module-x11-xsmp-symdef.h" @@ -49,20 +50,37 @@ PA_MODULE_AUTHOR("Lennart Poettering"); PA_MODULE_DESCRIPTION("X11 session management"); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_USAGE("session_manager= display="); -static int ice_in_use = 0; + +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){ - pa_core *c = PA_CORE(client_data); + struct userdata *u = client_data; + pa_assert(u); + + pa_log_debug("Got die message from XSMP."); - pa_log_debug("Got die message from XSM. Exiting..."); + pa_x11_wrapper_kill(u->x11); - pa_core_assert_ref(c); - c->mainloop->quit(c->mainloop, 0); + pa_x11_wrapper_unref(u->x11); + u->x11 = NULL; + + pa_module_unload_request(u->module); } static void save_complete_cb(SmcConn connection, SmPointer client_data) { @@ -86,12 +104,15 @@ static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_fla } static void new_ice_connection(IceConn connection, IcePointer client_data, Bool opening, IcePointer *watch_data) { - pa_core *c = client_data; - - pa_assert(c); + 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); + *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); } @@ -99,12 +120,13 @@ static void new_ice_connection(IceConn connection, IcePointer client_data, Bool int pa__init(pa_module*m) { pa_modargs *ma = NULL; - char t[256], *vendor, *client_id; + char t[256], *vendor, *client_id, *k; SmcCallbacks callbacks; SmProp prop_program, prop_user; SmProp *prop_list[2]; SmPropValue val_program, val_user; - SmcConn connection; + struct userdata *u; + const char *e; pa_assert(m); @@ -114,21 +136,33 @@ int pa__init(pa_module*m) { } IceAddConnectionWatch(new_ice_connection, m->core); - ice_in_use = 1; + 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 (!getenv("SESSION_MANAGER")) { + 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 = m->core; + 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; @@ -136,8 +170,8 @@ int pa__init(pa_module*m) { callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb; callbacks.shutdown_cancelled.client_data = m->core; - if (!(m->userdata = connection = SmcOpenConnection( - NULL, m->core, + if (!(u->connection = SmcOpenConnection( + (char*) e, m->core, SmProtoMajor, SmProtoMinor, SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, &callbacks, NULL, &client_id, @@ -164,9 +198,16 @@ int pa__init(pa_module*m) { prop_user.vals = &val_user; prop_list[1] = &prop_user; - SmcSetProperties(connection, PA_ELEMENTSOF(prop_list), prop_list); + 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); + k = pa_sprintf_malloc("XSMP Session on %s as %s", vendor, client_id); + u->client = pa_client_new(u->core, __FILE__, k); + pa_xfree(k); + + pa_proplist_sets(u->client->proplist, "xsmp.vendor", vendor); + pa_proplist_sets(u->client->proplist, "xsmp.client.id", client_id); - pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(connection), client_id); free(vendor); free(client_id); @@ -184,13 +225,26 @@ fail: } void pa__done(pa_module*m) { + struct userdata *u; + pa_assert(m); - if (m->userdata) - SmcCloseConnection(m->userdata, 0, NULL); + 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 = 0; + ice_in_use = FALSE; } } diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c index 800a9458..36f684dc 100644 --- a/src/pulsecore/x11wrap.c +++ b/src/pulsecore/x11wrap.c @@ -63,7 +63,8 @@ struct pa_x11_wrapper { struct pa_x11_client { PA_LLIST_FIELDS(pa_x11_client); pa_x11_wrapper *wrapper; - int (*callback)(pa_x11_wrapper *w, XEvent *e, void *userdata); + pa_x11_event_cb_t event_cb; + pa_x11_kill_cb_t kill_cb; void *userdata; }; @@ -72,17 +73,23 @@ static void work(pa_x11_wrapper *w) { pa_assert(w); pa_assert(PA_REFCNT_VALUE(w) >= 1); + pa_x11_wrapper_ref(w); + while (XPending(w->display)) { - pa_x11_client *c; + pa_x11_client *c, *n; XEvent e; XNextEvent(w->display, &e); - for (c = w->clients; c; c = c->next) { - pa_assert(c->callback); - if (c->callback(w, &e, c->userdata) != 0) - break; + for (c = w->clients; c; c = n) { + n = c->next; + + if (c->event_cb) + if (c->event_cb(w, &e, c->userdata) != 0) + break; } } + + pa_x11_wrapper_unref(w); } /* IO notification event for the X11 display connection */ @@ -251,7 +258,24 @@ Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w) { return w->display; } -pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata) { +void pa_x11_wrapper_kill(pa_x11_wrapper *w) { + pa_x11_client *c, *n; + + pa_assert(w); + + pa_x11_wrapper_ref(w); + + for (c = w->clients; c; c = n) { + n = c->next; + + if (c->kill_cb) + c->kill_cb(w, c->userdata); + } + + pa_x11_wrapper_unref(w); +} + +pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, pa_x11_event_cb_t event_cb, pa_x11_kill_cb_t kill_cb, void *userdata) { pa_x11_client *c; pa_assert(w); @@ -259,7 +283,8 @@ pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, c = pa_xnew(pa_x11_client, 1); c->wrapper = w; - c->callback = cb; + c->event_cb = event_cb; + c->kill_cb = kill_cb; c->userdata = userdata; PA_LLIST_PREPEND(pa_x11_client, w->clients, c); diff --git a/src/pulsecore/x11wrap.h b/src/pulsecore/x11wrap.h index 9bed2fce..d614c1ab 100644 --- a/src/pulsecore/x11wrap.h +++ b/src/pulsecore/x11wrap.h @@ -30,6 +30,11 @@ typedef struct pa_x11_wrapper pa_x11_wrapper; +typedef struct pa_x11_client pa_x11_client; + +typedef int (*pa_x11_event_cb_t)(pa_x11_wrapper *w, XEvent *e, void *userdata); +typedef void (*pa_x11_kill_cb_t)(pa_x11_wrapper *w, void *userdata); + /* Return the X11 wrapper for this core. In case no wrapper was existant before, allocate a new one */ pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name); @@ -43,10 +48,11 @@ void pa_x11_wrapper_unref(pa_x11_wrapper* w); /* Return the X11 display object for this connection */ Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w); -typedef struct pa_x11_client pa_x11_client; +/* Kill the connection to the X11 display */ +void pa_x11_wrapper_kill(pa_x11_wrapper *w); /* Register an X11 client, that is called for each X11 event */ -pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, int (*cb)(pa_x11_wrapper *w, XEvent *e, void *userdata), void *userdata); +pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, pa_x11_event_cb_t event_cb, pa_x11_kill_cb_t kill_cb, void *userdata); /* Free an X11 client object */ void pa_x11_client_free(pa_x11_client *c); -- cgit