/* function is called with LOCK */ static gboolean gst_jack_ring_buffer_release (GstRingBuffer * buf) { GstJackAudioSrc *src; GstJackRingBuffer *abuf; gint res; abuf = GST_JACK_RING_BUFFER_CAST (buf); src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); GST_DEBUG_OBJECT (src, "release"); if ((res = gst_jack_audio_client_set_active (src->client, FALSE))) { /* we only warn, this means the server is probably shut down and the client * is gone anyway. */ GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL), ("Could not deactivate Jack client (%d)", res)); } abuf->channels = -1; abuf->buffer_size = -1; abuf->sample_rate = -1; /* free the buffer */ gst_buffer_unref (buf->data); buf->data = NULL; return TRUE; }
static void gst_jack_ring_buffer_finalize (GObject * object) { GstJackRingBuffer *ringbuffer; ringbuffer = GST_JACK_RING_BUFFER_CAST (object); G_OBJECT_CLASS (ring_parent_class)->finalize (object); }
/* this is the callback of jack. This should be RT-safe. * Writes samples from the jack input port's buffer to the gst ring buffer. */ static int jack_process_cb (jack_nframes_t nframes, void *arg) { GstJackAudioSrc *src; GstRingBuffer *buf; GstJackRingBuffer *abuf; gint len, givenLen; guint8 *writeptr, *dataStart; gint writeseg; gint channels, i, j; sample_t **buffers, *data; buf = GST_RING_BUFFER_CAST (arg); abuf = GST_JACK_RING_BUFFER_CAST (arg); src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); channels = buf->spec.channels; len = sizeof (sample_t) * nframes * channels; /* alloc pointers to samples */ buffers = g_alloca (sizeof (sample_t *) * channels); data = g_alloca (len); /* get input buffers */ for (i = 0; i < channels; i++) buffers[i] = (sample_t *) jack_port_get_buffer (src->ports[i], nframes); //writeptr = data; dataStart = (guint8 *) data; /* the samples in the jack input buffers have to be interleaved into the * ringbuffer */ for (i = 0; i < nframes; ++i) for (j = 0; j < channels; ++j) *data++ = buffers[j][i]; if (gst_ring_buffer_prepare_read (buf, &writeseg, &writeptr, &givenLen)) { memcpy (writeptr, (char *) dataStart, givenLen); GST_DEBUG ("copy %d frames: %p, %d bytes, %d channels", nframes, writeptr, len / channels, channels); /* clear written samples in the ringbuffer */ // gst_ring_buffer_clear(buf, 0); /* we wrote one segment */ gst_ring_buffer_advance (buf, 1); } return 0; }
/* we error out */ static int jack_buffer_size_cb (jack_nframes_t nframes, void *arg) { GstJackAudioSrc *src; GstJackRingBuffer *abuf; abuf = GST_JACK_RING_BUFFER_CAST (arg); src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (arg)); if (abuf->buffer_size != -1 && abuf->buffer_size != nframes) goto not_supported; return 0; /* ERRORS */ not_supported: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Jack changed the buffer size, which is not supported")); return 1; } }
/* we error out */ static int jack_sample_rate_cb (jack_nframes_t nframes, void *arg) { GstJackAudioSink *sink; GstJackRingBuffer *abuf; abuf = GST_JACK_RING_BUFFER_CAST (arg); sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (arg)); if (abuf->sample_rate != -1 && abuf->sample_rate != nframes) goto not_supported; return 0; /* ERRORS */ not_supported: { GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL), ("Jack changed the sample rate, which is not supported")); return 1; } }
/* allocate a buffer and setup resources to process the audio samples of * the format as specified in @spec. * * We allocate N jack ports, one for each channel. If we are asked to * automatically make a connection with physical ports, we connect as many * ports as there are physical ports, leaving leftover ports unconnected. * * It is assumed that samplerate and number of channels are acceptable since our * getcaps method will always provide correct values. If unacceptable caps are * received for some reason, we fail here. */ static gboolean gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) { GstJackAudioSrc *src; GstJackRingBuffer *abuf; const char **ports; gint sample_rate, buffer_size; gint i, channels, res; jack_client_t *client; src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); abuf = GST_JACK_RING_BUFFER_CAST (buf); GST_DEBUG_OBJECT (src, "acquire"); client = gst_jack_audio_client_get_client (src->client); /* sample rate must be that of the server */ sample_rate = jack_get_sample_rate (client); if (sample_rate != spec->rate) goto wrong_samplerate; channels = spec->channels; if (!gst_jack_audio_src_allocate_channels (src, channels)) goto out_of_ports; buffer_size = jack_get_buffer_size (client); /* the segment size in bytes, this is large enough to hold a buffer of 32bit floats * for all channels */ spec->segsize = buffer_size * sizeof (gfloat) * channels; spec->latency_time = gst_util_uint64_scale (spec->segsize, (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample); /* segtotal based on buffer-time latency */ spec->segtotal = spec->buffer_time / spec->latency_time; GST_DEBUG_OBJECT (src, "segsize %d, segtotal %d", spec->segsize, spec->segtotal); /* allocate the ringbuffer memory now */ buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); if ((res = gst_jack_audio_client_set_active (src->client, TRUE))) goto could_not_activate; /* 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) { /* 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. */ ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); if (ports == NULL) { /* no ports? fine then we don't do anything except for posting a warning * message. */ GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), ("No physical output ports found, leaving ports unconnected")); goto done; } for (i = 0; i < channels; i++) { /* stop when all output ports are exhausted */ if (ports[i] == NULL) { /* 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")); break; } GST_DEBUG_OBJECT (src, "try connecting to %s", 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])); g_print ("connecting to %s\n", jack_port_name (src->ports[i])); if (res != 0 && res != EEXIST) goto cannot_connect; } free (ports); } done: abuf->sample_rate = sample_rate; abuf->buffer_size = buffer_size; abuf->channels = spec->channels; return TRUE; /* ERRORS */ wrong_samplerate: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Wrong samplerate, server is running at %d and we received %d", sample_rate, spec->rate)); return FALSE; } out_of_ports: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Cannot allocate more Jack ports")); return FALSE; } could_not_activate: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Could not activate client (%d:%s)", res, g_strerror (res))); return FALSE; } cannot_connect: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Could not connect input ports to physical ports (%d:%s)", res, g_strerror (res))); free (ports); return FALSE; } }