#include <pulsecore/core-util.h> /* required for "pa_streq" */
#include "classify.h"
+#include "node.h"
agl_node_type agl_classify_guess_stream_node_type (struct userdata *u, pa_proplist *pl)
{
+ agl_nodeset *ns;
+ agl_nodeset_map *map;
agl_node_type type;
const char *role;
pa_assert (u);
pa_assert (pl);
+ pa_assert_se (ns = u->nodeset);
role = pa_proplist_gets (pl, PA_PROP_MEDIA_ROLE);
if (!role)
type = agl_node_type_unknown;
+
+ /* ask the configuration, see defaults in "config.c" */
+ else if (map = pa_hashmap_get (ns->roles, role))
+ type = map->type;
+ /* configuration did not match, here are some sensible defaults */
else if (pa_streq (role, "radio"))
type = agl_radio;
else if (pa_streq (role, "music"))
#include "config.h"
#include "zone.h"
+bool use_default_configuration (struct userdata *);
+
const char *agl_config_file_get_path (const char *dir, const char *file, char *buf, size_t len)
{
pa_assert (file);
if (!success) {
pa_log_info ("applying builtin default configuration");
- //success = use_default_configuration (u);
+ success = use_default_configuration (u);
}
return success;
static rtgroup_def rtgroups[] = {
{ agl_input,
- "phone",
+ "Phone",
+ "PhoneCard",
agl_router_phone_accept,
agl_router_phone_compare
},
- { 0, NULL, NULL, NULL }
+ { 0, NULL, NULL, NULL, NULL }
};
static classmap_def classmap[] = {
- { agl_phone, 0, agl_output, "phone" },
- { agl_player, 0, agl_output, "default" },
- { agl_radio, 0, agl_output, "default" },
- { agl_navigator,0, agl_output, "default" },
- { agl_event, 0, agl_output, "default" },
+ { agl_phone, 0, agl_input, "Phone" },
+ { agl_player, 0, agl_input, "default" },
+ { agl_radio, 0, agl_input, "default" },
+ { agl_navigator,0, agl_input, "default" },
+ { agl_event, 0, agl_input, "default" },
{ agl_node_type_unknown, 0, agl_direction_unknown, NULL }
};
agl_zoneset_add_zone (u, z->name, (uint32_t)(z - zones));
for (r = rtgroups; r->name; r++)
- agl_router_create_rtgroup (u, r->type, r->name, r->accept, r->compare);
+ agl_router_create_rtgroup (u, r->type, r->name, r->node_desc,
+ r->accept, r->compare);
for (c = classmap; c->rtgroup; c++)
agl_router_assign_class_to_rtgroup (u, c->class, c->zone,
typedef struct {
agl_direction type; /* agl_input/agl_output */
const char *name;
+ const char *node_desc;
agl_rtgroup_accept_t accept;
agl_rtgroup_compare_t compare;
} rtgroup_def;
case agl_alert: return "Alert";
case agl_event: return "Event";
case agl_system: return "System";
- default: return "<user defined>";
+ default: return "default";
}
}
return 1;
}
-agl_rtgroup *agl_router_create_rtgroup (struct userdata *u, agl_direction type, const char *name, agl_rtgroup_accept_t accept, agl_rtgroup_compare_t compare)
+agl_rtgroup *agl_router_create_rtgroup (struct userdata *u, agl_direction type, const char *name, const char *node_desc, agl_rtgroup_accept_t accept, agl_rtgroup_compare_t compare)
{
agl_router *router;
agl_rtgroup *rtg;
+ agl_nodeset *nodeset;
+ agl_node *node;
pa_hashmap *table;
pa_assert (u);
pa_assert (type == agl_input || type == agl_output);
pa_assert (name);
- pa_assert (accept);
- pa_assert (compare);
pa_assert_se (router = u->router);
+ pa_assert_se (nodeset = u->nodeset);
if (type == agl_input)
table = router->rtgroups.input;
rtg->accept = accept;
rtg->compare = compare;
AGL_DLIST_INIT(rtg->entries);
+ /* associate an agl_output node for an agl_input routing group */
+ if (type == agl_input) {
+ node = agl_node_create (u, NULL);
+ node->direction = agl_output;
+ node->implement = agl_device;
+ node->visible = true;
+ node->available = true;
+ node->paname = pa_xstrdup (node_desc);
+ /* add to global nodeset */
+ pa_idxset_put (nodeset->nodes, node, &node->index);
+ rtg->node = node;
+ } else {
+ rtg->node = NULL;
+ }
+
pa_hashmap_put (table, rtg->name, rtg);
void agl_router_register_node (struct userdata *u, agl_node *node)
{
+ agl_router *router;
+ agl_rtgroup *rtg;
+
pa_assert (u);
pa_assert (node);
+ pa_assert_se (router = u->router);
- implement_default_route (u, node, NULL, agl_utils_new_stamp ());
+ /* we try to discover node routing group from the configuration, "Phone" for instance,
+ * see defaults in "config.c. Otherwise we just say NULL, a.k.a. default */
+ if (node->direction == agl_input) {
+ rtg = pa_hashmap_get (router->rtgroups.input, agl_node_type_str (node->type));
+ if (rtg)
+ implement_default_route (u, node, rtg->node, agl_utils_new_stamp ());
+ else
+ implement_default_route (u, node, NULL, agl_utils_new_stamp ());
+ } else {
+ rtg = pa_hashmap_get (router->rtgroups.output, agl_node_type_str (node->type));
+ if (rtg)
+ implement_default_route (u, rtg->node, node, agl_utils_new_stamp ());
+ else
+ implement_default_route (u, NULL, node, agl_utils_new_stamp ());
+ }
}
void agl_router_unregister_node (struct userdata *u, agl_node *node)
typedef int (*agl_rtgroup_compare_t)(struct userdata *, agl_rtgroup *, agl_node *, agl_node *);
struct agl_rtgroup {
- char *name; /**< name of the rtgroup */
+ char *name; /**< name of the rtgroup */
agl_dlist entries; /**< listhead of ordered rtentries */
+ agl_node *node; /**< final node */
agl_rtgroup_accept_t accept; /**< function pointer, whether to accept a node or not */
agl_rtgroup_compare_t compare; /**< function pointer, comparision for ordering */
};
int agl_router_default_compare (struct userdata *, agl_rtgroup *, agl_node *, agl_node *);
int agl_router_phone_compare (struct userdata *, agl_rtgroup *, agl_node *, agl_node *);
-agl_rtgroup *agl_router_create_rtgroup (struct userdata *, agl_direction, const char *, agl_rtgroup_accept_t, agl_rtgroup_compare_t);
+agl_rtgroup *agl_router_create_rtgroup (struct userdata *, agl_direction, const char *, const char *, agl_rtgroup_accept_t, agl_rtgroup_compare_t);
void agl_router_destroy_rtgroup (struct userdata *, agl_direction, const char *);
bool agl_router_assign_class_to_rtgroup (struct userdata *, agl_node_type, uint32_t, agl_direction, const char *);
void agl_router_assign_class_priority (struct userdata *, agl_node_type, int);
/* DEVICE DESTINATION */
case agl_device:
- /* IF THERE IS NO SOURCE : DEFAULT OUTPUT PREROUTE */
- /* if (!from)
- return setup_device_output(u, to) != NULL;
- else { */
switch (from->implement) {
/* STREAM TO DEVICE : OK */
case agl_stream:
- //if (!setup_default_stream2dev_link (u, from, to))
- // return false;
+ sink = agl_utils_get_alsa_sink (u, to->paname);
+ source = agl_utils_get_null_source (u, from->nullsink);
+
+ from->loopnode = agl_loopnode_create (u, AGL_LOOPNODE_SINK, from->index, source->index, sink->index);
break;
/* DEVICE TO DEVICE : OK */
case agl_device:
pa_assert_se ((core = u->core));
PA_IDXSET_FOREACH(sink, core->sinks, idx) {
- if (sink->name && strstr (sink->name, "alsa_output"))
+ if (sink->name && strstr (sink->name, "alsa_output") && strstr (sink->name, "pci"))
return sink;
}
return NULL;
}
+pa_sink *agl_utils_get_alsa_sink (struct userdata *u, const char *name)
+{
+ pa_core *core;
+ pa_sink *sink;
+ int idx;
+
+ pa_assert (u);
+ pa_assert_se ((core = u->core));
+
+ PA_IDXSET_FOREACH(sink, core->sinks, idx) {
+ if (sink->name && strstr (sink->name, "alsa_output")
+ && strstr (sink->name, name))
+ return sink;
+ }
+
+ return NULL;
+}
+
void agl_utils_init_stamp (void)
{
stamp = 0;
const char *agl_utils_get_sink_input_name (pa_sink_input *);
const char *agl_utils_get_source_output_name (pa_source_output *);
pa_sink *agl_utils_get_primary_alsa_sink (struct userdata *);
+pa_sink *agl_utils_get_alsa_sink (struct userdata *, const char *);
void agl_utils_init_stamp (void);
uint32_t agl_utils_new_stamp (void);
uint32_t agl_utils_get_stamp (void);