summaryrefslogtreecommitdiff
path: root/ext/jack/gstjackaudiosrc.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/jack/gstjackaudiosrc.c')
-rw-r--r--ext/jack/gstjackaudiosrc.c127
1 files changed, 110 insertions, 17 deletions
diff --git a/ext/jack/gstjackaudiosrc.c b/ext/jack/gstjackaudiosrc.c
index 11f4f9157..40784fa4a 100644
--- a/ext/jack/gstjackaudiosrc.c
+++ b/ext/jack/gstjackaudiosrc.c
@@ -407,7 +407,6 @@ gst_jack_ring_buffer_acquire (GstAudioRingBuffer * buf,
{
GstJackAudioSrc *src;
GstJackRingBuffer *abuf;
- const char **ports;
gint sample_rate, buffer_size;
gint i, bpf, rate, channels, res;
jack_client_t *client;
@@ -467,20 +466,38 @@ gst_jack_ring_buffer_acquire (GstAudioRingBuffer * buf,
/* if we need to automatically connect the ports, do so now. We must do this
* after activating the client. */
if (src->connect == GST_JACK_CONNECT_AUTO
- || src->connect == GST_JACK_CONNECT_AUTO_FORCED) {
+ || src->connect == GST_JACK_CONNECT_AUTO_FORCED
+ || src->connect == GST_JACK_CONNECT_EXPLICIT) {
+ const char **available_ports = NULL;
+ const char **jack_ports = NULL;
+ char **user_ports = NULL;
+
/* find all the physical output ports. A physical output port is a port
* associated with a hardware device. Someone needs connect to a physical
* port in order to capture something. */
- if (src->port_pattern == NULL) {
- ports = jack_get_ports (client, NULL, NULL,
- JackPortIsPhysical | JackPortIsOutput);
- } else {
- ports = jack_get_ports (client, src->port_pattern, NULL,
- JackPortIsOutput);
+ if (src->port_names) {
+ user_ports = gst_jack_audio_client_get_port_names_from_string (client,
+ src->port_names, JackPortIsOutput);
+
+ if (user_ports)
+ available_ports = (const char **) user_ports;
}
- if (ports == NULL) {
+ if (!available_ports && src->connect == GST_JACK_CONNECT_EXPLICIT)
+ goto wrong_port_names;
+
+ if (!available_ports) {
+ if (!src->port_pattern) {
+ jack_ports = jack_get_ports (client, NULL, NULL,
+ JackPortIsPhysical | JackPortIsOutput);
+ } else {
+ jack_ports = jack_get_ports (client, src->port_pattern, NULL,
+ JackPortIsOutput);
+ }
+ }
+
+ if (!available_ports) {
/* no ports? fine then we don't do anything except for posting a warning
* message. */
GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL),
@@ -490,7 +507,7 @@ gst_jack_ring_buffer_acquire (GstAudioRingBuffer * buf,
for (i = 0; i < channels; i++) {
/* stop when all output ports are exhausted */
- if (ports[i] == NULL) {
+ if (!available_ports[i]) {
/* post a warning that we could not connect all ports */
GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL),
("No more physical ports, leaving some ports unconnected"));
@@ -500,11 +517,18 @@ gst_jack_ring_buffer_acquire (GstAudioRingBuffer * buf,
jack_port_name (src->ports[i]));
/* connect the physical port to a port */
- res = jack_connect (client, ports[i], jack_port_name (src->ports[i]));
- if (res != 0 && res != EEXIST)
+ res = jack_connect (client,
+ available_ports[i], jack_port_name (src->ports[i]));
+ if (res != 0 && res != EEXIST) {
+ jack_free (jack_ports);
+ g_strfreev (user_ports);
+
goto cannot_connect;
+ }
}
- jack_free (ports);
+
+ jack_free (jack_ports);
+ g_strfreev (user_ports);
}
done:
@@ -539,7 +563,12 @@ cannot_connect:
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
("Could not connect input ports to physical ports (%d:%s)",
res, g_strerror (res)));
- jack_free (ports);
+ return FALSE;
+ }
+wrong_port_names:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
+ ("Invalid port-names was provided"));
return FALSE;
}
}
@@ -701,6 +730,7 @@ enum
PROP_PORT_PATTERN,
PROP_TRANSPORT,
PROP_LOW_LATENCY,
+ PROP_PORT_NAMES,
PROP_LAST
};
@@ -825,6 +855,19 @@ gst_jack_audio_src_class_init (GstJackAudioSrcClass * klass)
GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ /**
+ * GstJackAudioSrc:port-names:
+ *
+ * Comma-separated list of port name including "client_name:" prefix
+ *
+ * Since: 1.20
+ */
+ g_object_class_install_property (gobject_class, PROP_PORT_NAMES,
+ g_param_spec_string ("port-names", "Port Names",
+ "Comma-separated list of port name including \"client_name:\" prefix",
+ NULL, GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
gst_element_class_set_static_metadata (gstelement_class,
@@ -875,6 +918,8 @@ gst_jack_audio_src_dispose (GObject * object)
src->port_pattern = NULL;
}
+ g_clear_pointer (&src->port_names, g_free);
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -912,6 +957,10 @@ gst_jack_audio_src_set_property (GObject * object, guint prop_id,
case PROP_LOW_LATENCY:
src->low_latency = g_value_get_boolean (value);
break;
+ case PROP_PORT_NAMES:
+ g_free (src->port_names);
+ src->port_names = g_value_dup_string (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -946,6 +995,9 @@ gst_jack_audio_src_get_property (GObject * object, guint prop_id,
case PROP_LOW_LATENCY:
g_value_set_boolean (value, src->low_latency);
break;
+ case PROP_PORT_NAMES:
+ g_value_set_string (value, src->port_names);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -964,14 +1016,42 @@ gst_jack_audio_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
if (src->client == NULL)
goto no_client;
+ if (src->connect == GST_JACK_CONNECT_EXPLICIT && !src->port_names)
+ goto no_port_names;
+
client = gst_jack_audio_client_get_client (src->client);
- if (src->connect == GST_JACK_CONNECT_AUTO) {
+ if (src->connect == GST_JACK_CONNECT_AUTO ||
+ src->connect == GST_JACK_CONNECT_EXPLICIT) {
+ max = 0;
+
+ if (src->port_names) {
+ gchar **user_ports =
+ gst_jack_audio_client_get_port_names_from_string (client,
+ src->port_names, JackPortIsOutput);
+
+ if (user_ports) {
+ max = g_strv_length (user_ports);
+ } else {
+ GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND,
+ ("Invalid \"port-names\" was requested"),
+ ("Requested \"port-names\" %s contains invalid name",
+ src->port_names));
+ }
+
+ g_strfreev (user_ports);
+ }
+
+ if (max > 0)
+ goto found;
+
+ if (src->connect == GST_JACK_CONNECT_EXPLICIT)
+ goto no_port_names;
+
/* get a port count, this is the number of channels we can automatically
* connect. */
ports = jack_get_ports (client, NULL, NULL,
JackPortIsPhysical | JackPortIsOutput);
- max = 0;
if (ports != NULL) {
for (; ports[max]; max++);
@@ -983,7 +1063,13 @@ gst_jack_audio_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
* pads. */
max = G_MAXINT;
}
- min = MIN (1, max);
+
+found:
+ if (src->connect == GST_JACK_CONNECT_EXPLICIT) {
+ min = max;
+ } else {
+ min = MIN (1, max);
+ }
rate = jack_get_sample_rate (client);
@@ -1011,6 +1097,13 @@ no_client:
/* base class will get template caps for us when we return NULL */
return NULL;
}
+no_port_names:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS,
+ ("User must provide valid port names"),
+ ("\"port-names\" contains invalid name or NULL string"));
+ return NULL;
+ }
}
static GstAudioRingBuffer *