modernize module-hal-detect.c and check for ALSA pcm_class != modem

git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1594 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2007-08-08 23:49:17 +00:00
parent 26a024622c
commit a69f4705c5

View file

@ -1,25 +1,25 @@
/* $Id$ */ /* $Id$ */
/*** /***
This file is part of PulseAudio. This file is part of PulseAudio.
Copyright 2006 Lennart Poettering Copyright 2006 Lennart Poettering
Copyright 2006 Shams E. King Copyright 2006 Shams E. King
PulseAudio is free software; you can redistribute it and/or modify PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License, by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version. or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. General Public License for more details.
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA. USA.
***/ ***/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -27,7 +27,6 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -55,25 +54,6 @@ PA_MODULE_AUTHOR("Shahms King")
PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers") PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers")
PA_MODULE_VERSION(PACKAGE_VERSION) 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",
#endif
};
struct device { struct device {
uint32_t index; uint32_t index;
char *udi; char *udi;
@ -81,13 +61,10 @@ struct device {
struct userdata { struct userdata {
pa_core *core; pa_core *core;
LibHalContext *ctx; LibHalContext *context;
capability_t capability; pa_dbus_connection *connection;
pa_dbus_connection *conn;
pa_hashmap *devices; pa_hashmap *devices;
#if defined(HAVE_ALSA) && defined(HAVE_OSS) const char *capability;
int use_oss;
#endif
}; };
struct timerdata { struct timerdata {
@ -95,23 +72,23 @@ struct timerdata {
char *udi; char *udi;
}; };
static const char* get_capability_name(capability_t cap) { #define CAPABILITY_ALSA "alsa"
if (cap >= CAP_MAX) #define CAPABILITY_OSS "oss"
return NULL;
return capabilities[cap];
}
static void hal_device_free(struct device* d) { static void hal_device_free(struct device* d) {
pa_assert(d);
pa_xfree(d->udi); pa_xfree(d->udi);
pa_xfree(d); pa_xfree(d);
} }
static void hal_device_free_cb(void *d, PA_GCC_UNUSED void *data) { 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) { static const char *strip_udi(const char *udi) {
const char *slash; const char *slash;
if ((slash = strrchr(udi, '/'))) if ((slash = strrchr(udi, '/')))
return slash+1; return slash+1;
@ -119,6 +96,7 @@ static const char *strip_udi(const char *udi) {
} }
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
typedef enum { typedef enum {
ALSA_TYPE_SINK, ALSA_TYPE_SINK,
ALSA_TYPE_SOURCE, ALSA_TYPE_SOURCE,
@ -126,59 +104,61 @@ typedef enum {
ALSA_TYPE_MAX ALSA_TYPE_MAX
} alsa_type_t; } alsa_type_t;
static alsa_type_t hal_device_get_alsa_type(LibHalContext *ctx, const char *udi, static alsa_type_t hal_alsa_device_get_type(LibHalContext *context, const char *udi, DBusError *error) {
DBusError *error)
{
char *type; char *type;
alsa_type_t t; alsa_type_t t;
type = libhal_device_get_property_string(ctx, udi, "alsa.type", error); if (!(type = libhal_device_get_property_string(context, udi, "alsa.type", error)))
if (!type || dbus_error_is_set(error)) return ALSA_TYPE_OTHER;
return FALSE;
if (!strcmp(type, "playback")) { if (!strcmp(type, "playback"))
t = ALSA_TYPE_SINK; t = ALSA_TYPE_SINK;
} else if (!strcmp(type, "capture")) { else if (!strcmp(type, "capture"))
t = ALSA_TYPE_SOURCE; t = ALSA_TYPE_SOURCE;
} else { else
t = ALSA_TYPE_OTHER; t = ALSA_TYPE_OTHER;
}
libhal_free_string(type); libhal_free_string(type);
return t; return t;
} }
static int hal_device_get_alsa_card(LibHalContext *ctx, const char *udi, static int hal_alsa_device_is_modem(LibHalContext *context, const char *udi, DBusError *error) {
DBusError *error) char *class;
{ int r;
return libhal_device_get_property_int(ctx, udi, "alsa.card", error);
if (!(class = libhal_device_get_property_string(context, udi, "alsa.pcm_class", error)))
return 0;
r = strcmp(class, "modem") == 0;
pa_xfree(class);
return r;
} }
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)
{
return libhal_device_get_property_int(ctx, udi, "alsa.device", error);
}
static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi,
DBusError *error)
{
char args[128]; char args[128];
alsa_type_t type; alsa_type_t type;
int device, card; int device, card;
const char *module_name; const char *module_name;
DBusError error;
dbus_error_init(&error);
type = hal_device_get_alsa_type(u->ctx, udi, error); type = hal_alsa_device_get_type(u->context, udi, &error);
if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER) if (dbus_error_is_set(&error) || type == ALSA_TYPE_OTHER)
return NULL; goto fail;
device = hal_device_get_alsa_device(u->ctx, udi, error); device = libhal_device_get_property_int(u->context, udi, "alsa.device", &error);
if (dbus_error_is_set(error) || device != 0) if (dbus_error_is_set(&error) || device != 0)
return NULL; goto fail;
card = hal_device_get_alsa_card(u->ctx, udi, error); card = libhal_device_get_property_int(u->context, udi, "alsa.card", &error);
if (dbus_error_is_set(error)) if (dbus_error_is_set(&error))
return NULL; goto fail;
if (hal_alsa_device_is_modem(u->context, udi, &error))
goto fail;
if (type == ALSA_TYPE_SINK) { if (type == ALSA_TYPE_SINK) {
module_name = "module-alsa-sink"; module_name = "module-alsa-sink";
@ -191,58 +171,67 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi,
pa_log_debug("Loading %s with arguments '%s'", module_name, args); pa_log_debug("Loading %s with arguments '%s'", module_name, args);
return pa_module_load(u->core, module_name, args); return pa_module_load(u->core, module_name, args);
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 #endif
#ifdef HAVE_OSS #ifdef HAVE_OSS
static dbus_bool_t hal_device_is_oss_pcm(LibHalContext *ctx, const char *udi,
DBusError *error) static int hal_oss_device_is_pcm(LibHalContext *context, const char *udi, DBusError *error) {
{ char *class = NULL, *dev = NULL, *e;
dbus_bool_t rv = FALSE;
char* type, *device_file = NULL;
int device; int device;
int r = 0;
type = libhal_device_get_property_string(ctx, udi, "oss.type", error); class = libhal_device_get_property_string(context, udi, "oss.type", error);
if (!type || dbus_error_is_set(error)) if (dbus_error_is_set(error) || !class)
return FALSE; goto finish;
if (!strcmp(type, "pcm")) { if (strcmp(class, "pcm"))
char *e; goto finish;
device = libhal_device_get_property_int(ctx, udi, "oss.device", error); dev = libhal_device_get_property_string(context, udi, "oss.device_file", error);
if (dbus_error_is_set(error) || device != 0) if (dbus_error_is_set(error) || !dev)
goto exit; goto finish;
device_file = libhal_device_get_property_string(ctx, udi, "oss.device_file", if ((e = strrchr(dev, '/')))
error); if (pa_startswith(e + 1, "audio"))
if (!device_file || dbus_error_is_set(error)) goto finish;
goto exit;
/* hack to ignore /dev/audio style devices */ device = libhal_device_get_property_int(context, udi, "oss.device", error);
if ((e = strrchr(device_file, '/'))) if (dbus_error_is_set(error) || device != 0)
rv = !pa_startswith(e + 1, "audio"); goto finish;
}
exit: r = 1;
libhal_free_string(type);
libhal_free_string(device_file); finish:
return rv;
libhal_free_string(class);
libhal_free_string(dev);
return r;
} }
static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, static pa_module* hal_device_load_oss(struct userdata *u, const char *udi) {
DBusError *error)
{
char args[256]; char args[256];
char* device; char* device;
DBusError error;
dbus_error_init(&error);
if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error)) if (!hal_oss_device_is_pcm(u->context, udi, &error) || dbus_error_is_set(&error))
return NULL; goto fail;
device = libhal_device_get_property_string(u->ctx, udi, "oss.device_file", device = libhal_device_get_property_string(u->context, udi, "oss.device_file", &error);
error); if (!device || dbus_error_is_set(&error))
if (!device || dbus_error_is_set(error)) goto fail;
return NULL;
pa_snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi)); pa_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); libhal_free_string(device);
@ -250,139 +239,167 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi,
pa_log_debug("Loading module-oss with arguments '%s'", args); pa_log_debug("Loading module-oss with arguments '%s'", args);
return pa_module_load(u->core, "module-oss", args); return pa_module_load(u->core, "module-oss", args);
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 NULL;
} }
#endif #endif
static dbus_bool_t hal_device_add(struct userdata *u, const char *udi, static int hal_device_add(struct userdata *u, const char *udi) {
DBusError *error)
{
pa_module* m = NULL; pa_module* m = NULL;
struct device *d; struct device *d;
switch(u->capability) { pa_assert(u);
pa_assert(u->capability);
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
case CAP_ALSA: if (strcmp(u->capability, CAPABILITY_ALSA) == 0)
m = hal_device_load_alsa(u, udi, error); m = hal_device_load_alsa(u, udi);
break;
#endif #endif
#ifdef HAVE_OSS #ifdef HAVE_OSS
case CAP_OSS: if (strcmp(u->capability, CAPABILITY_OSS) == 0)
#ifdef HAVE_ALSA m = hal_device_load_oss(u, udi);
if (u->use_oss)
#endif #endif
m = hal_device_load_oss(u, udi, error);
break;
#endif
default:
assert(FALSE); /* never reached */
break;
}
if (!m || dbus_error_is_set(error)) if (!m)
return FALSE; return -1;
d = pa_xnew(struct device, 1); d = pa_xnew(struct device, 1);
d->udi = pa_xstrdup(udi); d->udi = pa_xstrdup(udi);
d->index = m->index; d->index = m->index;
pa_hashmap_put(u->devices, d->udi, d); pa_hashmap_put(u->devices, d->udi, d);
return TRUE; return 0;
} }
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; DBusError error;
int i,n,count; int i, n, count = 0;
dbus_bool_t r;
char** udis; char** udis;
const char* cap = get_capability_name(capability);
assert(capability < CAP_MAX); pa_assert(u);
pa_assert(!u->capability);
pa_log_info("Trying capability %u (%s)", capability, cap);
dbus_error_init(&error); dbus_error_init(&error);
udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error);
pa_log_info("Trying capability %s", capability);
udis = libhal_find_device_by_capability(u->context, capability, &n, &error);
if (dbus_error_is_set(&error)) { if (dbus_error_is_set(&error)) {
pa_log_error("Error finding devices: %s: %s", error.name, pa_log_error("Error finding devices: %s: %s", error.name, error.message);
error.message);
dbus_error_free(&error); dbus_error_free(&error);
return -1; return -1;
} }
count = 0;
u->capability = capability; if (n > 0) {
for (i = 0; i < n; ++i) { u->capability = capability;
r = hal_device_add(u, udis[i], &error);
if (dbus_error_is_set(&error)) { for (i = 0; i < n; i++) {
pa_log_error("Error adding device: %s: %s", error.name, if (hal_device_add(u, udis[i]) < 0)
error.message); pa_log_debug("Not loaded device %s", udis[i]);
dbus_error_free(&error); else
count = -1; count++;
break;
} }
if (r)
++count;
} }
libhal_free_string_array(udis); libhal_free_string_array(udis);
return count; return count;
} }
static dbus_bool_t device_has_capability(LibHalContext *ctx, const char *udi, static dbus_bool_t device_has_capability(LibHalContext *context, const char *udi, const char* cap, DBusError *error){
const char* cap, DBusError *error)
{
dbus_bool_t has_prop; 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)) if (!has_prop || dbus_error_is_set(error))
return FALSE; 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, static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const struct timeval *tv, void *userdata) {
const struct timeval *tv, void *userdata)
{
DBusError error; DBusError error;
struct timerdata *td = (struct timerdata*) userdata; struct timerdata *td = userdata;
int b;
dbus_error_init(&error); dbus_error_init(&error);
if (libhal_device_exists(td->u->ctx, td->udi, &error))
hal_device_add(td->u, td->udi, &error); b = libhal_device_exists(td->u->context, td->udi, &error);
if (dbus_error_is_set(&error)) { if (dbus_error_is_set(&error)) {
pa_log_error("Error adding device: %s: %s", error.name, pa_log_error("Error adding device: %s: %s", error.name, error.message);
error.message);
dbus_error_free(&error); dbus_error_free(&error);
} } else if (b)
hal_device_add(td->u, td->udi);
pa_xfree(td->udi); pa_xfree(td->udi);
pa_xfree(td); pa_xfree(td);
ea->time_free(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; DBusError error;
struct timeval tv; struct timeval tv;
dbus_bool_t has_cap;
struct timerdata *t; struct timerdata *t;
struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx); struct userdata *u;
const char* cap = get_capability_name(u->capability); int good = 0;
pa_assert_se(u = libhal_ctx_get_user_data(context));
pa_log_debug("HAL Device added: %s", udi); pa_log_debug("HAL Device added: %s", udi);
dbus_error_init(&error); 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;
}
/* skip it */ if (u->capability) {
if (!has_cap)
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
}
if (!good)
return; return;
/* actually add the device 1/2 second later */ /* actually add the device 1/2 second later */
@ -392,104 +409,81 @@ static void device_added_cb(LibHalContext *ctx, const char *udi)
pa_gettimeofday(&tv); pa_gettimeofday(&tv);
pa_timeval_add(&tv, 500000); pa_timeval_add(&tv, 500000);
u->core->mainloop->time_new(u->core->mainloop, &tv, u->core->mainloop->time_new(u->core->mainloop, &tv, device_added_time_cb, t);
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 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); pa_log_debug("Device removed: %s", udi);
if ((d = pa_hashmap_remove(u->devices, udi))) { if ((d = pa_hashmap_remove(u->devices, udi))) {
pa_module_unload_by_index(u->core, d->index); pa_module_unload_by_index(u->core, d->index);
hal_device_free(d); hal_device_free(d);
} }
} }
static void new_capability_cb(LibHalContext *ctx, const char *udi, static void new_capability_cb(LibHalContext *context, const char *udi, const char* capability) {
const char* capability) struct userdata *u;
{
struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx);
const char* capname = get_capability_name(u->capability);
if (capname && !strcmp(capname, capability)) { pa_assert_se(u = libhal_ctx_get_user_data(context));
if (!u->capability || strcmp(u->capability, capability) == 0)
/* capability we care about, pretend it's a new device */ /* 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, static void lost_capability_cb(LibHalContext *context, const char *udi, const char* capability) {
const char* capability) struct userdata *u;
{
struct userdata *u = (struct userdata*) libhal_ctx_get_user_data(ctx);
const char* capname = get_capability_name(u->capability);
if (capname && !strcmp(capname, capability)) { pa_assert_se(u = libhal_ctx_get_user_data(context));
if (u->capability && strcmp(u->capability, capability) == 0)
/* capability we care about, pretend it was removed */ /* capability we care about, pretend it was removed */
device_removed_cb(ctx, udi); device_removed_cb(context, udi);
}
} }
#if 0 static void hal_context_free(LibHalContext* hal_context) {
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 pa_hal_context_free(LibHalContext* hal_ctx)
{
DBusError error; DBusError error;
dbus_error_init(&error); dbus_error_init(&error);
libhal_ctx_shutdown(hal_ctx, &error);
libhal_ctx_free(hal_ctx); libhal_ctx_shutdown(hal_context, &error);
libhal_ctx_free(hal_context);
if (dbus_error_is_set(&error)) { if (dbus_error_is_set(&error))
dbus_error_free(&error); dbus_error_free(&error);
}
} }
static void userdata_free(struct userdata *u) { static LibHalContext* hal_context_new(pa_core* c, DBusConnection *conn) {
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 LibHalContext* pa_hal_context_new(pa_core* c, DBusConnection *conn)
{
DBusError error; DBusError error;
LibHalContext *hal_ctx = NULL; LibHalContext *hal_context = NULL;
dbus_error_init(&error); dbus_error_init(&error);
if (!(hal_ctx = libhal_ctx_new())) {
if (!(hal_context = libhal_ctx_new())) {
pa_log_error("libhal_ctx_new() failed"); pa_log_error("libhal_ctx_new() failed");
goto fail; goto fail;
} }
if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) { if (!libhal_ctx_set_dbus_connection(hal_context, conn)) {
pa_log_error("Error establishing DBUS connection: %s: %s", pa_log_error("Error establishing DBUS connection: %s: %s", error.name, error.message);
error.name, error.message);
goto fail; goto fail;
} }
if (!libhal_ctx_init(hal_ctx, &error)) { if (!libhal_ctx_init(hal_context, &error)) {
pa_log_error("Couldn't connect to hald: %s: %s", pa_log_error("Couldn't connect to hald: %s: %s", error.name, error.message);
error.name, error.message);
goto fail; goto fail;
} }
return hal_ctx; return hal_context;
fail: fail:
if (hal_ctx) if (hal_context)
pa_hal_context_free(hal_ctx); hal_context_free(hal_context);
if (dbus_error_is_set(&error)) if (dbus_error_is_set(&error))
dbus_error_free(&error); dbus_error_free(&error);
@ -501,78 +495,82 @@ int pa__init(pa_core *c, pa_module*m) {
DBusError error; DBusError error;
pa_dbus_connection *conn; pa_dbus_connection *conn;
struct userdata *u = NULL; struct userdata *u = NULL;
LibHalContext *hal_ctx = NULL; LibHalContext *hal_context = NULL;
int n = 0; int n = 0;
assert(c); pa_assert(c);
assert(m); pa_assert(m);
dbus_error_init(&error); dbus_error_init(&error);
if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) { if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) {
pa_log_error("Unable to contact DBUS system bus: %s: %s", pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message);
error.name, error.message);
dbus_error_free(&error); dbus_error_free(&error);
return -1; return -1;
} }
if (!(hal_ctx = pa_hal_context_new(c, pa_dbus_connection_get(conn)))) { if (!(hal_context = hal_context_new(c, pa_dbus_connection_get(conn)))) {
/* pa_hal_context_new() logs appropriate errors */ /* pa_hal_context_new() logs appropriate errors */
pa_dbus_connection_unref(conn);
return -1; return -1;
} }
u = pa_xnew(struct userdata, 1); u = pa_xnew(struct userdata, 1);
u->core = c; u->core = c;
u->ctx = hal_ctx; u->context = hal_context;
u->conn = conn; u->connection = conn;
u->devices = pa_hashmap_new(pa_idxset_string_hash_func, u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
pa_idxset_string_compare_func); u->capability = NULL;
m->userdata = (void*) u; m->userdata = u;
#ifdef HAVE_ALSA #ifdef HAVE_ALSA
n = hal_device_add_all(u, CAP_ALSA); n = hal_device_add_all(u, CAPABILITY_ALSA);
#endif #endif
#if defined(HAVE_ALSA) && defined(HAVE_OSS) #if defined(HAVE_ALSA) && defined(HAVE_OSS)
u->use_oss = 0; if (n <= 0)
#endif
if (n <= 0) {
#endif
#ifdef HAVE_OSS #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;
}
#endif #endif
libhal_ctx_set_user_data(hal_ctx, u); libhal_ctx_set_user_data(hal_context, u);
libhal_ctx_set_device_added(hal_ctx, device_added_cb); libhal_ctx_set_device_added(hal_context, device_added_cb);
libhal_ctx_set_device_removed(hal_ctx, device_removed_cb); libhal_ctx_set_device_removed(hal_context, device_removed_cb);
libhal_ctx_set_device_new_capability(hal_ctx, new_capability_cb); libhal_ctx_set_device_new_capability(hal_context, new_capability_cb);
libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability_cb); libhal_ctx_set_device_lost_capability(hal_context, lost_capability_cb);
/*libhal_ctx_set_device_property_modified(hal_ctx, property_modified_cb);*/
dbus_error_init(&error); dbus_error_init(&error);
if (!libhal_device_property_watch_all(hal_ctx, &error)) {
pa_log_error("error monitoring device list: %s: %s", if (!libhal_device_property_watch_all(hal_context, &error)) {
error.name, error.message); pa_log_error("Error monitoring device list: %s: %s", error.name, error.message);
dbus_error_free(&error); dbus_error_free(&error);
userdata_free(u); pa__done(c, m);
return -1; return -1;
} }
pa_log_info("loaded %i modules.", n); pa_log_info("Loaded %i modules.", n);
return 0; return 0;
} }
void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) { void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) {
assert (c && m); struct userdata *u;
pa_assert(c);
pa_assert(m);
/* free the user data */ if (!(u = m->userdata))
userdata_free(m->userdata); return;
if (u->context)
hal_context_free(u->context);
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);
} }