summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Bachmann <manuel.bachmann@iot.bzh>2016-07-07 17:29:08 +0200
committerYannick Gicquel <yannick.gicquel@iot.bzh>2016-10-11 17:09:07 +0200
commitcc70e0ae30920ca835bf011f8040afb6fea43f45 (patch)
treec4d503c5a556bee69842f38b28e85a182c70bfb8
parent2478974dfde05063cbf0233e3d3c434ca2f46c7c (diff)
Implement routing groups and volume ramp up/down
Change-Id: I0e9d3b8b8be4d124907214c165617d86be6906fc Signed-off-by: Manuel Bachmann <manuel.bachmann@iot.bzh>
-rw-r--r--config.c5
-rw-r--r--config.h2
-rw-r--r--discover.c20
-rw-r--r--node.c38
-rw-r--r--node.h3
-rw-r--r--router.c102
-rw-r--r--router.h12
-rw-r--r--switch.c2
-rw-r--r--utils.c35
-rw-r--r--utils.h1
10 files changed, 190 insertions, 30 deletions
diff --git a/config.c b/config.c
index b978296..bbd8110 100644
--- a/config.c
+++ b/config.c
@@ -74,13 +74,12 @@ static zone_def zones[] = {
{ NULL }
};
-
static rtgroup_def rtgroups[] = {
{ agl_input,
"Phone",
"PhoneCard",
agl_router_phone_accept,
- agl_router_phone_compare
+ agl_router_phone_effect
},
{ 0, NULL, NULL, NULL, NULL }
@@ -128,7 +127,7 @@ bool use_default_configuration (struct userdata *u)
for (r = rtgroups; r->name; r++)
agl_router_create_rtgroup (u, r->type, r->name, r->node_desc,
- r->accept, r->compare);
+ r->accept, r->effect);
for (c = classmap; c->rtgroup; c++)
agl_router_assign_class_to_rtgroup (u, c->class, c->zone,
diff --git a/config.h b/config.h
index f39c9fb..be0098d 100644
--- a/config.h
+++ b/config.h
@@ -36,7 +36,7 @@ typedef struct {
const char *name;
const char *node_desc;
agl_rtgroup_accept_t accept;
- agl_rtgroup_compare_t compare;
+ agl_rtgroup_effect_t effect;
} rtgroup_def;
/* CLASS MAP (agl_phone="phone" card routing group...) */
diff --git a/discover.c b/discover.c
index 79164bb..ca3591b 100644
--- a/discover.c
+++ b/discover.c
@@ -743,12 +743,10 @@ void agl_discover_register_source_output (struct userdata *u, pa_source_output *
void agl_discover_add_sink_input (struct userdata *u, pa_sink_input *sinp)
{
- pa_core *core;
agl_node *node;
pa_assert (u);
pa_assert (sinp);
- pa_assert_se (core = u->core);
if (!sinp->client)
return;
@@ -759,16 +757,22 @@ void agl_discover_add_sink_input (struct userdata *u, pa_sink_input *sinp)
/* start routing */
agl_router_register_node (u, node);
+
+ /* apply priority effects */
+ agl_router_apply_node_priority_effect (u, node, true);
}
void agl_discover_remove_sink_input (struct userdata *u, pa_sink_input *sinp)
{
- pa_core *core;
- agl_node *node;
+ agl_nodeset *nodeset;
+ agl_node *node, *n;
+ pa_sink *sink;
+ int priority;
+ uint32_t index;
pa_assert (u);
pa_assert (sinp);
- pa_assert_se (core = u->core);
+ pa_assert_se (nodeset = u->nodeset);
if (!sinp->client)
return;
@@ -779,4 +783,10 @@ void agl_discover_remove_sink_input (struct userdata *u, pa_sink_input *sinp)
/* stop routing */
agl_router_unregister_node (u, node);
+
+ /* un-apply priority effects */
+ agl_router_apply_node_priority_effect (u, node, false);
+
+ /* remove node */
+ agl_node_destroy (u, node);
}
diff --git a/node.c b/node.c
index 1876a67..c85d512 100644
--- a/node.c
+++ b/node.c
@@ -20,6 +20,7 @@
*
*/
#include "node.h"
+#include "router.h"
#include <pulsecore/idxset.h>
@@ -129,12 +130,22 @@ agl_node *agl_node_create (struct userdata *u, agl_node *data)
}
}
- /* TODO : register the node to the router */
- /* agl_router_register_node (u, node); */
-
return node;
}
+void agl_node_destroy (struct userdata *u, agl_node *node)
+{
+ agl_nodeset *ns;
+
+ pa_assert (u);
+ pa_assert (node);
+ pa_assert_se (ns = u->nodeset);
+
+ pa_idxset_remove_by_index (ns->nodes, node->index);
+
+ pa_xfree (node);
+}
+
const char *agl_node_type_str (agl_node_type type)
{
switch (type) {
@@ -208,3 +219,24 @@ agl_node *agl_node_get_from_client (struct userdata *u, pa_client *client)
return NULL;
}
+
+bool agl_node_has_highest_priority (struct userdata *u, agl_node *node)
+{
+ agl_nodeset *nodeset;
+ agl_node *n;
+ int priority;
+ uint32_t index;
+
+ pa_assert (u);
+ pa_assert (node);
+ pa_assert (nodeset = u->nodeset);
+
+ priority = agl_router_get_node_priority (u, node);
+
+ PA_IDXSET_FOREACH(n, nodeset->nodes, index) {
+ if ((n != node) && (agl_router_get_node_priority (u, n) >= priority))
+ return false;
+ }
+
+ return true;
+}
diff --git a/node.h b/node.h
index 30c375b..837ff5a 100644
--- a/node.h
+++ b/node.h
@@ -104,10 +104,13 @@ void agl_nodeset_done (struct userdata *);
int agl_nodeset_add_role (struct userdata *, const char *, agl_node_type, agl_nodeset_resdef *);
agl_node *agl_node_create (struct userdata *, agl_node *);
+void agl_node_destroy (struct userdata *, agl_node *);
const char *agl_node_type_str (agl_node_type);
const char *agl_node_direction_str (agl_direction);
agl_node *agl_node_get_from_data (struct userdata *, agl_direction, void *);
agl_node *agl_node_get_from_client (struct userdata *, pa_client *);
+bool agl_node_has_highest_priority (struct userdata *, agl_node *);
+
#endif
diff --git a/router.c b/router.c
index e47a3d3..4ef0180 100644
--- a/router.c
+++ b/router.c
@@ -97,19 +97,26 @@ bool agl_router_phone_accept (struct userdata *u, agl_rtgroup *rtg, agl_node *no
return true;
}
-int agl_router_default_compare (struct userdata *u, agl_rtgroup *rtg, agl_node *n1, agl_node *n2)
+int agl_router_default_effect (struct userdata *u, agl_rtgroup *rtg, agl_node *node, bool new)
{
/* TODO */
return 1;
}
-int agl_router_phone_compare (struct userdata *u, agl_rtgroup *rtg, agl_node *n1, agl_node *n2)
+int agl_router_phone_effect (struct userdata *u, agl_rtgroup *rtg, agl_node *node, bool new)
{
- /* TODO */
+ pa_assert (u);
+ pa_assert (node);
+
+ if (new)
+ agl_utils_volume_ramp (u, node->nullsink, false);
+ else
+ agl_utils_volume_ramp (u, node->nullsink, true);
+
return 1;
}
-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_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_effect_t effect)
{
agl_router *router;
agl_rtgroup *rtg;
@@ -132,7 +139,7 @@ agl_rtgroup *agl_router_create_rtgroup (struct userdata *u, agl_direction type,
rtg = pa_xnew0 (agl_rtgroup, 1);
rtg->name = pa_xstrdup (name);
rtg->accept = accept;
- rtg->compare = compare;
+ rtg->effect = effect;
AGL_DLIST_INIT(rtg->entries);
/* associate an agl_output node for an agl_input routing group */
if (type == agl_input) {
@@ -194,7 +201,7 @@ bool agl_router_assign_class_to_rtgroup (struct userdata *u, agl_node_type class
agl_zone *rzone;
pa_assert (u);
- pa_assert (zone < AGL_ZONE_MAX);
+ pa_assert (zone < AGL_ZONE_MAX);
pa_assert (type == agl_input || type == agl_output);
pa_assert (name);
pa_assert_se (router = u->router);
@@ -225,7 +232,7 @@ bool agl_router_assign_class_to_rtgroup (struct userdata *u, agl_node_type class
}
zonemap = classmap[zone];
- if (!zonemap) { /* THIS LOOKS LIKE A HACK TO IGNORE THE ERROR... */
+ if (!zonemap) {
zonemap = pa_xnew0 (agl_rtgroup *, router->maplen);
classmap[zone] = zonemap;
}
@@ -261,6 +268,81 @@ void agl_router_assign_class_priority (struct userdata *u, agl_node_type class,
}
}
+int agl_router_get_node_priority (struct userdata *u, agl_node *node)
+{
+ agl_router *router;
+ int class;
+
+ pa_assert (u);
+ pa_assert (node);
+ pa_assert_se (router = u->router);
+
+ class = node->type;
+
+ if (class < 0 || class >= (int)router->maplen)
+ return 0;
+
+ return router->priormap[class];
+}
+
+bool agl_router_apply_node_priority_effect (struct userdata *u, agl_node *node, bool new)
+{
+ agl_router *router;
+ agl_rtgroup *rtg;
+ agl_nodeset *nodeset;
+ agl_node *n;
+ pa_sink *sink;
+ int priority;
+ uint32_t index;
+
+ pa_assert (u);
+ pa_assert (node);
+ pa_assert_se (router = u->router);
+ pa_assert_se (nodeset = u->nodeset);
+
+ /* do we have a routing group associated with this node ? It may have a custom effect */
+ if (node->direction == agl_input)
+ rtg = pa_hashmap_get (router->rtgroups.input, agl_node_type_str (node->type));
+ else
+ rtg = pa_hashmap_get (router->rtgroups.output, agl_node_type_str (node->type));
+
+ /* now let us compare priorities, and apply effect if needed */
+ /* "new" case */
+ if (new) {
+ priority = agl_router_get_node_priority (u, node);
+ PA_IDXSET_FOREACH(n, nodeset->nodes, index) {
+ if (n->nullsink && (priority > agl_router_get_node_priority (u, n))) {
+ sink = agl_utils_get_null_sink (u, n->nullsink);
+ if (sink) {
+ /* do we have a custom effect ? otherwise, just mute it */
+ if (rtg && rtg->effect)
+ rtg->effect (u, rtg, n, new);
+ else
+ pa_sink_set_mute (sink, new, false);
+ }
+ }
+ }
+ } else {
+ /* "old" case */
+ if (!agl_node_has_highest_priority (u, node))
+ return true;
+ PA_IDXSET_FOREACH(n, nodeset->nodes, index) {
+ if (n->nullsink) {
+ sink = agl_utils_get_null_sink (u, n->nullsink);
+ if (sink) {
+ /* do we have a custom effect ? otherwise, just unmute it */
+ if (rtg && rtg->effect)
+ rtg->effect (u, rtg, n, new);
+ else
+ pa_sink_set_mute (sink, new, false);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
void agl_router_register_node (struct userdata *u, agl_node *node)
{
agl_router *router;
@@ -393,12 +475,10 @@ void implement_default_route (struct userdata *u,
agl_node *start, agl_node *end,
uint32_t stamp)
{
- if (start->direction == agl_input) {
+ if (start->direction == agl_input)
agl_switch_setup_link (u, start, end, false);
- //agl_volume_add_limiting_class(u, end, volume_class(start), stamp);
- } else {
+ else
agl_switch_setup_link (u, end, start, false);
- }
}
agl_node *find_default_route (struct userdata *u, agl_node *start, uint32_t stamp)
diff --git a/router.h b/router.h
index 0bf21d5..cc7bf95 100644
--- a/router.h
+++ b/router.h
@@ -29,14 +29,14 @@
#define AGL_ZONE_MAX 8 /* max 8 zones, demo is using 5 */ /* DEFINED IN MURPHY */
typedef bool (*agl_rtgroup_accept_t)(struct userdata *, agl_rtgroup *, agl_node *);
-typedef int (*agl_rtgroup_compare_t)(struct userdata *, agl_rtgroup *, agl_node *, agl_node *);
+typedef int (*agl_rtgroup_effect_t)(struct userdata *, agl_rtgroup *, agl_node *, bool new);
struct agl_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 */
+ agl_rtgroup_effect_t effect; /**< function pointer, custom action such as volume up, down */
};
typedef struct {
@@ -73,13 +73,15 @@ void agl_router_done (struct userdata *);
bool agl_router_default_accept (struct userdata *, agl_rtgroup *, agl_node *);
bool agl_router_phone_accept (struct userdata *, agl_rtgroup *, agl_node *);
-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 *);
+int agl_router_default_effect (struct userdata *, agl_rtgroup *, agl_node *, bool);
+int agl_router_phone_effect (struct userdata *, agl_rtgroup *, agl_node *, bool);
-agl_rtgroup *agl_router_create_rtgroup (struct userdata *, agl_direction, const char *, 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_effect_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);
+int agl_router_get_node_priority (struct userdata *, agl_node *);
+bool agl_router_apply_node_priority_effect (struct userdata *, agl_node *, bool);
void agl_router_register_node (struct userdata *, agl_node *);
void agl_router_unregister_node (struct userdata *, agl_node *);
diff --git a/switch.c b/switch.c
index 8111068..e3b5451 100644
--- a/switch.c
+++ b/switch.c
@@ -107,6 +107,7 @@ bool agl_switch_setup_link (struct userdata *u, agl_node *from, agl_node *to, bo
/* STREAM TO DEVICE : OK */
case agl_stream:
sink = agl_utils_get_alsa_sink (u, to->paname);
+ if (!sink) break;
source = agl_utils_get_null_source (u, from->nullsink);
from->loopnode = agl_loopnode_create (u, AGL_LOOPNODE_SINK, from->index, source->index, sink->index);
@@ -147,7 +148,6 @@ bool agl_switch_setup_link (struct userdata *u, agl_node *from, agl_node *to, bo
sink = agl_utils_get_primary_alsa_sink (u);
source = agl_utils_get_null_source (u, from->nullsink);
-
from->loopnode = agl_loopnode_create (u, AGL_LOOPNODE_SINK, from->index, source->index, sink->index);
}
}
diff --git a/utils.c b/utils.c
index 9476c69..a841e2c 100644
--- a/utils.c
+++ b/utils.c
@@ -120,6 +120,39 @@ pa_source *agl_utils_get_null_source (struct userdata *u, struct agl_null_sink *
return sink ? sink->monitor_source : NULL;
}
+void agl_utils_volume_ramp (struct userdata *u, struct agl_null_sink *ns, bool up)
+{
+ pa_core *core;
+ pa_sink *sink;
+ pa_sink_input *sinp;
+ uint32_t index;
+ pa_cvolume_ramp rampvol;
+ pa_volume_t newvol;
+ long time;
+
+ if (up) {
+ newvol = PA_VOLUME_NORM;
+ time = 5000;
+ } else {
+ newvol = PA_VOLUME_NORM *10/100;
+ time = 3000;
+ }
+
+ pa_assert (u);
+ pa_assert_se ((core = u->core));
+
+ sink = agl_utils_get_null_sink (u, ns);
+ PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
+ if (sinp->sink && sinp->sink == sink)
+ break;
+ sinp = NULL;
+ }
+ if (!sinp) return;
+
+ pa_cvolume_ramp_set (&rampvol, sinp->volume.channels, PA_VOLUME_RAMP_TYPE_LINEAR,
+ time, newvol);
+ pa_sink_input_set_volume_ramp (sinp, &rampvol, true, false);
+}
const char *agl_utils_get_card_name (pa_card *card)
{
@@ -196,7 +229,7 @@ pa_sink *agl_utils_get_primary_alsa_sink (struct userdata *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, "pci"))
+ if (sink->name && strstr (sink->name, "alsa_output"))
return sink;
}
diff --git a/utils.h b/utils.h
index 19faeb2..abe8bef 100644
--- a/utils.h
+++ b/utils.h
@@ -32,6 +32,7 @@ struct agl_null_sink *agl_utils_create_null_sink (struct userdata *, const char
void agl_utils_destroy_null_sink (struct userdata *, struct agl_null_sink *);
pa_sink *agl_utils_get_null_sink (struct userdata *, struct agl_null_sink *);
pa_source *agl_utils_get_null_source (struct userdata *, struct agl_null_sink *);
+void agl_utils_volume_ramp (struct userdata *, struct agl_null_sink *, bool);
/* general helper functions */
const char *agl_utils_get_card_name (pa_card *);