From 050b73912ca0e81a5740b65745d4ba1d450a66ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 6 Aug 2006 16:16:50 +0000 Subject: merge HAL support from Shams E. King git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1187 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 495 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 495 insertions(+) create mode 100644 src/modules/module-hal-detect.c (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c new file mode 100644 index 00000000..1c15a2d1 --- /dev/null +++ b/src/modules/module-hal-detect.c @@ -0,0 +1,495 @@ +/*** + This file is part of PulseAudio. + + 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 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 "dbus-util.h" +#include "module-hal-detect-symdef.h" + +PA_MODULE_AUTHOR("Shahms King") +PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") +PA_MODULE_VERSION(PACKAGE_VERSION) + +static const char* capabilities[] = { "alsa", "oss" }; + +typedef enum { + CAP_ALSA, + CAP_OSS, + CAP_MAX +} capability_t; + +typedef enum { + ALSA_TYPE_SINK, + ALSA_TYPE_SOURCE, + ALSA_TYPE_OTHER, + ALSA_TYPE_MAX +} alsa_type_t; + +struct device { + char *udi; + pa_module *module; +}; + +struct userdata { + pa_core *core; + pa_subscription *sub; + LibHalContext *ctx; + capability_t capability; + pa_dbus_connection *conn; + pa_hashmap *by_udi; + pa_hashmap *by_module; +}; + +struct timerdata { + struct userdata *u; + char *udi; +}; + +static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + char *type; + alsa_type_t t; + + type = libhal_device_get_property_string(ctx, udi, "alsa.type", error); + if (!type || dbus_error_is_set(error)) + return FALSE; + + if (!strcmp(type, "playback")) { + t = ALSA_TYPE_SINK; + } else if (!strcmp(type, "capture")) { + t = ALSA_TYPE_SOURCE; + } else { + t = ALSA_TYPE_OTHER; + } + libhal_free_string(type); + + return t; +} + +static int hal_device_get_alsa_card(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + return libhal_device_get_property_int(ctx, udi, "alsa.card", error); +} + +static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + return libhal_device_get_property_int(ctx, udi, "alsa.device", error); +} + +static void hal_device_free(struct device* d) { + pa_xfree(d->udi); + pa_xfree(d); +} + +static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { + hal_device_free((struct device*) d); +} + +static dbus_bool_t hal_device_add_alsa(struct userdata *u, const char *udi, + DBusError *error) +{ + char args[64]; + alsa_type_t type; + int device, card; + pa_module *m; + struct device *d; + const char *module_name; + + type = hal_device_get_alsa_type(u->ctx, udi, error); + if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) { + return FALSE; + } + + device = hal_device_get_alsa_device(u->ctx, udi, error); + if (dbus_error_is_set(error) || device != 0) + return FALSE; + + card = hal_device_get_alsa_card(u->ctx, udi, error); + if (dbus_error_is_set(error)) + return FALSE; + + module_name = (type == ALSA_TYPE_SINK) ? "module-alsa-sink" + : "module-alsa-source"; + snprintf(args, sizeof(args), "device=hw:%u", card); + if (!(m = pa_module_load(u->core, module_name, args))) + return FALSE; + + d = pa_xmalloc(sizeof(struct device)); + d->udi = pa_xstrdup(udi); + d->module = m; + + pa_hashmap_put(u->by_module, m, d); + pa_hashmap_put(u->by_udi, udi, d); + + return TRUE; +} + +static int hal_device_add_all(struct userdata *u, capability_t capability) +{ + DBusError error; + int i,n,count; + dbus_bool_t r; + char** udis; + const char* cap = capabilities[capability]; + + assert(capability < CAP_MAX); + + pa_log_info(__FILE__": Trying capability %u (%s)", capability, cap); + dbus_error_init(&error); + udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error); + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error finding devices: %s: %s", error.name, + error.message); + dbus_error_free(&error); + return -1; + } + count = 0; + for (i = 0; i < n; ++i) { + switch(capability) { + case CAP_ALSA: + r = hal_device_add_alsa(u, udis[i], &error); + break; + case CAP_OSS: + /* r = hal_device_add_oss(u, udis[i], &error) + * break; */ + case CAP_MAX: + default: + assert(FALSE); + break; + } + + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + error.message); + dbus_error_free(&error); + count = -1; + break; + } + if (r) + ++count; + } + + libhal_free_string_array(udis); + u->capability = capability; + return count; +} + +static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi, + const char* cap, DBusError *error) +{ + dbus_bool_t has_prop; + has_prop = libhal_device_property_exists(ctx, udi, "info.capabilities", + error); + if (!has_prop || dbus_error_is_set(error)) + return FALSE; + + return libhal_device_query_capability(ctx, udi, cap, error); +} + +static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, + const struct timeval *tv, void *userdata) +{ + DBusError error; + struct timerdata *td = (struct timerdata*) userdata; + + dbus_error_init(&error); + if (!libhal_device_exists(td->u->ctx, td->udi, &error)) + goto exit; + + switch(td->u->capability) { + case CAP_ALSA: + hal_device_add_alsa(td->u, td->udi, &error); + break; + case CAP_OSS: + /* hal_device_add_oss(td->u, td->udi, &error); + * break; */ + case CAP_MAX: + default: + /* not reached */ + assert(FALSE); + break; + } + +exit: + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + error.message); + dbus_error_free(&error); + } + + pa_xfree(td->udi); + pa_xfree(td); + ea->time_free(ev); +} + +static void device_added_cb(LibHalContext *ctx, const char *udi) +{ + DBusError error; + struct timeval tv; + dbus_bool_t has_cap; + struct timerdata *t; + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + const char* cap = capabilities[u->capability]; + + pa_log_debug(__FILE__": HAL Device added: %s", udi); + + dbus_error_init(&error); + has_cap = device_has_capability(ctx, udi, cap, &error); + if (dbus_error_is_set(&error)) { + pa_log_error(__FILE__": Error getting capability: %s: %s", error.name, + error.message); + dbus_error_free(&error); + return; + } + + /* skip it */ + if (!has_cap) + return; + + /* actually add the device one second later */ + t = pa_xmalloc(sizeof(struct timerdata)); + t->u = u; + t->udi = pa_xstrdup(udi); + + gettimeofday(&tv, NULL); + tv.tv_sec += 1; + u->core->mainloop->time_new(u->core->mainloop, &tv, + device_added_time_cb, t); +} + +static void device_removed_cb(LibHalContext* ctx, const char *udi) +{ + struct device *d; + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + + pa_log_debug(__FILE__": Device removed: %s", udi); + if ((d = pa_hashmap_remove(u->by_udi, udi))) { + d = pa_hashmap_remove(u->by_module, d->module); + pa_log_debug(__FILE__": Unloading: %s <%s>", d->module->name, d->module->argument); + pa_module_unload_request(d->module); + hal_device_free(d); + } +} + +#if 0 +static void new_capability_cb(LibHalContext *ctx, const char *udi, + const char* capability) +{ +} + +static void lost_capability_cb(LibHalContext *ctx, const char *udi, + const char* capability) +{ +} + +static void property_modified_cb(LibHalContext *ctx, const char *udi, + const char* key, + dbus_bool_t is_removed, + dbus_bool_t is_added) +{ +} +#endif + +static void subscribe_notify_cb(pa_core *c, pa_subscription_event_type_t type, + uint32_t idx, void *userdata) +{ + pa_module *m; + struct device *d; + struct userdata *u = (struct userdata*) userdata; + + /* only listen for module remove events */ + if (type != (PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE)) + return; + + if (!(m = pa_idxset_get_by_index(c->modules, idx))) + return; + + /* we found the module, see if it's one we care about */ + if ((d = pa_hashmap_remove(u->by_module, m))) { + pa_log_debug(__FILE__": Removing module #%u %s: %s", + m->index, m->name, d->udi); + d = pa_hashmap_remove(u->by_udi, d->udi); + hal_device_free(d); + } +} + + +static void pa_hal_context_free(LibHalContext* hal_ctx) +{ + DBusError error; + + dbus_error_init(&error); + libhal_ctx_shutdown(hal_ctx, &error); + libhal_ctx_free(hal_ctx); + + if (dbus_error_is_set(&error)) { + dbus_error_free(&error); + } +} + +static void userdata_free(struct userdata *u) { + pa_hal_context_free(u->ctx); + pa_subscription_free(u->sub); + /* free the hashmap */ + pa_hashmap_free(u->by_module, NULL, NULL); + /* free the devices with the hashmap */ + pa_hashmap_free(u->by_udi, hal_device_free_cb, NULL); + pa_dbus_connection_unref(u->conn); + pa_xfree(u); +} + +static LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn) +{ + DBusError error; + LibHalContext *hal_ctx = NULL; + + dbus_error_init(&error); + if (!(hal_ctx = libhal_ctx_new())) { + pa_log_error(__FILE__": libhal_ctx_new() failed"); + goto fail; + } + + if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) { + pa_log_error(__FILE__": Error establishing DBUS connection: %s: %s", + error.name, error.message); + goto fail; + } + + if (!libhal_ctx_init(hal_ctx, &error)) { + pa_log_error(__FILE__": Couldn't connect to hald: %s: %s", + error.name, error.message); + goto fail; + } + + return hal_ctx; + +fail: + if (hal_ctx) + pa_hal_context_free(hal_ctx); + + if (dbus_error_is_set(&error)) + dbus_error_free(&error); + + return NULL; +} + +int pa__init(pa_core *c, pa_module*m) { + int n; + DBusError error; + pa_dbus_connection *conn; + struct userdata *u = NULL; + LibHalContext *hal_ctx = NULL; + + assert(c); + assert(m); + + dbus_error_init(&error); + if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) { + pa_log_error(__FILE__": Unable to contact DBUS system bus: %s: %s", + error.name, error.message); + dbus_error_free(&error); + return -1; + } + + if (!(hal_ctx = pa_hal_context_new(c, pa_dbus_connection_get(conn)))) { + /* pa_hal_context_new() logs appropriate errors */ + return -1; + } + + u = pa_xmalloc(sizeof(struct userdata)); + u->core = c; + u->ctx = hal_ctx; + u->conn = conn; + u->by_module = pa_hashmap_new(NULL, NULL); + u->by_udi = pa_hashmap_new(pa_idxset_string_hash_func, + pa_idxset_string_compare_func); + u->sub = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_MODULE, + subscribe_notify_cb, (void*) u); + m->userdata = (void*) u; + +#if HAVE_ALSA + if ((n = hal_device_add_all(u, CAP_ALSA)) <= 0) +#endif +#if HAVE_OSS + if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) +#endif + { + pa_log_warn(__FILE__": failed to detect any sound hardware."); + userdata_free(u); + return -1; + } + + libhal_ctx_set_user_data(hal_ctx, (void*) u); + libhal_ctx_set_device_added(hal_ctx, device_added_cb); + libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); + + dbus_error_init(&error); + if (!libhal_device_property_watch_all(hal_ctx, &error)) { + pa_log_error(__FILE__": error monitoring device list: %s: %s", + error.name, error.message); + dbus_error_free(&error); + userdata_free(u); + return -1; + } + + /* + libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); + libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); + libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb); + */ + + pa_log_info(__FILE__": loaded %i modules.", n); + + return 0; +} + + +void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) { + assert (c && m); + + /* free the user data */ + userdata_free(m->userdata); +} -- cgit From d953870564c13bc4742634a17300c58abbf1eadf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 6 Aug 2006 19:14:07 +0000 Subject: * add SVN $Id$ tags * add a const git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1188 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 1c15a2d1..adcb866c 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -1,3 +1,5 @@ +/* $Id$ */ + /*** This file is part of PulseAudio. @@ -50,7 +52,7 @@ PA_MODULE_AUTHOR("Shahms King") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") PA_MODULE_VERSION(PACKAGE_VERSION) -static const char* capabilities[] = { "alsa", "oss" }; +static const char*const capabilities[] = { "alsa", "oss" }; typedef enum { CAP_ALSA, -- cgit From b382df5868db14628bed2d7445706dab5a4bdf58 Mon Sep 17 00:00:00 2001 From: "Shahms E. King" Date: Mon, 7 Aug 2006 20:29:31 +0000 Subject: clean up hal patch to use pa_xnew and timeval compatibility wrappers git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1190 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 67 ++++++++++------------------------------- 1 file changed, 16 insertions(+), 51 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index adcb866c..a35144b0 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -34,11 +34,11 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -68,18 +68,16 @@ typedef enum { } alsa_type_t; struct device { + uint32_t index; char *udi; - pa_module *module; }; struct userdata { pa_core *core; - pa_subscription *sub; LibHalContext *ctx; capability_t capability; pa_dbus_connection *conn; - pa_hashmap *by_udi; - pa_hashmap *by_module; + pa_hashmap *devices; }; struct timerdata { @@ -159,12 +157,11 @@ static dbus_bool_t hal_device_add_alsa(struct userdata *u, const char *udi, if (!(m = pa_module_load(u->core, module_name, args))) return FALSE; - d = pa_xmalloc(sizeof(struct device)); + d = pa_xnew(struct device, 1); d->udi = pa_xstrdup(udi); - d->module = m; + d->index = m->index; - pa_hashmap_put(u->by_module, m, d); - pa_hashmap_put(u->by_udi, udi, d); + pa_hashmap_put(u->devices, udi, d); return TRUE; } @@ -291,13 +288,13 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) if (!has_cap) return; - /* actually add the device one second later */ - t = pa_xmalloc(sizeof(struct timerdata)); + /* actually add the device 1/2 second later */ + t = pa_xnew(struct timerdata, 1); t->u = u; t->udi = pa_xstrdup(udi); - gettimeofday(&tv, NULL); - tv.tv_sec += 1; + pa_gettimeofday(&tv); + pa_timeval_add(&tv, 500000); u->core->mainloop->time_new(u->core->mainloop, &tv, device_added_time_cb, t); } @@ -308,10 +305,8 @@ static void device_removed_cb(LibHalContext* ctx, const char *udi) struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); pa_log_debug(__FILE__": Device removed: %s", udi); - if ((d = pa_hashmap_remove(u->by_udi, udi))) { - d = pa_hashmap_remove(u->by_module, d->module); - pa_log_debug(__FILE__": Unloading: %s <%s>", d->module->name, d->module->argument); - pa_module_unload_request(d->module); + if ((d = pa_hashmap_remove(u->devices, udi))) { + pa_module_unload_by_index(u->core, d->index); hal_device_free(d); } } @@ -335,30 +330,6 @@ static void property_modified_cb(LibHalContext *ctx, const char *udi, } #endif -static void subscribe_notify_cb(pa_core *c, pa_subscription_event_type_t type, - uint32_t idx, void *userdata) -{ - pa_module *m; - struct device *d; - struct userdata *u = (struct userdata*) userdata; - - /* only listen for module remove events */ - if (type != (PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE)) - return; - - if (!(m = pa_idxset_get_by_index(c->modules, idx))) - return; - - /* we found the module, see if it's one we care about */ - if ((d = pa_hashmap_remove(u->by_module, m))) { - pa_log_debug(__FILE__": Removing module #%u %s: %s", - m->index, m->name, d->udi); - d = pa_hashmap_remove(u->by_udi, d->udi); - hal_device_free(d); - } -} - - static void pa_hal_context_free(LibHalContext* hal_ctx) { DBusError error; @@ -374,11 +345,8 @@ static void pa_hal_context_free(LibHalContext* hal_ctx) static void userdata_free(struct userdata *u) { pa_hal_context_free(u->ctx); - pa_subscription_free(u->sub); - /* free the hashmap */ - pa_hashmap_free(u->by_module, NULL, NULL); /* free the devices with the hashmap */ - pa_hashmap_free(u->by_udi, hal_device_free_cb, NULL); + pa_hashmap_free(u->devices, hal_device_free_cb, NULL); pa_dbus_connection_unref(u->conn); pa_xfree(u); } @@ -441,15 +409,12 @@ int pa__init(pa_core *c, pa_module*m) { return -1; } - u = pa_xmalloc(sizeof(struct userdata)); + u = pa_xnew(struct userdata, 1); u->core = c; u->ctx = hal_ctx; u->conn = conn; - u->by_module = pa_hashmap_new(NULL, NULL); - u->by_udi = pa_hashmap_new(pa_idxset_string_hash_func, - pa_idxset_string_compare_func); - u->sub = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_MODULE, - subscribe_notify_cb, (void*) u); + u->devices = pa_hashmap_new(pa_idxset_string_hash_func, + pa_idxset_string_compare_func); m->userdata = (void*) u; #if HAVE_ALSA -- cgit From 7ee7a23408a1dae0ce1655067b26ed49e8e2e11f Mon Sep 17 00:00:00 2001 From: "Shahms E. King" Date: Tue, 8 Aug 2006 19:26:06 +0000 Subject: add HAL support for OSS devices and capability changes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1191 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 175 ++++++++++++++++++++++++++-------------- 1 file changed, 115 insertions(+), 60 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index a35144b0..27c39221 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -85,6 +85,21 @@ struct timerdata { char *udi; }; +static const char* get_capability_name(capability_t cap) { + if (cap >= CAP_MAX) + return NULL; + return capabilities[cap]; +} + +static void hal_device_free(struct device* d) { + pa_xfree(d->udi); + pa_xfree(d); +} + +static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { + hal_device_free((struct device*) d); +} + static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, DBusError *error) { @@ -119,42 +134,98 @@ static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, return libhal_device_get_property_int(ctx, udi, "alsa.device", error); } -static void hal_device_free(struct device* d) { - pa_xfree(d->udi); - pa_xfree(d); -} - -static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { - hal_device_free((struct device*) d); -} - -static dbus_bool_t hal_device_add_alsa(struct userdata *u, const char *udi, +static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, DBusError *error) { char args[64]; alsa_type_t type; int device, card; - pa_module *m; - struct device *d; const char *module_name; type = hal_device_get_alsa_type(u->ctx, udi, error); - if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) { - return FALSE; - } + if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) + return NULL; device = hal_device_get_alsa_device(u->ctx, udi, error); if (dbus_error_is_set(error) || device != 0) - return FALSE; + return NULL; card = hal_device_get_alsa_card(u->ctx, udi, error); if (dbus_error_is_set(error)) - return FALSE; + return NULL; module_name = (type == ALSA_TYPE_SINK) ? "module-alsa-sink" : "module-alsa-source"; snprintf(args, sizeof(args), "device=hw:%u", card); - if (!(m = pa_module_load(u->core, module_name, args))) + return pa_module_load(u->core, module_name, args); +} + +static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, + DBusError *error) +{ + dbus_bool_t rv = FALSE; + char* device; + char* type; + + type = libhal_device_get_property_string(ctx, udi, "oss.type", error); + if (!type || dbus_error_is_set(error)) + return FALSE; + + if (!strcmp(type, "pcm")) { + device = libhal_device_get_property_string(ctx, udi, "oss.device_file", + error); + if (!device || dbus_error_is_set(error)) + goto exit; + + /* hack to ignore /dev/audio style devices */ + if ((device = strrchr(device, '/'))) + rv = (pa_startswith(device + 1, "audio")) ? FALSE : TRUE; + } + +exit: + libhal_free_string(type); + return rv; +} + +static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, + DBusError *error) +{ + char args[128]; + char* device; + + if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error)) + return NULL; + + device = libhal_device_get_property_string(u->ctx, udi, "oss.device_file", + error); + if (!device || dbus_error_is_set(error)) + return NULL; + + snprintf(args, sizeof(args), "device=%s", device); + libhal_free_string(device); + + return pa_module_load(u->core, "module-oss", args); +} + +static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, + DBusError *error) +{ + pa_module* m; + struct device *d; + + switch(u->capability) { + case CAP_ALSA: + m = hal_device_load_alsa(u, udi, error); + break; + case CAP_OSS: + m = hal_device_load_oss(u, udi, error); + break; + default: + assert(FALSE); /* never reached */ + break; + } + + if (!m || dbus_error_is_set(error)) return FALSE; d = pa_xnew(struct device, 1); @@ -172,7 +243,7 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) int i,n,count; dbus_bool_t r; char** udis; - const char* cap = capabilities[capability]; + const char* cap = get_capability_name(capability); assert(capability < CAP_MAX); @@ -186,20 +257,9 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) return -1; } count = 0; + u->capability = capability; for (i = 0; i < n; ++i) { - switch(capability) { - case CAP_ALSA: - r = hal_device_add_alsa(u, udis[i], &error); - break; - case CAP_OSS: - /* r = hal_device_add_oss(u, udis[i], &error) - * break; */ - case CAP_MAX: - default: - assert(FALSE); - break; - } - + r = hal_device_add(u, udis[i], &error); if (dbus_error_is_set(&error)) { pa_log_error(__FILE__": Error adding device: %s: %s", error.name, error.message); @@ -212,7 +272,6 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) } libhal_free_string_array(udis); - u->capability = capability; return count; } @@ -221,7 +280,7 @@ static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi, { dbus_bool_t has_prop; has_prop = libhal_device_property_exists(ctx, udi, "info.capabilities", - error); + error); if (!has_prop || dbus_error_is_set(error)) return FALSE; @@ -235,24 +294,9 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, struct timerdata *td = (struct timerdata*) userdata; dbus_error_init(&error); - if (!libhal_device_exists(td->u->ctx, td->udi, &error)) - goto exit; + if (libhal_device_exists(td->u->ctx, td->udi, &error)) + hal_device_add(td->u, td->udi, &error); - switch(td->u->capability) { - case CAP_ALSA: - hal_device_add_alsa(td->u, td->udi, &error); - break; - case CAP_OSS: - /* hal_device_add_oss(td->u, td->udi, &error); - * break; */ - case CAP_MAX: - default: - /* not reached */ - assert(FALSE); - break; - } - -exit: if (dbus_error_is_set(&error)) { pa_log_error(__FILE__": Error adding device: %s: %s", error.name, error.message); @@ -271,7 +315,7 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) dbus_bool_t has_cap; struct timerdata *t; struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* cap = capabilities[u->capability]; + const char* cap = get_capability_name(u->capability); pa_log_debug(__FILE__": HAL Device added: %s", udi); @@ -311,17 +355,31 @@ static void device_removed_cb(LibHalContext* ctx, const char *udi) } } -#if 0 static void new_capability_cb(LibHalContext *ctx, const char *udi, - const char* capability) + const char* capability) { + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + const char* capname = get_capability_name(u->capability); + + if (capname && !strcmp(capname, capability)) { + /* capability we care about, pretend it's a new device */ + device_added_cb(ctx, udi); + } } static void lost_capability_cb(LibHalContext *ctx, const char *udi, const char* capability) { + struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + const char* capname = get_capability_name(u->capability); + + if (capname && !strcmp(capname, capability)) { + /* capability we care about, pretend it was removed */ + device_removed_cb(ctx, udi); + } } +#if 0 static void property_modified_cb(LibHalContext *ctx, const char *udi, const char* key, dbus_bool_t is_removed, @@ -432,6 +490,9 @@ int pa__init(pa_core *c, pa_module*m) { libhal_ctx_set_user_data(hal_ctx, (void*) u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); + libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); + libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); + /*libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb);*/ dbus_error_init(&error); if (!libhal_device_property_watch_all(hal_ctx, &error)) { @@ -442,12 +503,6 @@ int pa__init(pa_core *c, pa_module*m) { return -1; } - /* - libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); - libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); - libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb); - */ - pa_log_info(__FILE__": loaded %i modules.", n); return 0; -- cgit From 59f1a67cb5f55f57b743667a3a15547fb1fb7cbc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 15:05:02 +0000 Subject: use the copied udi string as hash key for the device table, because the temporary one is freed when the function exits git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1192 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 27c39221..dd30045e 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -232,7 +232,7 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, d->udi = pa_xstrdup(udi); d->index = m->index; - pa_hashmap_put(u->devices, udi, d); + pa_hashmap_put(u->devices, d->udi, d); return TRUE; } -- cgit From dcd3acc0b887dcf3f94569a1984e0217a1ddf581 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 16:29:46 +0000 Subject: remove OSS specific code from module-hal-detect if HAVE_OSS is not set. Same for ALSA git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1195 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index dd30045e..6a430a83 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -52,20 +52,24 @@ PA_MODULE_AUTHOR("Shahms King") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") PA_MODULE_VERSION(PACKAGE_VERSION) -static const char*const capabilities[] = { "alsa", "oss" }; - typedef enum { +#ifdef HAVE_ALSA CAP_ALSA, +#endif +#ifdef HAVE_OSS CAP_OSS, +#endif CAP_MAX } capability_t; -typedef enum { - ALSA_TYPE_SINK, - ALSA_TYPE_SOURCE, - ALSA_TYPE_OTHER, - ALSA_TYPE_MAX -} alsa_type_t; +static const char* const capabilities[CAP_MAX] = { +#ifdef HAVE_ALSA + [CAP_ALSA] = "alsa", +#endif +#ifdef HAVE_OSS + [CAP_OSS] = "oss", +#endif +}; struct device { uint32_t index; @@ -100,6 +104,14 @@ static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { hal_device_free((struct device*) d); } +#ifdef HAVE_ALSA +typedef enum { + ALSA_TYPE_SINK, + ALSA_TYPE_SOURCE, + ALSA_TYPE_OTHER, + ALSA_TYPE_MAX +} alsa_type_t; + static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, DBusError *error) { @@ -160,6 +172,9 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, return pa_module_load(u->core, module_name, args); } +#endif + +#ifdef HAVE_OSS static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, DBusError *error) { @@ -206,6 +221,7 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, return pa_module_load(u->core, "module-oss", args); } +#endif static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, DBusError *error) @@ -214,12 +230,16 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, struct device *d; switch(u->capability) { +#ifdef HAVE_ALSA case CAP_ALSA: m = hal_device_load_alsa(u, udi, error); break; +#endif +#ifdef HAVE_OSS case CAP_OSS: m = hal_device_load_oss(u, udi, error); break; +#endif default: assert(FALSE); /* never reached */ break; @@ -475,10 +495,10 @@ int pa__init(pa_core *c, pa_module*m) { pa_idxset_string_compare_func); m->userdata = (void*) u; -#if HAVE_ALSA +#ifdef HAVE_ALSA if ((n = hal_device_add_all(u, CAP_ALSA)) <= 0) #endif -#if HAVE_OSS +#ifdef HAVE_OSS if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) #endif { -- cgit From 1d7b8e1ba761314a85908dd172b75a02526ff649 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 11 Aug 2006 17:12:54 +0000 Subject: use the HAL UDI for naming input/output devices git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1200 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 6a430a83..0063fdbd 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -104,6 +104,14 @@ static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { hal_device_free((struct device*) d); } +static const char *strip_udi(const char *udi) { + const char *slash; + if ((slash = strrchr(udi, '/'))) + return slash+1; + + return udi; +} + #ifdef HAVE_ALSA typedef enum { ALSA_TYPE_SINK, @@ -166,9 +174,14 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, if (dbus_error_is_set(error)) return NULL; - module_name = (type == ALSA_TYPE_SINK) ? "module-alsa-sink" - : "module-alsa-source"; - snprintf(args, sizeof(args), "device=hw:%u", card); + if (type == ALSA_TYPE_SINK) { + module_name = "module-alsa-sink"; + snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi)); + } else { + module_name = "module-alsa-source"; + snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); + } + return pa_module_load(u->core, module_name, args); } @@ -216,7 +229,7 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, if (!device || dbus_error_is_set(error)) return NULL; - snprintf(args, sizeof(args), "device=%s", device); + snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi)); libhal_free_string(device); return pa_module_load(u->core, "module-oss", args); -- cgit From bb961569eb562b4c92617098627f8092098955d0 Mon Sep 17 00:00:00 2001 From: "Shahms E. King" Date: Sat, 12 Aug 2006 01:17:19 +0000 Subject: increase module argument buffer size to prevent truncating names git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1208 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 0063fdbd..54d139ec 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -157,7 +157,7 @@ static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, DBusError *error) { - char args[64]; + char args[128]; alsa_type_t type; int device, card; const char *module_name; @@ -218,7 +218,7 @@ exit: static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, DBusError *error) { - char args[128]; + char args[256]; char* device; if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error)) -- cgit From c86890d5e794aa5b4b3e39796c705b5922877dfe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 12 Aug 2006 13:18:34 +0000 Subject: * only load an OSS driver for the first device of a sound card, similar to what is done for ALSA. * fix a mem leak git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1217 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 54d139ec..825fa96c 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -192,26 +192,33 @@ static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, DBusError *error) { dbus_bool_t rv = FALSE; - char* device; - char* type; + char* type, *device_file = NULL; + int device; type = libhal_device_get_property_string(ctx, udi, "oss.type", error); if (!type || dbus_error_is_set(error)) return FALSE; - + if (!strcmp(type, "pcm")) { - device = libhal_device_get_property_string(ctx, udi, "oss.device_file", + char *e; + + device = libhal_device_get_property_int(ctx, udi, "oss.device", error); + if (dbus_error_is_set(error) || device != 0) + goto exit; + + device_file = libhal_device_get_property_string(ctx, udi, "oss.device_file", error); - if (!device || dbus_error_is_set(error)) + if (!device_file || dbus_error_is_set(error)) goto exit; /* hack to ignore /dev/audio style devices */ - if ((device = strrchr(device, '/'))) - rv = (pa_startswith(device + 1, "audio")) ? FALSE : TRUE; + if ((e = strrchr(device_file, '/'))) + rv = !pa_startswith(e + 1, "audio"); } exit: libhal_free_string(type); + libhal_free_string(device_file); return rv; } -- cgit From e385d93e5aad6a6fce754c00c804ff1d6a6746d4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:38:40 +0000 Subject: remove all occurences of pa_logXXX(__FILE__": and replace them by pa_logXXX(" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1272 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 825fa96c..8232cd38 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -287,11 +287,11 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) assert(capability < CAP_MAX); - pa_log_info(__FILE__": Trying capability %u (%s)", capability, cap); + pa_log_info("Trying capability %u (%s)", capability, cap); dbus_error_init(&error); udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error finding devices: %s: %s", error.name, + pa_log_error("Error finding devices: %s: %s", error.name, error.message); dbus_error_free(&error); return -1; @@ -301,7 +301,7 @@ static int hal_device_add_all(struct userdata *u, capability_t capability) for (i = 0; i < n; ++i) { r = hal_device_add(u, udis[i], &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + pa_log_error("Error adding device: %s: %s", error.name, error.message); dbus_error_free(&error); count = -1; @@ -338,7 +338,7 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, hal_device_add(td->u, td->udi, &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error adding device: %s: %s", error.name, + pa_log_error("Error adding device: %s: %s", error.name, error.message); dbus_error_free(&error); } @@ -357,12 +357,12 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); const char* cap = get_capability_name(u->capability); - pa_log_debug(__FILE__": HAL Device added: %s", udi); + pa_log_debug("HAL Device added: %s", udi); dbus_error_init(&error); has_cap = device_has_capability(ctx, udi, cap, &error); if (dbus_error_is_set(&error)) { - pa_log_error(__FILE__": Error getting capability: %s: %s", error.name, + pa_log_error("Error getting capability: %s: %s", error.name, error.message); dbus_error_free(&error); return; @@ -388,7 +388,7 @@ static void device_removed_cb(LibHalContext* ctx, const char *udi) struct device *d; struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - pa_log_debug(__FILE__": Device removed: %s", udi); + pa_log_debug("Device removed: %s", udi); if ((d = pa_hashmap_remove(u->devices, udi))) { pa_module_unload_by_index(u->core, d->index); hal_device_free(d); @@ -456,18 +456,18 @@ static LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn) dbus_error_init(&error); if (!(hal_ctx = libhal_ctx_new())) { - pa_log_error(__FILE__": libhal_ctx_new() failed"); + pa_log_error("libhal_ctx_new() failed"); goto fail; } if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) { - pa_log_error(__FILE__": Error establishing DBUS connection: %s: %s", + pa_log_error("Error establishing DBUS connection: %s: %s", error.name, error.message); goto fail; } if (!libhal_ctx_init(hal_ctx, &error)) { - pa_log_error(__FILE__": Couldn't connect to hald: %s: %s", + pa_log_error("Couldn't connect to hald: %s: %s", error.name, error.message); goto fail; } @@ -496,7 +496,7 @@ int pa__init(pa_core *c, pa_module*m) { dbus_error_init(&error); if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) { - pa_log_error(__FILE__": Unable to contact DBUS system bus: %s: %s", + pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message); dbus_error_free(&error); return -1; @@ -522,7 +522,7 @@ int pa__init(pa_core *c, pa_module*m) { if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) #endif { - pa_log_warn(__FILE__": failed to detect any sound hardware."); + pa_log_warn("failed to detect any sound hardware."); userdata_free(u); return -1; } @@ -536,14 +536,14 @@ int pa__init(pa_core *c, pa_module*m) { dbus_error_init(&error); if (!libhal_device_property_watch_all(hal_ctx, &error)) { - pa_log_error(__FILE__": error monitoring device list: %s: %s", + pa_log_error("error monitoring device list: %s: %s", error.name, error.message); dbus_error_free(&error); userdata_free(u); return -1; } - pa_log_info(__FILE__": loaded %i modules.", n); + pa_log_info("loaded %i modules.", n); return 0; } -- cgit From 521daf6f0ac4fa6a2fbfb5d523c0c743342dca2b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 13:43:45 +0000 Subject: Huge trailing whitespace cleanup. Let's keep the tree pure from here on, mmmkay? git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1418 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 8232cd38..eb275ff0 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + 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 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 @@ -58,7 +58,7 @@ typedef enum { #endif #ifdef HAVE_OSS CAP_OSS, -#endif +#endif CAP_MAX } capability_t; @@ -181,7 +181,7 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, module_name = "module-alsa-source"; snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); } - + return pa_module_load(u->core, module_name, args); } @@ -198,7 +198,7 @@ static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, type = libhal_device_get_property_string(ctx, udi, "oss.type", error); if (!type || dbus_error_is_set(error)) return FALSE; - + if (!strcmp(type, "pcm")) { char *e; -- cgit From 06211b7c8fd329137ae9003818543912a87d9898 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Feb 2007 15:35:19 +0000 Subject: Add copyright notices to all relevant files. (based on svn log) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1426 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index eb275ff0..56a3efc1 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2006 Lennart Poettering + Copyright 2006 Shams E. King + 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 of the License, -- cgit From 0b14c026890ee6806971d179a66aee5b03e1d763 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 6 Mar 2007 13:31:29 +0000 Subject: Don't fail if hal doesn't currently contain any devices. (closes #55) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1434 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 56a3efc1..a28b6f0d 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -488,7 +488,6 @@ fail: } int pa__init(pa_core *c, pa_module*m) { - int n; DBusError error; pa_dbus_connection *conn; struct userdata *u = NULL; @@ -519,16 +518,11 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = (void*) u; #ifdef HAVE_ALSA - if ((n = hal_device_add_all(u, CAP_ALSA)) <= 0) + hal_device_add_all(u, CAP_ALSA); #endif #ifdef HAVE_OSS - if ((n = hal_device_add_all(u, CAP_OSS)) <= 0) + hal_device_add_all(u, CAP_OSS); #endif - { - pa_log_warn("failed to detect any sound hardware."); - userdata_free(u); - return -1; - } libhal_ctx_set_user_data(hal_ctx, (void*) u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); -- cgit From 960b5cbd10105df4cd6320e005b73e3c9aa32cc6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 May 2007 23:38:22 +0000 Subject: Fix build and only load OSS xor ALSA modules if both are available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1440 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index a28b6f0d..27cd449e 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -85,6 +85,9 @@ struct userdata { capability_t capability; pa_dbus_connection *conn; pa_hashmap *devices; +#if defined(HAVE_ALSA) && defined(HAVE_OSS) + int use_oss; +#endif }; struct timerdata { @@ -185,6 +188,8 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); } + pa_log_debug("Loading %s with arguments '%s'", module_name, args); + return pa_module_load(u->core, module_name, args); } @@ -242,6 +247,8 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi)); libhal_free_string(device); + pa_log_debug("Loading module-oss with arguments '%s'", args); + return pa_module_load(u->core, "module-oss", args); } #endif @@ -249,7 +256,7 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, DBusError *error) { - pa_module* m; + pa_module* m = NULL; struct device *d; switch(u->capability) { @@ -260,7 +267,10 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, #endif #ifdef HAVE_OSS case CAP_OSS: - m = hal_device_load_oss(u, udi, error); +#ifdef HAVE_ALSA + if (u->use_oss) +#endif + m = hal_device_load_oss(u, udi, error); break; #endif default: @@ -492,6 +502,7 @@ int pa__init(pa_core *c, pa_module*m) { pa_dbus_connection *conn; struct userdata *u = NULL; LibHalContext *hal_ctx = NULL; + int n = 0; assert(c); assert(m); @@ -518,13 +529,26 @@ int pa__init(pa_core *c, pa_module*m) { m->userdata = (void*) u; #ifdef HAVE_ALSA - hal_device_add_all(u, CAP_ALSA); + n = hal_device_add_all(u, CAP_ALSA); #endif +#if defined(HAVE_ALSA) && defined(HAVE_OSS) + u->use_oss = 0; + + if (n <= 0) { +#endif #ifdef HAVE_OSS - hal_device_add_all(u, CAP_OSS); + n += hal_device_add_all(u, CAP_OSS); #endif +#if defined(HAVE_ALSA) && defined(HAVE_OSS) + + /* We found something with OSS, but didn't find anything with + * ALSA. Then let's use only OSS from now on. */ + if (n > 0) + u->use_oss = 1; + } +#endif - libhal_ctx_set_user_data(hal_ctx, (void*) u); + libhal_ctx_set_user_data(hal_ctx, u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); -- cgit From 1e12e0ee8dfdda1632b9c082aba6fc1956813a5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 May 2007 17:24:48 +0000 Subject: Kill spaces on EOL git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1465 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 27cd449e..1f48a452 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -87,7 +87,7 @@ struct userdata { pa_hashmap *devices; #if defined(HAVE_ALSA) && defined(HAVE_OSS) int use_oss; -#endif +#endif }; struct timerdata { @@ -269,7 +269,7 @@ static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, case CAP_OSS: #ifdef HAVE_ALSA if (u->use_oss) -#endif +#endif m = hal_device_load_oss(u, udi, error); break; #endif @@ -533,9 +533,9 @@ int pa__init(pa_core *c, pa_module*m) { #endif #if defined(HAVE_ALSA) && defined(HAVE_OSS) u->use_oss = 0; - + if (n <= 0) { -#endif +#endif #ifdef HAVE_OSS n += hal_device_add_all(u, CAP_OSS); #endif @@ -546,7 +546,7 @@ int pa__init(pa_core *c, pa_module*m) { if (n > 0) u->use_oss = 1; } -#endif +#endif libhal_ctx_set_user_data(hal_ctx, u); libhal_ctx_set_device_added(hal_ctx, device_added_cb); -- cgit From a67c21f093202f142438689d3f7cfbdf4ea82eea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 28 Oct 2007 19:13:50 +0000 Subject: merge 'lennart' branch back into trunk. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 858 ++++++++++++++++++++++++++-------------- 1 file changed, 565 insertions(+), 293 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 1f48a452..a8ca7df3 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -1,25 +1,25 @@ /* $Id$ */ /*** - This file is part of PulseAudio. + This file is part of PulseAudio. - Copyright 2006 Lennart Poettering - Copyright 2006 Shams E. King + Copyright 2006 Lennart Poettering + Copyright 2006 Shams E. King - 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 of the License, - or (at your option) any later version. + 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 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. + 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. + 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 @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -45,6 +44,9 @@ #include #include #include +#include +#include +#include #include @@ -54,40 +56,27 @@ PA_MODULE_AUTHOR("Shahms King") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") PA_MODULE_VERSION(PACKAGE_VERSION) - -typedef enum { -#ifdef HAVE_ALSA - CAP_ALSA, -#endif -#ifdef HAVE_OSS - CAP_OSS, -#endif - CAP_MAX -} capability_t; - -static const char* const capabilities[CAP_MAX] = { -#ifdef HAVE_ALSA - [CAP_ALSA] = "alsa", -#endif -#ifdef HAVE_OSS - [CAP_OSS] = "oss", +#if defined(HAVE_ALSA) && defined(HAVE_OSS) +PA_MODULE_USAGE("api=") +#elif defined(HAVE_ALSA) +PA_MODULE_USAGE("api=") +#elif defined(HAVE_OSS) +PA_MODULE_USAGE("api=") #endif -}; struct device { uint32_t index; char *udi; + char *sink_name, *source_name; + int acl_race_fix; }; struct userdata { pa_core *core; - LibHalContext *ctx; - capability_t capability; - pa_dbus_connection *conn; + LibHalContext *context; + pa_dbus_connection *connection; pa_hashmap *devices; -#if defined(HAVE_ALSA) && defined(HAVE_OSS) - int use_oss; -#endif + const char *capability; }; struct timerdata { @@ -95,23 +84,30 @@ struct timerdata { char *udi; }; -static const char* get_capability_name(capability_t cap) { - if (cap >= CAP_MAX) - return NULL; - return capabilities[cap]; -} +#define CAPABILITY_ALSA "alsa" +#define CAPABILITY_OSS "oss" + +static const char* const valid_modargs[] = { + "api", + NULL +}; static void hal_device_free(struct device* d) { + pa_assert(d); + pa_xfree(d->udi); + pa_xfree(d->sink_name); + pa_xfree(d->source_name); pa_xfree(d); } static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { - hal_device_free((struct device*) d); + hal_device_free(d); } static const char *strip_udi(const char *udi) { const char *slash; + if ((slash = strrchr(udi, '/'))) return slash+1; @@ -119,6 +115,7 @@ static const char *strip_udi(const char *udi) { } #ifdef HAVE_ALSA + typedef enum { ALSA_TYPE_SINK, ALSA_TYPE_SOURCE, @@ -126,234 +123,297 @@ typedef enum { ALSA_TYPE_MAX } alsa_type_t; -static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, - DBusError *error) -{ +static alsa_type_t hal_alsa_device_get_type(LibHalContext *context, const char *udi, DBusError *error) { char *type; alsa_type_t t; - type = libhal_device_get_property_string(ctx, udi, "alsa.type", error); - if (!type || dbus_error_is_set(error)) - return FALSE; + if (!(type = libhal_device_get_property_string(context, udi, "alsa.type", error))) + return ALSA_TYPE_OTHER; - if (!strcmp(type, "playback")) { + if (!strcmp(type, "playback")) t = ALSA_TYPE_SINK; - } else if (!strcmp(type, "capture")) { + else if (!strcmp(type, "capture")) t = ALSA_TYPE_SOURCE; - } else { + else t = ALSA_TYPE_OTHER; - } + libhal_free_string(type); return t; } -static int hal_device_get_alsa_card(LibHalContext *ctx, const char *udi, - DBusError *error) -{ - return libhal_device_get_property_int(ctx, udi, "alsa.card", error); -} +static int hal_alsa_device_is_modem(LibHalContext *context, const char *udi, DBusError *error) { + char *class; + int r; + + if (!(class = libhal_device_get_property_string(context, udi, "alsa.pcm_class", error))) + return 0; + + r = strcmp(class, "modem") == 0; + pa_xfree(class); -static int hal_device_get_alsa_device(LibHalContext *ctx, const char *udi, - DBusError *error) -{ - return libhal_device_get_property_int(ctx, udi, "alsa.device", error); + return r; } -static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, - DBusError *error) -{ - char args[128]; +static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char **sink_name, char **source_name) { + char *args; alsa_type_t type; int device, card; const char *module_name; + DBusError error; + pa_module *m; - type = hal_device_get_alsa_type(u->ctx, udi, error); - if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) - return NULL; + dbus_error_init(&error); - device = hal_device_get_alsa_device(u->ctx, udi, error); - if (dbus_error_is_set(error) || device != 0) - return NULL; + pa_assert(u); + pa_assert(sink_name); + pa_assert(source_name); - card = hal_device_get_alsa_card(u->ctx, udi, error); - if (dbus_error_is_set(error)) - return NULL; + *sink_name = *source_name = NULL; + + type = hal_alsa_device_get_type(u->context, udi, &error); + if (dbus_error_is_set(&error) || type == ALSA_TYPE_OTHER) + goto fail; + + device = libhal_device_get_property_int(u->context, udi, "alsa.device", &error); + if (dbus_error_is_set(&error) || device != 0) + goto fail; + + card = libhal_device_get_property_int(u->context, udi, "alsa.card", &error); + if (dbus_error_is_set(&error)) + goto fail; + + if (hal_alsa_device_is_modem(u->context, udi, &error)) + goto fail; if (type == ALSA_TYPE_SINK) { + *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi)); + module_name = "module-alsa-sink"; - snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi)); + args = pa_sprintf_malloc("device=hw:%u sink_name=%s", card, *sink_name); } else { + *source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi)); + module_name = "module-alsa-source"; - snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi)); + args = pa_sprintf_malloc("device=hw:%u source_name=%s", card, *source_name); } pa_log_debug("Loading %s with arguments '%s'", module_name, args); - return pa_module_load(u->core, module_name, args); + m = pa_module_load(u->core, module_name, args); + + pa_xfree(args); + + if (!m) { + pa_xfree(*sink_name); + pa_xfree(*source_name); + *sink_name = *source_name = NULL; + } + + return m; + +fail: + if (dbus_error_is_set(&error)) { + pa_log_error("D-Bus error while parsing ALSA data: %s: %s", error.name, error.message); + dbus_error_free(&error); + } + + return NULL; } #endif #ifdef HAVE_OSS -static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi, - DBusError *error) -{ - dbus_bool_t rv = FALSE; - char* type, *device_file = NULL; + +static int hal_oss_device_is_pcm(LibHalContext *context, const char *udi, DBusError *error) { + char *class = NULL, *dev = NULL, *e; int device; + int r = 0; - type = libhal_device_get_property_string(ctx, udi, "oss.type", error); - if (!type || dbus_error_is_set(error)) - return FALSE; + class = libhal_device_get_property_string(context, udi, "oss.type", error); + if (dbus_error_is_set(error) || !class) + goto finish; - if (!strcmp(type, "pcm")) { - char *e; + if (strcmp(class, "pcm")) + goto finish; - device = libhal_device_get_property_int(ctx, udi, "oss.device", error); - if (dbus_error_is_set(error) || device != 0) - goto exit; + dev = libhal_device_get_property_string(context, udi, "oss.device_file", error); + if (dbus_error_is_set(error) || !dev) + goto finish; - device_file = libhal_device_get_property_string(ctx, udi, "oss.device_file", - error); - if (!device_file || dbus_error_is_set(error)) - goto exit; + if ((e = strrchr(dev, '/'))) + if (pa_startswith(e + 1, "audio")) + goto finish; - /* hack to ignore /dev/audio style devices */ - if ((e = strrchr(device_file, '/'))) - rv = !pa_startswith(e + 1, "audio"); - } + device = libhal_device_get_property_int(context, udi, "oss.device", error); + if (dbus_error_is_set(error) || device != 0) + goto finish; -exit: - libhal_free_string(type); - libhal_free_string(device_file); - return rv; + r = 1; + +finish: + + libhal_free_string(class); + libhal_free_string(dev); + + return r; } -static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, - DBusError *error) -{ - char args[256]; +static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, char **sink_name, char **source_name) { + char* args; char* device; + DBusError error; + pa_module *m; - if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error)) - return NULL; + dbus_error_init(&error); - device = libhal_device_get_property_string(u->ctx, udi, "oss.device_file", - error); - if (!device || dbus_error_is_set(error)) - return NULL; + pa_assert(u); + pa_assert(sink_name); + pa_assert(source_name); + + *sink_name = *source_name = NULL; - snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi)); + if (!hal_oss_device_is_pcm(u->context, udi, &error) || dbus_error_is_set(&error)) + goto fail; + + device = libhal_device_get_property_string(u->context, udi, "oss.device_file", &error); + if (!device || dbus_error_is_set(&error)) + goto fail; + + *sink_name = pa_sprintf_malloc("oss_output.%s", strip_udi(udi)); + *source_name = pa_sprintf_malloc("oss_input.%s", strip_udi(udi)); + + args = pa_sprintf_malloc("device=%s sink_name=%s source_name=%s", device, *sink_name, *source_name); libhal_free_string(device); pa_log_debug("Loading module-oss with arguments '%s'", args); + m = pa_module_load(u->core, "module-oss", args); + pa_xfree(args); + + if (!m) { + pa_xfree(*sink_name); + pa_xfree(*source_name); + *sink_name = *source_name = NULL; + } + + return m; + +fail: + if (dbus_error_is_set(&error)) { + pa_log_error("D-Bus error while parsing OSS data: %s: %s", error.name, error.message); + dbus_error_free(&error); + } - return pa_module_load(u->core, "module-oss", args); + return NULL; } #endif -static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, - DBusError *error) -{ +static struct device* hal_device_add(struct userdata *u, const char *udi) { pa_module* m = NULL; struct device *d; + char *sink_name = NULL, *source_name = NULL; + + pa_assert(u); + pa_assert(u->capability); + pa_assert(!pa_hashmap_get(u->devices, udi)); - switch(u->capability) { #ifdef HAVE_ALSA - case CAP_ALSA: - m = hal_device_load_alsa(u, udi, error); - break; + if (strcmp(u->capability, CAPABILITY_ALSA) == 0) + m = hal_device_load_alsa(u, udi, &sink_name, &source_name); #endif #ifdef HAVE_OSS - case CAP_OSS: -#ifdef HAVE_ALSA - if (u->use_oss) -#endif - m = hal_device_load_oss(u, udi, error); - break; + if (strcmp(u->capability, CAPABILITY_OSS) == 0) + m = hal_device_load_oss(u, udi, &sink_name, &source_name); #endif - default: - assert(FALSE); /* never reached */ - break; - } - if (!m || dbus_error_is_set(error)) - return FALSE; + if (!m) + return NULL; d = pa_xnew(struct device, 1); + d->acl_race_fix = 0; d->udi = pa_xstrdup(udi); d->index = m->index; - + d->sink_name = sink_name; + d->source_name = source_name; pa_hashmap_put(u->devices, d->udi, d); - return TRUE; + return d; } -static int hal_device_add_all(struct userdata *u, capability_t capability) -{ +static int hal_device_add_all(struct userdata *u, const char *capability) { DBusError error; - int i,n,count; - dbus_bool_t r; + int i, n, count = 0; char** udis; - const char* cap = get_capability_name(capability); - assert(capability < CAP_MAX); + pa_assert(u); - pa_log_info("Trying capability %u (%s)", capability, cap); dbus_error_init(&error); - udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error); + + if (u->capability && strcmp(u->capability, capability) != 0) + return 0; + + pa_log_info("Trying capability %s", capability); + + udis = libhal_find_device_by_capability(u->context, capability, &n, &error); if (dbus_error_is_set(&error)) { - pa_log_error("Error finding devices: %s: %s", error.name, - error.message); + pa_log_error("Error finding devices: %s: %s", error.name, error.message); dbus_error_free(&error); return -1; } - count = 0; - u->capability = capability; - for (i = 0; i < n; ++i) { - r = hal_device_add(u, udis[i], &error); - if (dbus_error_is_set(&error)) { - pa_log_error("Error adding device: %s: %s", error.name, - error.message); - dbus_error_free(&error); - count = -1; - break; + + if (n > 0) { + u->capability = capability; + + for (i = 0; i < n; i++) { + struct device *d; + + if (!(d = hal_device_add(u, udis[i]))) + pa_log_debug("Not loaded device %s", udis[i]); + else { + if (d->sink_name) + pa_scache_play_item_by_name(u->core, "pulse-coldplug", d->sink_name, PA_VOLUME_NORM, 0); + count++; + } } - if (r) - ++count; } libhal_free_string_array(udis); return count; } -static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi, - const char* cap, DBusError *error) -{ +static dbus_bool_t device_has_capability(LibHalContext *context, const char *udi, const char* cap, DBusError *error){ dbus_bool_t has_prop; - has_prop = libhal_device_property_exists(ctx, udi, "info.capabilities", - error); + + has_prop = libhal_device_property_exists(context, udi, "info.capabilities", error); if (!has_prop || dbus_error_is_set(error)) return FALSE; - return libhal_device_query_capability(ctx, udi, cap, error); + return libhal_device_query_capability(context, udi, cap, error); } -static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, - const struct timeval *tv, void *userdata) -{ +static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const struct timeval *tv, void *userdata) { DBusError error; - struct timerdata *td = (struct timerdata*) userdata; + struct timerdata *td = userdata; dbus_error_init(&error); - if (libhal_device_exists(td->u->ctx, td->udi, &error)) - hal_device_add(td->u, td->udi, &error); - if (dbus_error_is_set(&error)) { - pa_log_error("Error adding device: %s: %s", error.name, - error.message); - dbus_error_free(&error); + if (!pa_hashmap_get(td->u->devices, td->udi)) { + int b; + struct device *d; + + b = libhal_device_exists(td->u->context, td->udi, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error adding device: %s: %s", error.name, error.message); + dbus_error_free(&error); + } else if (b) { + if (!(d = hal_device_add(td->u, td->udi))) + pa_log_debug("Not loaded device %s", td->udi); + else { + if (d->sink_name) + pa_scache_play_item_by_name(td->u->core, "pulse-hotplug", d->sink_name, PA_VOLUME_NORM, 0); + } + } } pa_xfree(td->udi); @@ -361,28 +421,68 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, ea->time_free(ev); } -static void device_added_cb(LibHalContext *ctx, const char *udi) -{ +static void device_added_cb(LibHalContext *context, const char *udi) { DBusError error; struct timeval tv; - dbus_bool_t has_cap; struct timerdata *t; - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* cap = get_capability_name(u->capability); + struct userdata *u; + int good = 0; + + pa_assert_se(u = libhal_ctx_get_user_data(context)); + + if (pa_hashmap_get(u->devices, udi)) + return; pa_log_debug("HAL Device added: %s", udi); dbus_error_init(&error); - has_cap = device_has_capability(ctx, udi, cap, &error); - if (dbus_error_is_set(&error)) { - pa_log_error("Error getting capability: %s: %s", error.name, - error.message); - dbus_error_free(&error); - return; + + if (u->capability) { + + good = device_has_capability(context, udi, u->capability, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error getting capability: %s: %s", error.name, error.message); + dbus_error_free(&error); + return; + } + + } else { + +#ifdef HAVE_ALSA + good = device_has_capability(context, udi, CAPABILITY_ALSA, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error getting capability: %s: %s", error.name, error.message); + dbus_error_free(&error); + return; + } + + if (good) + u->capability = CAPABILITY_ALSA; +#endif +#if defined(HAVE_OSS) && defined(HAVE_ALSA) + if (!good) { +#endif +#ifdef HAS_OSS + good = device_has_capability(context, udi, CAPABILITY_OSS, &error); + + if (dbus_error_is_set(&error)) { + pa_log_error("Error getting capability: %s: %s", error.name, error.message); + dbus_error_free(&error); + return; + } + + if (good) + u->capability = CAPABILITY_OSS; + +#endif +#if defined(HAVE_OSS) && defined(HAVE_ALSA) + } +#endif } - /* skip it */ - if (!has_cap) + if (!good) return; /* actually add the device 1/2 second later */ @@ -392,187 +492,359 @@ static void device_added_cb(LibHalContext *ctx, const char *udi) pa_gettimeofday(&tv); pa_timeval_add(&tv, 500000); - u->core->mainloop->time_new(u->core->mainloop, &tv, - device_added_time_cb, t); + u->core->mainloop->time_new(u->core->mainloop, &tv, device_added_time_cb, t); } -static void device_removed_cb(LibHalContext* ctx, const char *udi) -{ +static void device_removed_cb(LibHalContext* context, const char *udi) { struct device *d; - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); + struct userdata *u; + + pa_assert_se(u = libhal_ctx_get_user_data(context)); pa_log_debug("Device removed: %s", udi); + if ((d = pa_hashmap_remove(u->devices, udi))) { pa_module_unload_by_index(u->core, d->index); hal_device_free(d); } } -static void new_capability_cb(LibHalContext *ctx, const char *udi, - const char* capability) -{ - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* capname = get_capability_name(u->capability); +static void new_capability_cb(LibHalContext *context, const char *udi, const char* capability) { + struct userdata *u; + + pa_assert_se(u = libhal_ctx_get_user_data(context)); - if (capname && !strcmp(capname, capability)) { + if (!u->capability || strcmp(u->capability, capability) == 0) /* capability we care about, pretend it's a new device */ - device_added_cb(ctx, udi); - } + device_added_cb(context, udi); } -static void lost_capability_cb(LibHalContext *ctx, const char *udi, - const char* capability) -{ - struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); - const char* capname = get_capability_name(u->capability); +static void lost_capability_cb(LibHalContext *context, const char *udi, const char* capability) { + struct userdata *u; - if (capname && !strcmp(capname, capability)) { - /* capability we care about, pretend it was removed */ - device_removed_cb(ctx, udi); - } -} + pa_assert_se(u = libhal_ctx_get_user_data(context)); -#if 0 -static void property_modified_cb(LibHalContext *ctx, const char *udi, - const char* key, - dbus_bool_t is_removed, - dbus_bool_t is_added) -{ + if (u->capability && strcmp(u->capability, capability) == 0) + /* capability we care about, pretend it was removed */ + device_removed_cb(context, udi); } -#endif -static void pa_hal_context_free(LibHalContext* hal_ctx) -{ +static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) { + struct userdata*u = userdata; DBusError error; + pa_assert(bus); + pa_assert(message); + pa_assert(u); + dbus_error_init(&error); - libhal_ctx_shutdown(hal_ctx, &error); - libhal_ctx_free(hal_ctx); - if (dbus_error_is_set(&error)) { - dbus_error_free(&error); + pa_log_debug("dbus: interface=%s, path=%s, member=%s\n", + dbus_message_get_interface(message), + dbus_message_get_path(message), + dbus_message_get_member(message)); + + if (dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLAdded") || + dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLRemoved")) { + uint32_t uid; + int suspend = strcmp(dbus_message_get_member(message), "ACLRemoved") == 0; + + if (!dbus_message_get_args(message, &error, DBUS_TYPE_UINT32, &uid, DBUS_TYPE_INVALID) || dbus_error_is_set(&error)) { + pa_log_error("Failed to parse ACL message: %s: %s", error.name, error.message); + goto finish; + } + + if (uid == getuid() || uid == geteuid()) { + struct device *d; + const char *udi; + + udi = dbus_message_get_path(message); + + if ((d = pa_hashmap_get(u->devices, udi))) { + int send_acl_race_fix_message = 0; + + d->acl_race_fix = 0; + + if (d->sink_name) { + pa_sink *sink; + + if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) { + int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED; + + if (prev_suspended && !suspend) { + /* resume */ + if (pa_sink_suspend(sink, 0) >= 0) + pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0); + else + d->acl_race_fix = 1; + + } else if (!prev_suspended && suspend) { + /* suspend */ + if (pa_sink_suspend(sink, 1) >= 0) + send_acl_race_fix_message = 1; + } + } + } + + if (d->source_name) { + pa_source *source; + + if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0))) { + int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED; + + if (prev_suspended && !suspend) { + /* resume */ + if (pa_source_suspend(source, 0) < 0) + d->acl_race_fix = 1; + + } else if (!prev_suspended && suspend) { + /* suspend */ + if (pa_source_suspend(source, 0) >= 0) + send_acl_race_fix_message = 1; + } + } + } + + if (send_acl_race_fix_message) { + DBusMessage *msg; + msg = dbus_message_new_signal(udi, "org.pulseaudio.Server", "DirtyGiveUpMessage"); + dbus_connection_send(pa_dbus_connection_get(u->connection), msg, NULL); + dbus_message_unref(msg); + } + + } else if (!suspend) + device_added_cb(u->context, udi); + } + + } else if (dbus_message_is_signal(message, "org.pulseaudio.Server", "DirtyGiveUpMessage")) { + /* We use this message to avoid a dirty race condition when we + get an ACLAdded message before the previously owning PA + sever has closed the device. We can remove this as + soon as HAL learns frevoke() */ + + const char *udi; + struct device *d; + + udi = dbus_message_get_path(message); + + if ((d = pa_hashmap_get(u->devices, udi)) && d->acl_race_fix) { + pa_log_debug("Got dirty give up message for '%s', trying resume ...", udi); + + d->acl_race_fix = 0; + + if (d->sink_name) { + pa_sink *sink; + + if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0))) { + + int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED; + + if (prev_suspended) { + /* resume */ + if (pa_sink_suspend(sink, 0) >= 0) + pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0); + } + } + } + + if (d->source_name) { + pa_source *source; + + if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0))) { + + int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED; + + if (prev_suspended) + pa_source_suspend(source, 0); + } + } + + } else + /* Yes, we don't check the UDI for validity, but hopefully HAL will */ + device_added_cb(u->context, udi); } + +finish: + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_HANDLED; } -static void userdata_free(struct userdata *u) { - pa_hal_context_free(u->ctx); - /* free the devices with the hashmap */ - pa_hashmap_free(u->devices, hal_device_free_cb, NULL); - pa_dbus_connection_unref(u->conn); - pa_xfree(u); +static void hal_context_free(LibHalContext* hal_context) { + DBusError error; + + dbus_error_init(&error); + + libhal_ctx_shutdown(hal_context, &error); + libhal_ctx_free(hal_context); + + dbus_error_free(&error); } -static LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn) -{ +static LibHalContext* hal_context_new(pa_core* c, DBusConnection *conn) { DBusError error; - LibHalContext *hal_ctx = NULL; + LibHalContext *hal_context = NULL; dbus_error_init(&error); - if (!(hal_ctx = libhal_ctx_new())) { + + if (!(hal_context = libhal_ctx_new())) { pa_log_error("libhal_ctx_new() failed"); goto fail; } - if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) { - pa_log_error("Error establishing DBUS connection: %s: %s", - error.name, error.message); + if (!libhal_ctx_set_dbus_connection(hal_context, conn)) { + pa_log_error("Error establishing DBUS connection: %s: %s", error.name, error.message); goto fail; } - if (!libhal_ctx_init(hal_ctx, &error)) { - pa_log_error("Couldn't connect to hald: %s: %s", - error.name, error.message); + if (!libhal_ctx_init(hal_context, &error)) { + pa_log_error("Couldn't connect to hald: %s: %s", error.name, error.message); goto fail; } - return hal_ctx; + return hal_context; fail: - if (hal_ctx) - pa_hal_context_free(hal_ctx); + if (hal_context) + hal_context_free(hal_context); - if (dbus_error_is_set(&error)) - dbus_error_free(&error); + dbus_error_free(&error); return NULL; } -int pa__init(pa_core *c, pa_module*m) { +int pa__init(pa_module*m) { DBusError error; pa_dbus_connection *conn; struct userdata *u = NULL; - LibHalContext *hal_ctx = NULL; + LibHalContext *hal_context = NULL; int n = 0; + pa_modargs *ma; + const char *api; - assert(c); - assert(m); + pa_assert(m); dbus_error_init(&error); - if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) { - pa_log_error("Unable to contact DBUS system bus: %s: %s", - error.name, error.message); - dbus_error_free(&error); - return -1; + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log("Failed to parse module arguments"); + goto fail; } - if (!(hal_ctx = pa_hal_context_new(c, pa_dbus_connection_get(conn)))) { + if ((api = pa_modargs_get_value(ma, "api", NULL))) { + int good = 0; + +#ifdef HAVE_ALSA + if (strcmp(api, CAPABILITY_ALSA) == 0) { + good = 1; + api = CAPABILITY_ALSA; + } +#endif +#ifdef HAVE_OSS + if (strcmp(api, CAPABILITY_OSS) == 0) { + good = 1; + api = CAPABILITY_OSS; + } +#endif + + if (!good) { + pa_log_error("Invalid API specification."); + goto fail; + } + } + + if (!(conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) { + if (conn) + pa_dbus_connection_unref(conn); + pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message); + goto fail; + } + + if (!(hal_context = hal_context_new(m->core, pa_dbus_connection_get(conn)))) { /* pa_hal_context_new() logs appropriate errors */ - return -1; + pa_dbus_connection_unref(conn); + goto fail; } u = pa_xnew(struct userdata, 1); - u->core = c; - u->ctx = hal_ctx; - u->conn = conn; - u->devices = pa_hashmap_new(pa_idxset_string_hash_func, - pa_idxset_string_compare_func); - m->userdata = (void*) u; + u->core = m->core; + u->context = hal_context; + u->connection = conn; + u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); + u->capability = api; + m->userdata = u; #ifdef HAVE_ALSA - n = hal_device_add_all(u, CAP_ALSA); + n = hal_device_add_all(u, CAPABILITY_ALSA); #endif #if defined(HAVE_ALSA) && defined(HAVE_OSS) - u->use_oss = 0; - - if (n <= 0) { + if (n <= 0) #endif #ifdef HAVE_OSS - n += hal_device_add_all(u, CAP_OSS); + n += hal_device_add_all(u, CAPABILITY_OSS); #endif -#if defined(HAVE_ALSA) && defined(HAVE_OSS) - /* We found something with OSS, but didn't find anything with - * ALSA. Then let's use only OSS from now on. */ - if (n > 0) - u->use_oss = 1; + libhal_ctx_set_user_data(hal_context, u); + libhal_ctx_set_device_added(hal_context, device_added_cb); + libhal_ctx_set_device_removed(hal_context, device_removed_cb); + libhal_ctx_set_device_new_capability(hal_context, new_capability_cb); + libhal_ctx_set_device_lost_capability(hal_context, lost_capability_cb); + + if (!libhal_device_property_watch_all(hal_context, &error)) { + pa_log_error("Error monitoring device list: %s: %s", error.name, error.message); + goto fail; } -#endif - libhal_ctx_set_user_data(hal_ctx, u); - libhal_ctx_set_device_added(hal_ctx, device_added_cb); - libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); - libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); - libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); - /*libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb);*/ + if (!dbus_connection_add_filter(pa_dbus_connection_get(conn), filter_cb, u, NULL)) { + pa_log_error("Failed to add filter function"); + goto fail; + } - dbus_error_init(&error); - if (!libhal_device_property_watch_all(hal_ctx, &error)) { - pa_log_error("error monitoring device list: %s: %s", - error.name, error.message); - dbus_error_free(&error); - userdata_free(u); - return -1; + dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error); + if (dbus_error_is_set(&error)) { + pa_log_error("Unable to subscribe to HAL ACL signals: %s: %s", error.name, error.message); + goto fail; + } + + dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',interface='org.pulseaudio.Server'", &error); + if (dbus_error_is_set(&error)) { + pa_log_error("Unable to subscribe to PulseAudio signals: %s: %s", error.name, error.message); + goto fail; } - pa_log_info("loaded %i modules.", n); + pa_log_info("Loaded %i modules.", n); + + pa_modargs_free(ma); return 0; + +fail: + if (ma) + pa_modargs_free(ma); + + dbus_error_free(&error); + pa__done(m); + + return -1; } -void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) { - assert (c && m); +void pa__done(pa_module *m) { + struct userdata *u; + + pa_assert(m); + + if (!(u = m->userdata)) + return; + + if (u->context) + hal_context_free(u->context); - /* free the user data */ - userdata_free(m->userdata); + if (u->devices) + pa_hashmap_free(u->devices, hal_device_free_cb, NULL); + + if (u->connection) + pa_dbus_connection_unref(u->connection); + + pa_xfree(u); } -- cgit From e313fe1b3d0d9f9945c41c151d72edbe9cf1ec54 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 9 Nov 2007 18:25:40 +0000 Subject: tag modules that may only be loaded once at most especially, and enforce that in the module loader git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2043 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index a8ca7df3..00b66c16 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -53,15 +53,16 @@ #include "dbus-util.h" #include "module-hal-detect-symdef.h" -PA_MODULE_AUTHOR("Shahms King") -PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") -PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_AUTHOR("Shahms King"); +PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers"); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(TRUE); #if defined(HAVE_ALSA) && defined(HAVE_OSS) -PA_MODULE_USAGE("api=") +PA_MODULE_USAGE("api="); #elif defined(HAVE_ALSA) -PA_MODULE_USAGE("api=") +PA_MODULE_USAGE("api="); #elif defined(HAVE_OSS) -PA_MODULE_USAGE("api=") +PA_MODULE_USAGE("api="); #endif struct device { -- cgit From d17bb53d3ebfbd7046719400264bd87830c140d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 13 Nov 2007 17:37:44 +0000 Subject: Completely rework ALSA device selection code: choose the device to open depending on the requested number of channels and channel map. In most cases it will now suffice to set default-channels=6 to enable 5.1 sound for all devices that support it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2050 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-hal-detect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/modules/module-hal-detect.c') diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index 00b66c16..832bc73e 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -191,12 +191,12 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi)); module_name = "module-alsa-sink"; - args = pa_sprintf_malloc("device=hw:%u sink_name=%s", card, *sink_name); + args = pa_sprintf_malloc("device_id=%u sink_name=%s", card, *sink_name); } else { *source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi)); module_name = "module-alsa-source"; - args = pa_sprintf_malloc("device=hw:%u source_name=%s", card, *source_name); + args = pa_sprintf_malloc("device_id=%u source_name=%s", card, *source_name); } pa_log_debug("Loading %s with arguments '%s'", module_name, args); -- cgit