mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
audio-dsp: handle node remove
Handle dynamic samplerate and channels Improve node names Keep track of removed nodes
This commit is contained in:
parent
08484b92f5
commit
d2c545be8d
1 changed files with 54 additions and 22 deletions
|
|
@ -21,6 +21,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
|
@ -117,7 +118,9 @@ struct port {
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
|
|
||||||
struct pw_node *node;
|
struct pw_node *node;
|
||||||
|
struct spa_hook node_listener;
|
||||||
|
|
||||||
struct impl *impl;
|
struct impl *impl;
|
||||||
|
|
||||||
|
|
@ -394,8 +397,10 @@ static int port_enum_formats(struct spa_node *node,
|
||||||
"I", t->media_subtype.raw,
|
"I", t->media_subtype.raw,
|
||||||
":", t->format_audio.format, "I", t->audio_format.S16,
|
":", t->format_audio.format, "I", t->audio_format.S16,
|
||||||
":", t->format_audio.layout, "i", SPA_AUDIO_LAYOUT_INTERLEAVED,
|
":", t->format_audio.layout, "i", SPA_AUDIO_LAYOUT_INTERLEAVED,
|
||||||
":", t->format_audio.rate, "i", n->sample_rate,
|
":", t->format_audio.rate, "iru", n->sample_rate,
|
||||||
":", t->format_audio.channels, "i", n->channels);
|
SPA_POD_PROP_MIN_MAX(1, INT32_MAX),
|
||||||
|
":", t->format_audio.channels, "iru", n->channels,
|
||||||
|
SPA_POD_PROP_MIN_MAX(1, MAX_PORTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -475,6 +480,8 @@ static int port_set_format(struct spa_node *node, struct port *p,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pw_log_info(NAME " %p: set format on port %p", n, p);
|
pw_log_info(NAME " %p: set format on port %p", n, p);
|
||||||
|
n->sample_rate = info.info.raw.rate;
|
||||||
|
n->channels = info.info.raw.channels;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -729,36 +736,42 @@ static struct port *make_port(struct node *n, enum pw_direction direction,
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pw_node *make_node(struct impl *impl, const struct pw_properties *props,
|
static struct node *make_node(struct impl *impl, const struct pw_properties *props,
|
||||||
enum pw_direction direction)
|
enum pw_direction direction)
|
||||||
{
|
{
|
||||||
struct pw_node *node;
|
struct pw_node *node;
|
||||||
struct node *n;
|
struct node *n;
|
||||||
struct port *p;
|
struct port *p;
|
||||||
const char *alias;
|
const char *api, *alias, *plugged;
|
||||||
char node_name[128];
|
char node_name[128];
|
||||||
|
struct pw_properties *pr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ((alias = pw_properties_get(props, "alsa.device")) == NULL)
|
if ((api = pw_properties_get(props, "device.api")) == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if ((alias = pw_properties_get(props, "device.name")) == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
|
||||||
snprintf(node_name, sizeof(node_name), "system_%s", alias);
|
snprintf(node_name, sizeof(node_name), "system_%s", alias);
|
||||||
for (i = 0; node_name[i]; i++) {
|
for (i = 0; node_name[i]; i++) {
|
||||||
if (node_name[i] == ':' || node_name[i] == ',')
|
if (node_name[i] == ':' || node_name[i] == ',')
|
||||||
node_name[i] = '_';
|
node_name[i] = '_';
|
||||||
}
|
}
|
||||||
if ((alias = pw_properties_get(props, "alsa.card")) == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
node = pw_node_new(impl->core, node_name,
|
pr = pw_properties_new(
|
||||||
pw_properties_new(
|
"media.class",
|
||||||
"alsa.card", alias,
|
direction == PW_DIRECTION_OUTPUT ?
|
||||||
"media.class",
|
"Audio/DSP/Playback" :
|
||||||
direction == PW_DIRECTION_OUTPUT ?
|
"Audio/DSP/Capture",
|
||||||
"Audio/DSP/Playback" :
|
"device.name", alias,
|
||||||
"Audio/DSP/Capture",
|
NULL);
|
||||||
NULL),
|
|
||||||
sizeof(struct node));
|
if ((plugged = pw_properties_get(props, "node.plugged")) != NULL)
|
||||||
|
pw_properties_set(pr, "node.plugged", plugged);
|
||||||
|
|
||||||
|
node = pw_node_new(impl->core, node_name, pr, sizeof(struct node));
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
@ -784,7 +797,8 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
|
||||||
snprintf(port_name, sizeof(port_name), "%s_%d",
|
snprintf(port_name, sizeof(port_name), "%s_%d",
|
||||||
direction == PW_DIRECTION_INPUT ? "playback" : "capture",
|
direction == PW_DIRECTION_INPUT ? "playback" : "capture",
|
||||||
n->port_count[direction]);
|
n->port_count[direction]);
|
||||||
snprintf(alias_name, sizeof(alias_name), "alsa_pcm:%s:%s%d",
|
snprintf(alias_name, sizeof(alias_name), "%s_pcm:%s:%s%d",
|
||||||
|
api,
|
||||||
alias,
|
alias,
|
||||||
direction == PW_DIRECTION_INPUT ? "in" : "out",
|
direction == PW_DIRECTION_INPUT ? "in" : "out",
|
||||||
n->port_count[direction]);
|
n->port_count[direction]);
|
||||||
|
|
@ -805,7 +819,7 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
|
||||||
pw_node_register(node, NULL, pw_module_get_global(impl->module), NULL);
|
pw_node_register(node, NULL, pw_module_get_global(impl->module), NULL);
|
||||||
pw_node_set_active(node, true);
|
pw_node_set_active(node, true);
|
||||||
|
|
||||||
return node;
|
return n;
|
||||||
|
|
||||||
error_free_node:
|
error_free_node:
|
||||||
pw_node_destroy(node);
|
pw_node_destroy(node);
|
||||||
|
|
@ -813,16 +827,31 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void node_destroy(void *data)
|
||||||
|
{
|
||||||
|
struct node *node = data;
|
||||||
|
|
||||||
|
spa_list_remove(&node->link);
|
||||||
|
pw_node_destroy(node->node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pw_node_events node_events = {
|
||||||
|
PW_VERSION_NODE_EVENTS,
|
||||||
|
.destroy = node_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
static int on_global(void *data, struct pw_global *global)
|
static int on_global(void *data, struct pw_global *global)
|
||||||
{
|
{
|
||||||
struct impl *impl = data;
|
struct impl *impl = data;
|
||||||
struct pw_node *n, *node;
|
struct pw_node *n;
|
||||||
|
struct node *node;
|
||||||
const struct pw_properties *properties;
|
const struct pw_properties *properties;
|
||||||
const char *str;
|
const char *str;
|
||||||
char *error;
|
char *error;
|
||||||
struct pw_port *ip, *op;
|
struct pw_port *ip, *op;
|
||||||
struct pw_link *link;
|
struct pw_link *link;
|
||||||
|
|
||||||
|
|
||||||
if (pw_global_get_type(global) != impl->t->node)
|
if (pw_global_get_type(global) != impl->t->node)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -832,12 +861,14 @@ static int on_global(void *data, struct pw_global *global)
|
||||||
if ((str = pw_properties_get(properties, "media.class")) == NULL)
|
if ((str = pw_properties_get(properties, "media.class")) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
pw_log_debug("global added %s", str);
|
||||||
|
|
||||||
if (strcmp(str, "Audio/Sink") == 0) {
|
if (strcmp(str, "Audio/Sink") == 0) {
|
||||||
if ((ip = pw_node_get_free_port(n, PW_DIRECTION_INPUT)) == NULL)
|
if ((ip = pw_node_get_free_port(n, PW_DIRECTION_INPUT)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
if ((node = make_node(impl, properties, PW_DIRECTION_OUTPUT)) == NULL)
|
if ((node = make_node(impl, properties, PW_DIRECTION_OUTPUT)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
if ((op = pw_node_get_free_port(node, PW_DIRECTION_OUTPUT)) == NULL)
|
if ((op = pw_node_get_free_port(node->node, PW_DIRECTION_OUTPUT)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (strcmp(str, "Audio/Source") == 0) {
|
else if (strcmp(str, "Audio/Source") == 0) {
|
||||||
|
|
@ -845,7 +876,7 @@ static int on_global(void *data, struct pw_global *global)
|
||||||
return 0;
|
return 0;
|
||||||
if ((node = make_node(impl, properties, PW_DIRECTION_INPUT)) == NULL)
|
if ((node = make_node(impl, properties, PW_DIRECTION_INPUT)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
if ((ip = pw_node_get_free_port(node, PW_DIRECTION_INPUT)) == NULL)
|
if ((ip = pw_node_get_free_port(node->node, PW_DIRECTION_INPUT)) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -862,9 +893,10 @@ static int on_global(void *data, struct pw_global *global)
|
||||||
free(error);
|
free(error);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pw_link_register(link, NULL, pw_module_get_global(impl->module), NULL);
|
pw_link_register(link, NULL, pw_module_get_global(impl->module), NULL);
|
||||||
|
|
||||||
|
pw_node_add_listener(n, &node->node_listener, &node_events, node);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue