cleanup:
- rm -fr $(TMPDIR) && \
- rm -f $(SPECFILE)
- rm -f $(TARBALL)
+# rm -fr $(TMPDIR) && \
+# rm -f $(SPECFILE)
+# rm -f $(TARBALL)
# rules to patch the SPEC file and build a source tarball
$(SPECFILE): $(SPECFILE).in
module_genivi_mir_la_SOURCES = \
module-genivi-mir.c \
- index-hash.c \
- config-file.c \
- client-ext.c \
- sink-ext.c \
- source-ext.c \
- sink-input-ext.c \
- source-output-ext.c \
- card-ext.c \
- module-ext.c \
- classify.c \
- discover.c \
+ tracker.c \
node.c \
- policy-group.c \
- context.c \
+ discover.c \
audiomgr.c \
- dbusif.c
+ dbusif.c \
+ utils.c
AM_CFLAGS = -g3 -O0
-module_genivi_mir_la_LDFLAGS = -module -avoid-version
+module_genivi_mir_la_LDFLAGS = -module -avoid-version -Wl,--no-undefined
module_genivi_mir_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) $(LIBPULSE_LIBS) $(PULSEDEVEL_LIBS)
module_genivi_mir_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) $(LIBPULSE_CFLAGS) $(PULSEDEVEL_CFLAGS) -DPULSEAUDIO_HAS_PORTS=$(PULSEAUDIO_HAS_PORTS)
}
void pa_audiomgr_node_unregistered(struct userdata *u,
- uint16_t id,
am_nodeunreg_data *ud)
{
(void)u;
- (void)id;
/* can't do too much here anyways,
since the node is gone already */
am_nodereg_data *);
void pa_audiomgr_unregister_node(struct userdata *, mir_node *);
-void pa_audiomgr_node_unregistered(struct userdata *, uint16_t,
- am_nodeunreg_data *);
+void pa_audiomgr_node_unregistered(struct userdata *, am_nodeunreg_data *);
void pa_audiomgr_connect(struct userdata *, am_connect_data *);
void pa_audiomgr_disconnect(struct userdata *, am_connect_data *);
static DBusHandlerResult filter(DBusConnection *, DBusMessage *, void *);
static void handle_admin_message(struct userdata *, DBusMessage *);
+#if 0
static void handle_info_message(struct userdata *, DBusMessage *);
static void handle_action_message(struct userdata *, DBusMessage *);
+#endif
static void murphy_registration_cb(struct userdata *, const char *,
DBusMessage *, void *);
static pa_bool_t register_to_murphy(struct userdata *);
+#if 0
static int signal_status(struct userdata *, uint32_t, uint32_t);
+#endif
static DBusHandlerResult audiomgr_method_handler(DBusConnection *,
DBusMessage *, void *);
}
}
-void pa_policy_dbusif_send_device_state(struct userdata *u, char *state,
- char **types, int ntype)
-{
- static char *path = (char *)"/com/nokia/policy/info";
-
- struct pa_policy_dbusif *dbusif = u->dbusif;
- DBusConnection *conn = pa_dbus_connection_get(dbusif->conn);
- DBusMessage *msg;
- DBusMessageIter mit;
- DBusMessageIter dit;
- int i;
- int sts;
-
- if (!types || ntype < 1)
- return;
-
- msg = dbus_message_new_signal(path, dbusif->ifnam, "info");
-
- if (msg == NULL) {
- pa_log("%s: failed to make new info message", __FILE__);
- goto fail;
- }
-
- dbus_message_iter_init_append(msg, &mit);
-
- if (!dbus_message_iter_append_basic(&mit, DBUS_TYPE_STRING, &state) ||
- !dbus_message_iter_open_container(&mit, DBUS_TYPE_ARRAY,"s", &dit)){
- pa_log("%s: failed to build info message", __FILE__);
- goto fail;
- }
-
- for (i = 0; i < ntype; i++) {
- if (!dbus_message_iter_append_basic(&dit, DBUS_TYPE_STRING,&types[i])){
- pa_log("%s: failed to build info message", __FILE__);
- goto fail;
- }
- }
-
- dbus_message_iter_close_container(&mit, &dit);
-
- sts = dbus_connection_send(conn, msg, NULL);
-
- if (!sts) {
- pa_log("%s: Can't send info message: out of memory", __FILE__);
- }
-
- fail:
- dbus_message_unref(msg); /* should cope with NULL msg */
-}
-
-void pa_policy_dbusif_send_media_status(struct userdata *u, const char *media,
- const char *group, int active)
-{
- static char *path = (char *)"/com/nokia/policy/info";
- static const char *type = "media";
-
- struct pa_policy_dbusif *dbusif = u->dbusif;
- DBusConnection *conn = pa_dbus_connection_get(dbusif->conn);
- DBusMessage *msg;
- const char *state;
- int success;
-
- msg = dbus_message_new_signal(path, dbusif->ifnam, "info");
-
- if (msg == NULL)
- pa_log("%s: failed to make new info message", __FILE__);
- else {
- state = active ? "active" : "inactive";
-
- success = dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_STRING, &media,
- DBUS_TYPE_STRING, &group,
- DBUS_TYPE_STRING, &state,
- DBUS_TYPE_INVALID);
-
- if (!success)
- pa_log("%s: Can't build D-Bus info message", __FILE__);
- else {
- if (!dbus_connection_send(conn, msg, NULL)) {
- pa_log("%s: Can't send info message: out of memory", __FILE__);
- }
- }
-
- dbus_message_unref(msg);
- }
-}
static DBusHandlerResult filter(DBusConnection *conn, DBusMessage *msg,
void *arg)
}
+#if 0
if (dbus_message_is_signal(msg, POLICY_DBUS_INTERFACE,POLICY_STREAM_INFO)){
handle_info_message(u, msg);
return DBUS_HANDLER_RESULT_HANDLED;
handle_action_message(u, msg);
return DBUS_HANDLER_RESULT_HANDLED;
}
+#endif
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
+static void handle_admin_message(struct userdata *u, DBusMessage *msg)
+{
+ struct pa_policy_dbusif *dbusif;
+ char *name;
+ char *before;
+ char *after;
+ int success;
+
+ pa_assert(u);
+ pa_assert_se((dbusif = u->dbusif));
+
+ success = dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &before,
+ DBUS_TYPE_STRING, &after,
+ DBUS_TYPE_INVALID);
+
+ if (!success || !name) {
+ pa_log("Received malformed '%s' message", ADMIN_NAME_OWNER_CHANGED);
+ return;
+ }
+
+ if (!strcmp(name, dbusif->mrpnam)) {
+ if (after && strcmp(after, "")) {
+ pa_log_debug("murphy is up");
+
+ if (!dbusif->mregist) {
+ register_to_murphy(u);
+ }
+ }
+
+ if (name && before && (!after || !strcmp(after, ""))) {
+ pa_log_info("murphy is gone");
+ dbusif->mregist = 0;
+ }
+ } else
+
+ if (!strcmp(name, dbusif->amnam)) {
+ if (after && strcmp(after, "")) {
+ pa_log_debug("audio manager is up");
+
+ if (!dbusif->amisup) {
+ register_to_audiomgr(u);
+ }
+ }
+
+ if (name && before && (!after || !strcmp(after, ""))) {
+ pa_log_info("audio manager is gone");
+
+ if (dbusif->amisup)
+ unregister_from_audiomgr(u);
+
+ dbusif->amisup = 0;
+ }
+ }
+}
+
+
static void reply_cb(DBusPendingCall *pend, void *data)
{
struct pending *pdata = (struct pending *)data;
}
-static void handle_admin_message(struct userdata *u, DBusMessage *msg)
+/**************************************************************************
+ *
+ * Murphy interfaces
+ *
+ */
+#if 0
+void pa_policy_dbusif_send_device_state(struct userdata *u, char *state,
+ char **types, int ntype)
{
- struct pa_policy_dbusif *dbusif;
- char *name;
- char *before;
- char *after;
- int success;
-
- pa_assert(u);
- pa_assert_se((dbusif = u->dbusif));
+ static char *path = (char *)"/com/nokia/policy/info";
- success = dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &before,
- DBUS_TYPE_STRING, &after,
- DBUS_TYPE_INVALID);
+ struct pa_policy_dbusif *dbusif = u->dbusif;
+ DBusConnection *conn = pa_dbus_connection_get(dbusif->conn);
+ DBusMessage *msg;
+ DBusMessageIter mit;
+ DBusMessageIter dit;
+ int i;
+ int sts;
- if (!success || !name) {
- pa_log("Received malformed '%s' message", ADMIN_NAME_OWNER_CHANGED);
+ if (!types || ntype < 1)
return;
+
+ msg = dbus_message_new_signal(path, dbusif->ifnam, "info");
+
+ if (msg == NULL) {
+ pa_log("%s: failed to make new info message", __FILE__);
+ goto fail;
}
- if (!strcmp(name, dbusif->mrpnam)) {
- if (after && strcmp(after, "")) {
- pa_log_debug("murphy is up");
+ dbus_message_iter_init_append(msg, &mit);
- if (!dbusif->mregist) {
- register_to_murphy(u);
- }
+ if (!dbus_message_iter_append_basic(&mit, DBUS_TYPE_STRING, &state) ||
+ !dbus_message_iter_open_container(&mit, DBUS_TYPE_ARRAY,"s", &dit)){
+ pa_log("%s: failed to build info message", __FILE__);
+ goto fail;
+ }
+
+ for (i = 0; i < ntype; i++) {
+ if (!dbus_message_iter_append_basic(&dit, DBUS_TYPE_STRING,&types[i])){
+ pa_log("%s: failed to build info message", __FILE__);
+ goto fail;
}
+ }
- if (name && before && (!after || !strcmp(after, ""))) {
- pa_log_info("murphy is gone");
- dbusif->mregist = 0;
- }
- } else
+ dbus_message_iter_close_container(&mit, &dit);
- if (!strcmp(name, dbusif->amnam)) {
- if (after && strcmp(after, "")) {
- pa_log_debug("audio manager is up");
+ sts = dbus_connection_send(conn, msg, NULL);
- if (!dbusif->amisup) {
- register_to_audiomgr(u);
- }
- }
+ if (!sts) {
+ pa_log("%s: Can't send info message: out of memory", __FILE__);
+ }
- if (name && before && (!after || !strcmp(after, ""))) {
- pa_log_info("audio manager is gone");
+ fail:
+ dbus_message_unref(msg); /* should cope with NULL msg */
+}
- if (dbusif->amisup)
- unregister_from_audiomgr(u);
+void pa_policy_dbusif_send_media_status(struct userdata *u, const char *media,
+ const char *group, int active)
+{
+ static char *path = (char *)"/com/nokia/policy/info";
+ static const char *type = "media";
- dbusif->amisup = 0;
- }
+ struct pa_policy_dbusif *dbusif = u->dbusif;
+ DBusConnection *conn = pa_dbus_connection_get(dbusif->conn);
+ DBusMessage *msg;
+ const char *state;
+ int success;
+
+ msg = dbus_message_new_signal(path, dbusif->ifnam, "info");
+
+ if (msg == NULL)
+ pa_log("%s: failed to make new info message", __FILE__);
+ else {
+ state = active ? "active" : "inactive";
+
+ success = dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_STRING, &media,
+ DBUS_TYPE_STRING, &group,
+ DBUS_TYPE_STRING, &state,
+ DBUS_TYPE_INVALID);
+
+ if (!success)
+ pa_log("%s: Can't build D-Bus info message", __FILE__);
+ else {
+ if (!dbus_connection_send(conn, msg, NULL)) {
+ pa_log("%s: Can't send info message: out of memory", __FILE__);
+ }
+ }
+
+ dbus_message_unref(msg);
}
}
+#endif
-/**************************************************************************
- *
- * Murphy interfaces
- *
- */
+#if 0
static void handle_info_message(struct userdata *u, DBusMessage *msg)
{
dbus_uint32_t txid;
send_signal:
signal_status(u, txid, success);
}
+#endif
static void murphy_registration_cb(struct userdata *u,
const char *method,
}
+#if 0
static int signal_status(struct userdata *u, uint32_t txid, uint32_t status)
{
struct pa_policy_dbusif *dbusif = u->dbusif;
dbus_message_unref(msg); /* should cope with NULL msg */
return -1;
}
+#endif
+
/**************************************************************************
*
void *data)
{
const char *error_descr;
- dbus_uint16_t object_id;
dbus_uint16_t status;
int success;
const char *objtype;
objtype = method;
pa_log_info("AudioManager replied to %s deregistration: %u",
- objtype, object_id);
+ objtype, status);
- pa_audiomgr_node_unregistered(u, object_id, data);
+ pa_audiomgr_node_unregistered(u, data);
}
}
}
const char *, const char *);
void pa_policy_dbusif_done(struct userdata *);
+#if 0
void pa_policy_dbusif_send_device_state(struct userdata *,char *,char **,int);
void pa_policy_dbusif_send_media_status(struct userdata *, const char *,
const char *, int);
+#endif
/* audiomgr stuff */
pa_bool_t pa_policy_dbusif_register_domain(struct userdata *,
#include "discover.h"
#include "node.h"
-#include "card-ext.h"
#include "audiomgr.h"
+#include "utils.h"
#define MAX_CARD_TARGET 4
#define MAX_NAME_LENGTH 256
static void parse_profile_name(pa_card_profile *,
char **, char **, char *, int);
+static char *node_key_from_card(struct userdata *, mir_direction,
+ void *, char *, size_t);
+
+
static void classify_node_by_card(mir_node *, pa_card *,
pa_card_profile *, pa_device_port *);
static void guess_node_type_and_name(mir_node *, const char *, const char *);
+static void pa_hashmap_node_free(void *node, void *u)
+{
+ mir_node_destroy(u, node);
+}
+
struct pa_discover *pa_discover_init(struct userdata *u)
{
- pa_discover *dsc = pa_xnew0(pa_discover, 1);
+ pa_discover *discover = pa_xnew0(pa_discover, 1);
- dsc->chmin = 1;
- dsc->chmax = 2;
- dsc->selected = TRUE;
+ discover->chmin = 1;
+ discover->chmax = 2;
+ discover->selected = TRUE;
- dsc->nodes = pa_hashmap_new(pa_idxset_string_hash_func,
- pa_idxset_string_compare_func);
- return dsc;
+ discover->nodes.byname = pa_hashmap_new(pa_idxset_string_hash_func,
+ pa_idxset_string_compare_func);
+ discover->nodes.byptr = pa_hashmap_new(pa_idxset_trivial_hash_func,
+ pa_idxset_trivial_compare_func);
+ return discover;
}
void pa_discover_done(struct userdata *u)
{
+ pa_discover *discover;
+
+ if (u && (discover = u->discover)) {
+ pa_hashmap_free(discover->nodes.byname, pa_hashmap_node_free,u);
+ pa_hashmap_free(discover->nodes.byptr, NULL,NULL);
+ pa_xfree(discover);
+ }
}
void pa_discover_domain_up(struct userdata *u)
pa_assert(u);
pa_assert_se((discover = u->discover));
- PA_HASHMAP_FOREACH(node, discover->nodes, state) {
+ PA_HASHMAP_FOREACH(node, discover->nodes.byname, state) {
node->amid = AM_ID_INVALID;
if (node->visible && node->available)
pa_assert(u);
pa_assert(card);
- if ((bus = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS)) == NULL) {
+ if (!(bus = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS))) {
pa_log_debug("ignoring card '%s' due to lack of '%s' property",
- pa_card_ext_get_name(card), PA_PROP_DEVICE_BUS);
+ pa_utils_get_card_name(card), PA_PROP_DEVICE_BUS);
return;
}
}
pa_log_debug("ignoring card '%s' due to unsupported bus type '%s'",
- pa_card_ext_get_name(card), bus);
+ pa_utils_get_card_name(card), bus);
}
void pa_discover_remove_card(struct userdata *u, pa_card *card)
pa_assert(card);
pa_assert_se((discover = u->discover));
- PA_HASHMAP_FOREACH(node, discover->nodes, state) {
+ PA_HASHMAP_FOREACH(node, discover->nodes.byname, state) {
if (node->implement == mir_device &&
node->pacard.index == card->index)
{
if ((bus = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS)) == NULL) {
pa_log_debug("ignoring profile change on card '%s' due to lack of '%s'"
- "property",pa_card_ext_get_name(card),PA_PROP_DEVICE_BUS);
+ "property", pa_utils_get_card_name(card),
+ PA_PROP_DEVICE_BUS);
return;
}
if (!pci && !usb && !bluetooth) {
pa_log_debug("ignoring profile change on card '%s' due to unsupported "
- "bus type '%s'", pa_card_ext_get_name(card), bus);
+ "bus type '%s'", pa_utils_get_card_name(card), bus);
}
if (bluetooth) {
pa_log_debug("alsa profile changed to '%s' on card '%s'",
card->active_profile->name, card->name);
- stamp = pa_policy_get_stamp();
+ stamp = pa_utils_get_stamp();
handle_alsa_card(u, card);
- PA_HASHMAP_FOREACH(node, discover->nodes, state) {
+ PA_HASHMAP_FOREACH(node, discover->nodes.byname, state) {
if (node->implement == mir_device &&
node->pacard.index == card->index &&
node->stamp < stamp)
}
+void pa_discover_add_sink(struct userdata *u, pa_sink *sink)
+{
+ pa_discover *discover;
+ mir_node *node;
+ pa_card *card;
+ char *key;
+ char buf[256];
+
+ pa_assert(u);
+ pa_assert(sink);
+ pa_assert_se((discover = u->discover));
+
+ if ((card = sink->card)) {
+ if (!(key = node_key_from_card(u, mir_output, sink, buf, sizeof(buf))))
+ return;
+ if (!(node = pa_discover_find_node(u, key))) {
+ pa_log_debug("can't find node for sink (key '%s')", key);
+ return;
+ }
+ pa_log_debug("node for '%s' found. Updating with sink data",
+ node->paname);
+ node->paidx = sink->index;
+ pa_hashmap_put(discover->nodes.byptr, sink, node);
+ }
+}
+
+
+void pa_discover_remove_sink(struct userdata *u, pa_sink *sink)
+{
+ pa_discover *discover;
+ mir_node *node;
+ char *name;
+
+ pa_assert(u);
+ pa_assert(sink);
+ pa_assert_se((discover = u->discover));
+
+ name = pa_utils_get_sink_name(sink);
+
+ if (!(node = pa_hashmap_get(discover->nodes.byptr, sink)))
+ pa_log_debug("can't find node for sink (name '%s')", name);
+ else {
+ pa_log_debug("node found. Reseting sink data");
+ node->paidx = PA_IDXSET_INVALID;
+ pa_hashmap_remove(discover->nodes.byptr, sink);
+ }
+}
+
+
+void pa_discover_add_source(struct userdata *u, pa_source *source)
+{
+ pa_discover *discover;
+ mir_node *node;
+ pa_card *card;
+ char *key;
+ char buf[256];
+
+ pa_assert(u);
+ pa_assert(source);
+ pa_assert_se((discover = u->discover));
+
+ if ((card = source->card)) {
+ if (!(key = node_key_from_card(u, mir_output,source, buf,sizeof(buf))))
+ return;
+ if (!(node = pa_discover_find_node(u, key))) {
+ pa_log_debug("can't find node for source (key '%s')", key);
+ return;
+ }
+ pa_log_debug("node for '%s' found. Updating with source data",
+ node->amname);
+ node->paidx = source->index;
+ pa_hashmap_put(discover->nodes.byptr, source, node);
+ }
+}
+
+
+void pa_discover_remove_source(struct userdata *u, pa_source *source)
+{
+ pa_discover *discover;
+ mir_node *node;
+ char *name;
+
+ pa_assert(u);
+ pa_assert(source);
+ pa_assert_se((discover = u->discover));
+
+ name = pa_utils_get_source_name(source);
+
+ if (!(node = pa_hashmap_get(discover->nodes.byptr, source)))
+ pa_log_debug("can't find node for source (name '%s')", name);
+ else {
+ pa_log_debug("node found. Reseting source data");
+ node->paidx = PA_IDXSET_INVALID;
+ pa_hashmap_remove(discover->nodes.byptr, source);
+ }
+}
+
+
mir_node *pa_discover_find_node(struct userdata *u, const char *key)
{
pa_discover *discover;
+ mir_node *node;
pa_assert(u);
- pa_assert(key);
pa_assert_se((discover = u->discover));
- return pa_hashmap_get(discover->nodes, key);
+ if (key)
+ node = pa_hashmap_get(discover->nodes.byname, key);
+ else
+ node = NULL;
+
+ return node;
}
data.amid = AM_ID_INVALID;
data.implement = mir_device;
data.paidx = PA_IDXSET_INVALID;
- data.stamp = pa_policy_get_stamp();
+ data.stamp = pa_utils_get_stamp();
- cnam = pa_card_ext_get_name(card);
+ cnam = pa_utils_get_card_name(card);
udd = pa_proplist_gets(card->proplist, "module-udev-detect.discovered");
if (udd && pa_streq(udd, "1")) {
data.amname = amname;
data.amdescr = (char *)cdescr;
data.pacard.index = card->index;
- data.stamp = pa_policy_get_stamp();
+ data.stamp = pa_utils_get_stamp();
- cnam = pa_card_ext_get_name(card);
+ cnam = pa_utils_get_card_name(card);
if (!strncmp(cnam, "bluez_card.", 11)) {
cid = cnam + 11;
pa_assert(data->paname);
pa_assert_se((discover = u->discover));
- if ((node = pa_hashmap_get(discover->nodes, data->key)))
+ if ((node = pa_hashmap_get(discover->nodes.byname, data->key)))
created = FALSE;
else {
created = TRUE;
node = mir_node_create(u, data);
- pa_hashmap_put(discover->nodes, node->key, node);
+ pa_hashmap_put(discover->nodes.byname, node->key, node);
mir_node_print(node, buf, sizeof(buf));
pa_log_debug("new node:\n%s", buf);
pa_assert_se((discover = u->discover));
if (node) {
- removed = pa_hashmap_remove(discover->nodes, node->key);
+ removed = pa_hashmap_remove(discover->nodes.byname, node->key);
if (node != removed) {
if (removed)
}
+static char *node_key_from_card(struct userdata *u, mir_direction direction,
+ void *data, char *buf, size_t len)
+{
+ pa_card *card;
+ pa_device_port *port;
+ const char *bus;
+ pa_bool_t pci;
+ pa_bool_t usb;
+ pa_bool_t bluetooth;
+ char *type;
+ char *name;
+ char *key;
+
+ pa_assert(u);
+ pa_assert(data);
+ pa_assert(direction == mir_input || direction == mir_output);
+
+ if (direction == mir_input) {
+ pa_sink *sink = data;
+ type = "sink";
+ name = pa_utils_get_sink_name(sink);
+ card = sink->card;
+ port = sink->active_port;
+ }
+ else {
+ pa_source *source = data;
+ type = "source";
+ name = pa_utils_get_source_name(source);
+ card = source->card;
+ port = source->active_port;
+ }
+
+ if (!card)
+ return NULL;
+
+ if (!(bus = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_BUS))) {
+ pa_log_debug("ignoring %s '%s' due to lack of '%s' property "
+ "on its card", type, name, PA_PROP_DEVICE_BUS);
+ return NULL;
+ }
+
+ pci = pa_streq(bus, "pci");
+ usb = pa_streq(bus, "usb");
+ bluetooth = pa_streq(bus, "bluetooth");
+
+ if (!pci && !usb && !bluetooth) {
+ pa_log_debug("ignoring %s '%s' due to unsupported bus type '%s' "
+ "of its card", type, name, bus);
+ return NULL;
+ }
+
+ if (bluetooth)
+ key = name;
+ else {
+ if (!port)
+ key = name;
+ else {
+ key = buf;
+ snprintf(buf, len, "%s@%s", name, port->name);
+ }
+ }
+
+ return key;
+}
+
+
static void classify_node_by_card(mir_node *data, pa_card *card,
pa_card_profile *prof, pa_device_port *port)
{
/*
* cirtreria for filtering sinks and sources
*/
- unsigned chmin; /**< minimum of max channels */
- unsigned chmax; /**< maximum of max channels */
- pa_bool_t selected; /**< for alsa cards: whether to consider the
- selected profile alone.
- for bluetooth cards: no effect */
- pa_hashmap *nodes;
+ unsigned chmin; /**< minimum of max channels */
+ unsigned chmax; /**< maximum of max channels */
+ pa_bool_t selected; /**< for alsa cards: whether to consider the
+ selected profile alone.
+ for bluetooth cards: no effect */
+ struct {
+ pa_hashmap *byname;
+ pa_hashmap *byptr;
+ } nodes;
} pa_discover;
void pa_discover_remove_card(struct userdata *, pa_card *);
void pa_discover_profile_changed(struct userdata *, pa_card *);
+void pa_discover_add_sink(struct userdata *, pa_sink *);
+void pa_discover_remove_sink(struct userdata *, pa_sink *);
+
+void pa_discover_add_source(struct userdata *, pa_source *);
+void pa_discover_remove_source(struct userdata *, pa_source *);
+
mir_node *pa_discover_find_node(struct userdata *, const char *);
#endif
static void handle_new_module(struct userdata *u, struct pa_module *module)
{
- char *name;
- uint32_t idx;
+ char *name;
if (module && u) {
name = pa_module_ext_get_name(module);
- idx = module->index;
pa_policy_context_register(u, pa_policy_object_module, name, module);
}
#include "module-genivi-mir-symdef.h"
#include "userdata.h"
-#include "index-hash.h"
-#include "config-file.h"
-#include "policy-group.h"
-#include "classify.h"
-#include "context.h"
-#include "client-ext.h"
-#include "sink-ext.h"
-#include "source-ext.h"
-#include "sink-input-ext.h"
-#include "source-output-ext.h"
-#include "card-ext.h"
-#include "module-ext.h"
#include "audiomgr.h"
#include "dbusif.h"
#include "discover.h"
+#include "tracker.h"
-#ifndef PA_DEFAULT_CONFIG_DIR
-#define PA_DEFAULT_CONFIG_DIR "/etc/pulse"
-#endif
PA_MODULE_AUTHOR("Janos Kovacs");
-PA_MODULE_DESCRIPTION("Policy enforcement module");
+PA_MODULE_DESCRIPTION("GenIVI and Murphy compliant audio policy module");
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(TRUE);
PA_MODULE_USAGE(
+ "config_dir=<configuration directory>"
"config_file=<policy configuration file> "
"dbus_if_name=<policy dbus interface> "
"dbus_murphy_path=<policy daemon's path> "
"dbus_audiomgr_path=<GenIVI audio manager's path> "
"dbus_audiomgr_name=<GenIVI audio manager's name> "
"null_sink_name=<name of the null sink> "
- "othermedia_preemption=<on|off> "
- "configdir=<configuration directory>"
);
static const char* const valid_modargs[] = {
+ "config_dir",
"config_file",
"dbus_if_name",
"dbus_murphy_path",
"dbus_audiomgr_path",
"dbus_audiomgr_name",
"null_sink_name",
- "othermedia_preemption",
- "configdir",
NULL
};
int pa__init(pa_module *m) {
struct userdata *u = NULL;
pa_modargs *ma = NULL;
+ const char *cfgdir;
const char *cfgfile;
const char *ifnam;
const char *mrppath;
const char *ampath;
const char *amnam;
const char *nsnam;
- const char *preempt;
- const char *cfgdir;
pa_assert(m);
goto fail;
}
+ cfgdir = pa_modargs_get_value(ma, "config_dir", NULL);
cfgfile = pa_modargs_get_value(ma, "config_file", NULL);
ifnam = pa_modargs_get_value(ma, "dbus_if_name", NULL);
mrppath = pa_modargs_get_value(ma, "dbus_murphy_path", NULL);
ampath = pa_modargs_get_value(ma, "dbus_audiomgr_path", NULL);
amnam = pa_modargs_get_value(ma, "dbus_audiomgr_name", NULL);
nsnam = pa_modargs_get_value(ma, "null_sink_name", NULL);
- preempt = pa_modargs_get_value(ma, "othermedia_preemption", NULL);
- cfgdir = pa_modargs_get_value(ma, "configdir", NULL);
-
u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
- u->nullsink = pa_sink_ext_init_null_sink(nsnam);
- u->hsnk = pa_index_hash_init(8);
- u->hsi = pa_index_hash_init(10);
- u->scl = pa_client_ext_subscription(u);
- u->ssnk = pa_sink_ext_subscription(u);
- u->ssrc = pa_source_ext_subscription(u);
- u->ssi = pa_sink_input_ext_subscription(u);
- u->sso = pa_source_output_ext_subscription(u);
- u->scrd = pa_card_ext_subscription(u);
- u->smod = pa_module_ext_subscription(u);
- u->groups = pa_policy_groupset_new(u);
- u->classify = pa_classify_new(u);
- u->context = pa_policy_context_new(u);
+ //u->nullsink = pa_sink_ext_init_null_sink(nsnam);
u->audiomgr = pa_audiomgr_init(u);
u->dbusif = pa_policy_dbusif_init(u,ifnam, mrppath,mrpnam, ampath,amnam);
u->discover = pa_discover_init(u);
+ u->tracker = pa_tracker_init(u);
- if (u->scl == NULL || u->ssnk == NULL || u->ssrc == NULL ||
- u->ssi == NULL || u->sso == NULL || u->scrd == NULL ||
- u->smod == NULL || u->groups == NULL || u->nullsink == NULL ||
- u->classify == NULL || u->context == NULL || u->dbusif == NULL ||
+ if (/*u->nullsink == NULL ||*/ u->dbusif == NULL ||
u->audiomgr == NULL || u->discover == NULL)
goto fail;
- pa_policy_groupset_update_default_sink(u, PA_IDXSET_INVALID);
- pa_policy_groupset_create_default_group(u, preempt);
-
- if (!pa_policy_parse_config_file(u, cfgfile) ||
- !pa_policy_parse_files_in_configdir(u, cfgdir))
- goto fail;
-
m->userdata = u;
-
- pa_sink_ext_discover(u);
- pa_source_ext_discover(u);
- pa_client_ext_discover(u);
- pa_sink_input_ext_discover(u);
- pa_source_output_ext_discover(u);
- pa_card_ext_discover(u);
- pa_module_ext_discover(u);
+ pa_tracker_synchronize(u);
+
pa_modargs_free(ma);
return 0;
pa_assert(m);
- if (!(u = m->userdata))
- return;
+ if ((u = m->userdata)) {
- pa_discover_done(u);
- pa_audiomgr_done(u);
- pa_policy_dbusif_done(u);
-
- pa_client_ext_subscription_free(u->scl);
- pa_sink_ext_subscription_free(u->ssnk);
- pa_source_ext_subscription_free(u->ssrc);
- pa_sink_input_ext_subscription_free(u->ssi);
- pa_source_output_ext_subscription_free(u->sso);
- pa_card_ext_subscription_free(u->scrd);
- pa_module_ext_subscription_free(u->smod);
-
- pa_policy_groupset_free(u->groups);
- pa_classify_free(u->classify);
- pa_policy_context_free(u->context);
- pa_index_hash_free(u->hsnk);
- pa_index_hash_free(u->hsi);
- pa_sink_ext_null_sink_free(u->nullsink);
+ pa_tracker_done(u);
+ pa_discover_done(u);
+ pa_audiomgr_done(u);
+ pa_policy_dbusif_done(u);
-
- pa_xfree(u);
-}
+ //pa_sink_ext_null_sink_free(u->nullsink);
-
-/*
- * For the time being the prototypes are in the userdata.h which is
- * not the best possible place for it
- */
-const char *pa_policy_file_path(const char *file, char *buf, size_t len)
-{
- snprintf(buf, len, "%s/x%s", PA_DEFAULT_CONFIG_DIR, file);
-
- return buf;
-}
-
-static uint32_t stamp;
-
-const uint32_t pa_policy_new_stamp(void)
-{
- return ++stamp;
+ pa_xfree(u);
+ }
}
-const uint32_t pa_policy_get_stamp(void)
-{
- return stamp;
-}
/*
#include "context.h"
#include "policy-group.h"
#include "dbusif.h"
+#include "discover.h"
/* hooks */
static pa_hook_result_t sink_put(void *, void *, void *);
pa_policy_context_register(u, pa_policy_object_sink, name, sink);
+ pa_discover_add_sink(u, sink);
+
if (len <= 0) {
if (!is_null_sink)
pa_log_debug("new sink '%s' (idx=%d)", name, idx);
#include "sink-ext.h"
#include "classify.h"
#include "context.h"
+#include "discover.h"
/* hooks */
static pa_hook_result_t sink_input_neew(void *, void *, void *);
snam, sinp, sinp->index);
pa_policy_group_remove_sink_input(u, sinp->index);
+
if ((ext = pa_index_hash_remove(u->hsi, idx)) == NULL)
pa_log("no extension found for sink-input '%s' (idx=%u)",snam,idx);
else {
#include "context.h"
#include "policy-group.h"
#include "dbusif.h"
+#include "discover.h"
/* this included for the sake of pa_policy_send_device_state()
which is temporarily hosted by sink-ext.c*/
pa_policy_context_register(u,pa_policy_object_source,name,source);
+ pa_discover_add_source(u, source);
+
if (ret < 0) {
pa_log("failed to set property '%s' on source '%s'",
PA_PROP_POLICY_DEVTYPELIST, name);
pa_policy_context_unregister(u, pa_policy_object_source,
name, source, idx);
+ pa_discover_remove_source(u, source);
+
if (len <= 0)
pa_log_debug("remove source '%s' (idx=%d)", name, idx);
else {
--- /dev/null
+#include <pulsecore/pulsecore-config.h>
+
+#include <pulse/def.h>
+#include <pulsecore/card.h>
+
+#include "tracker.h"
+#include "utils.h"
+#include "discover.h"
+
+static pa_hook_result_t card_put(void *, void *, void *);
+static pa_hook_result_t card_unlink(void *, void *, void *);
+static pa_hook_result_t card_profile_changed(void *, void *, void *);
+
+static pa_hook_result_t sink_put(void *, void *, void *);
+static pa_hook_result_t sink_unlink(void *, void *, void *);
+static pa_hook_result_t sink_port_changed(void *, void *, void *);
+static pa_hook_result_t sink_port_available_changed(void *, void *, void *);
+
+static pa_hook_result_t source_put(void *, void *, void *);
+static pa_hook_result_t source_unlink(void *, void *, void *);
+static pa_hook_result_t source_port_changed(void *, void *, void *);
+static pa_hook_result_t source_port_available_changed(void *, void *, void *);
+
+pa_tracker *pa_tracker_init(struct userdata *u)
+{
+ pa_core *core;
+ pa_hook *hooks;
+ pa_tracker *tracker;
+ pa_card_hooks *card;
+ pa_sink_hooks *sink;
+ pa_source_hooks *source;
+
+ pa_assert(u);
+ pa_assert_se((core = u->core));
+ pa_assert_se((hooks = core->hooks));
+
+ tracker = pa_xnew0(pa_tracker, 1);
+ card = &tracker->card;
+ sink = &tracker->sink;
+ source = &tracker->source;
+
+ /* card */
+ card->put = pa_hook_connect(
+ hooks + PA_CORE_HOOK_CARD_PUT,
+ PA_HOOK_LATE, card_put, u
+ );
+ card->unlink = pa_hook_connect(
+ hooks + PA_CORE_HOOK_CARD_UNLINK,
+ PA_HOOK_LATE, card_unlink, u
+ );
+ card->profchg = pa_hook_connect(
+ hooks + PA_CORE_HOOK_CARD_PROFILE_CHANGED,
+ PA_HOOK_LATE, card_profile_changed, u
+ );
+ /* sink */
+ sink->put = pa_hook_connect(
+ hooks + PA_CORE_HOOK_SINK_PUT,
+ PA_HOOK_LATE, sink_put, u
+ );
+ sink->unlink = pa_hook_connect(
+ hooks + PA_CORE_HOOK_SINK_UNLINK,
+ PA_HOOK_LATE, sink_unlink, u
+ );
+ sink->portchg = pa_hook_connect(
+ hooks + PA_CORE_HOOK_SINK_PORT_CHANGED,
+ PA_HOOK_LATE, sink_port_changed, u
+ );
+ sink->portavail = pa_hook_connect(
+ hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
+ PA_HOOK_LATE, sink_port_available_changed, u
+ );
+ /* source */
+ source->put = pa_hook_connect(
+ hooks + PA_CORE_HOOK_SOURCE_PUT,
+ PA_HOOK_LATE, source_put, u
+ );
+ source->unlink = pa_hook_connect(
+ hooks + PA_CORE_HOOK_SOURCE_UNLINK,
+ PA_HOOK_LATE, source_unlink, u
+ );
+ source->portchg = pa_hook_connect(
+ hooks + PA_CORE_HOOK_SOURCE_PORT_CHANGED,
+ PA_HOOK_LATE, source_port_changed, u
+ );
+ source->portavail = pa_hook_connect(
+ hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
+ PA_HOOK_LATE, source_port_available_changed, u
+ );
+
+ return tracker;
+}
+
+void pa_tracker_done(struct userdata *u)
+{
+ pa_tracker *tracker;
+ pa_card_hooks *card;
+ pa_sink_hooks *sink;
+ pa_source_hooks *source;
+
+ pa_assert(u);
+ pa_assert_se((tracker = u->tracker));
+
+ card = &tracker->card;
+ pa_hook_slot_free(card->put);
+ pa_hook_slot_free(card->unlink);
+ pa_hook_slot_free(card->profchg);
+
+ sink = &tracker->sink;
+ pa_hook_slot_free(sink->put);
+ pa_hook_slot_free(sink->unlink);
+ pa_hook_slot_free(sink->portchg);
+ pa_hook_slot_free(sink->portavail);
+
+ source = &tracker->source;
+ pa_hook_slot_free(source->put);
+ pa_hook_slot_free(source->unlink);
+ pa_hook_slot_free(source->portchg);
+ pa_hook_slot_free(source->portavail);
+
+
+ pa_xfree(tracker);
+}
+
+void pa_tracker_synchronize(struct userdata *u)
+{
+ pa_core *core;
+ pa_card *card;
+ pa_sink *sink;
+ pa_source *source;
+ uint32_t index;
+
+ pa_assert(u);
+ pa_assert_se((core = u->core));
+
+ pa_utils_new_stamp();
+
+ PA_IDXSET_FOREACH(card, core->cards, index) {
+ pa_discover_add_card(u, card);
+ }
+
+ PA_IDXSET_FOREACH(sink, core->sinks, index) {
+ pa_discover_add_sink(u, sink);
+ }
+
+ PA_IDXSET_FOREACH(source, core->sources, index) {
+ pa_discover_add_source(u, source);
+ }
+
+}
+
+
+static pa_hook_result_t card_put(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_card *card = (pa_card *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(card);
+
+ pa_utils_new_stamp();
+ pa_discover_add_card(u, card);
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t card_unlink(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_card *card = (pa_card *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(card);
+
+ pa_discover_remove_card(u, card);
+
+ return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t card_profile_changed(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_card *card = (pa_card *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(card);
+
+ pa_utils_new_stamp();
+ pa_discover_profile_changed(u, card);
+
+ return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t sink_put(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_sink *sink = (pa_sink *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(sink);
+
+ pa_utils_new_stamp();
+ pa_discover_add_sink(u, sink);
+
+ return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t sink_unlink(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_sink *sink = (pa_sink *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(sink);
+
+ pa_discover_remove_sink(u, sink);
+
+ return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t sink_port_changed(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_sink *sink = (pa_sink *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(sink);
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_port_available_changed(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_sink *sink = (pa_sink *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(sink);
+
+ return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t source_put(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_source *source = (pa_source *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(source);
+
+ pa_utils_new_stamp();
+ pa_discover_add_source(u, source);
+
+ return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t source_unlink(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_source *source = (pa_source *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(source);
+
+ pa_discover_remove_source(u, source);
+
+ return PA_HOOK_OK;
+}
+
+
+static pa_hook_result_t source_port_changed(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_source *source = (pa_source *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(source);
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_port_available_changed(void *hook_data,
+ void *call_data,
+ void *slot_data)
+{
+ pa_source *source = (pa_source *)call_data;
+ struct userdata *u = (struct userdata *)slot_data;
+
+ pa_assert(u);
+ pa_assert(source);
+
+ return PA_HOOK_OK;
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
+
--- /dev/null
+#ifndef footrackerfoo
+#define footrackerfoo
+
+#include "userdata.h"
+
+
+typedef struct pa_card_hooks {
+ pa_hook_slot *put;
+ pa_hook_slot *unlink;
+ pa_hook_slot *profchg;
+} pa_card_hooks;
+
+typedef struct pa_sink_hooks {
+ pa_hook_slot *put;
+ pa_hook_slot *unlink;
+ pa_hook_slot *portchg;
+ pa_hook_slot *portavail;
+} pa_sink_hooks;
+
+typedef struct pa_source_hooks {
+ pa_hook_slot *put;
+ pa_hook_slot *unlink;
+ pa_hook_slot *portchg;
+ pa_hook_slot *portavail;
+} pa_source_hooks;
+
+
+
+typedef struct pa_tracker {
+ pa_card_hooks card;
+ pa_sink_hooks sink;
+ pa_source_hooks source;
+} pa_tracker;
+
+pa_tracker *pa_tracker_init(struct userdata *);
+void pa_tracker_done(struct userdata *);
+
+void pa_tracker_synchronize(struct userdata *);
+
+
+
+#endif /* footrackerfoo */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
#include <stdbool.h>
#include <pulsecore/core.h>
-#define PA_POLICY_DEFAULT_GROUP_NAME "othermedia"
-#define PA_POLICY_CONNECTED "1"
-#define PA_POLICY_DISCONNECTED "0"
-#define PA_PROP_APPLICATION_PROCESS_ARGS "application.process.args"
-#define PA_PROP_APPLICATION_PROCESS_ARG0 "application.process.arg0"
-#define PA_PROP_POLICY_GROUP "policy.group"
-#define PA_PROP_POLICY_DEVTYPELIST "policy.device.typelist"
-#define PA_PROP_POLICY_CARDTYPELIST "policy.card.typelist"
-#define PA_PROP_MAEMO_AUDIO_MODE "x-maemo.mode"
-#define PA_PROP_MAEMO_ACCESSORY_HWID "x-maemo.accessory_hwid"
-
-struct pa_index_hash;
-struct pa_client_evsubscr;
-struct pa_sink_evsubscr;
-struct pa_source_evsubscr;
-struct pa_sinp_evsubscr;
-struct pa_sout_evsubscr;
-struct pa_card_evsubscr;
-struct pa_module_evsubscr;
-struct pa_policy_groupset;
-struct pa_classify;
-struct pa_policy_context;
-struct pa_policy_dbusif;
-struct pa_discover;
+typedef struct pa_null_sink pa_null_sink;
+typedef struct pa_tracker pa_tracker;
+typedef struct pa_audiomgr pa_audiomgr;
+typedef struct pa_policy_dbusif pa_policy_dbusif;
+typedef struct pa_discover pa_discover;
struct userdata {
- pa_core *core;
- pa_module *module;
- struct pa_null_sink *nullsink;
- struct pa_index_hash *hsnk; /* sink index hash */
- struct pa_index_hash *hsi; /* sink input index hash */
- struct pa_client_evsubscr *scl; /* client event susbscription */
- struct pa_sink_evsubscr *ssnk; /* sink event subscription */
- struct pa_source_evsubscr *ssrc; /* source event subscription */
- struct pa_sinp_evsubscr *ssi; /* sink input event susbscription */
- struct pa_sout_evsubscr *sso; /* source output event susbscription*/
- struct pa_card_evsubscr *scrd; /* card event subscription */
- struct pa_module_evsubscr *smod; /* module event subscription */
- struct pa_policy_groupset *groups; /* policy groups */
- struct pa_classify *classify; /* rules for classification */
- struct pa_policy_context *context; /* for processing context variables */
- struct pa_policy_dbusif *dbusif;
- struct pa_audiomgr *audiomgr;
- struct pa_discover *discover;
+ pa_core *core;
+ pa_module *module;
+ pa_null_sink *nullsink;
+ pa_audiomgr *audiomgr;
+ pa_policy_dbusif *dbusif;
+ pa_discover *discover;
+ pa_tracker *tracker;
};
-
-/*
- * Some day this should go to a better place
- */
-const char *pa_policy_file_path(const char *file, char *buf, size_t len);
-
-const uint32_t pa_policy_new_stamp(void);
-const uint32_t pa_policy_get_stamp(void);
-
#endif
/*
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <pulsecore/pulsecore-config.h>
+
+#include <pulsecore/card.h>
+#include <pulsecore/sink.h>
+#include <pulsecore/source.h>
+
+#include "userdata.h"
+#include "utils.h"
+
+#ifndef DEFAULT_CONFIG_DIR
+#define DEFAULT_CONFIG_DIR "/etc/pulse"
+#endif
+
+static uint32_t stamp;
+
+
+char *pa_utils_get_card_name(pa_card *card)
+{
+ return card->name ? card->name : (char *)"<unknown>";
+}
+
+char *pa_utils_get_sink_name(pa_sink *sink)
+{
+ return sink->name ? sink->name : (char *)"<unknown>";
+}
+
+char *pa_utils_get_source_name(pa_source *source)
+{
+ return source->name ? source->name : (char *)"<unknown>";
+}
+
+
+
+const char *pa_utils_file_path(const char *file, char *buf, size_t len)
+{
+ snprintf(buf, len, "%s/x%s", DEFAULT_CONFIG_DIR, file);
+
+ return buf;
+}
+
+
+const uint32_t pa_utils_new_stamp(void)
+{
+ return ++stamp;
+}
+
+const uint32_t pa_utils_get_stamp(void)
+{
+ return stamp;
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */
+
+
--- /dev/null
+#ifndef fooutilsfoo
+#define fooutilsfoo
+
+#include <stdbool.h>
+#include <pulsecore/core.h>
+
+char *pa_utils_get_card_name(pa_card *);
+char *pa_utils_get_sink_name(pa_sink *);
+char *pa_utils_get_source_name(pa_source *);
+
+
+const char *pa_utils_file_path(const char *, char *, size_t);
+
+const uint32_t pa_utils_new_stamp(void);
+const uint32_t pa_utils_get_stamp(void);
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ *
+ */