+static void Play (audio_output_t * p_aout, block_t * p_block)
+{
+ struct aout_sys_t *p_sys = p_aout->sys;
+ jack_ringbuffer_t *rb = p_sys->p_jack_ringbuffer;
+ const size_t bytes_per_frame = p_sys->i_channels * sizeof(jack_sample_t);
+
+ while (p_block->i_buffer > 0) {
+
+ /* move data to buffer */
+ const size_t write_space = jack_ringbuffer_write_space(rb);
+ const size_t bytes = p_block->i_buffer < write_space ?
+ p_block->i_buffer : write_space;
+
+ /* If our audio thread is not reading fast enough */
+ if( unlikely( bytes == 0 ) ) {
+ msg_Warn( p_aout, "%"PRIuPTR " frames of audio dropped",
+ p_block->i_buffer / bytes_per_frame );
+ break;
+ }
+
+ jack_ringbuffer_write( rb, (const char *) p_block->p_buffer, bytes );
+
+ p_block->p_buffer += bytes;
+ p_block->i_buffer -= bytes;
+ }
+
+ block_Release(p_block);
+}
+
+/**
+ * Pause or unpause playback
+ */
+static void Pause(audio_output_t *aout, bool paused, mtime_t date)
+{
+ aout_sys_t *sys = aout->sys;
+
+ if( paused ) {
+ sys->paused = date;
+ } else {
+ date -= sys->paused;
+ msg_Dbg(aout, "resuming after %"PRId64" us", date);
+ sys->paused = VLC_TS_INVALID;
+ }
+}
+
+static void Flush(audio_output_t *p_aout, bool wait)
+{
+ struct aout_sys_t * p_sys = p_aout->sys;
+ jack_ringbuffer_t *rb = p_sys->p_jack_ringbuffer;
+ jack_client_t *client = p_sys->p_jack_client;
+ int i_error;
+
+ /* Sleep if wait was requested */
+ if( wait )
+ {
+ mtime_t delay;
+ if (!TimeGet(p_aout, &delay))
+ msleep(delay);
+ }
+
+ /* FIXME: maybe the ringbuffer_reset should just be protected by signalling
+ * with atomic variables?
+ * Here we save and restore connections, otherwise we'd lose the connections
+ * every seek because of the deactivate/activate */
+
+ /* Save connections */
+ const char **connections_list[p_sys->i_channels];
+
+ for( size_t i = 0; i < p_sys->i_channels; i++ )
+ {
+ const char **port_connections = jack_port_get_all_connections( client,
+ p_sys->p_jack_ports[i] );
+ connections_list[i] = port_connections;
+ }
+
+ /* Suspend audio processing */
+ i_error = jack_deactivate( p_sys->p_jack_client );
+ if( i_error )
+ {
+ msg_Err( p_aout, "failed to deactivate JACK client (error %d)",
+ i_error );
+ return;
+ }
+
+ /* reset ringbuffer read and write pointers */
+ jack_ringbuffer_reset(rb);
+
+ /* Resume audio processing */
+ i_error = jack_activate( p_sys->p_jack_client );
+ if( i_error )
+ {
+ msg_Err( p_aout, "failed to activate JACK client (error %d)", i_error );
+ return;
+ }
+
+ /* Restore connections */
+ for( size_t i = 0; i < p_sys->i_channels; i++ )
+ {
+ const char **port_connections = connections_list[i];
+ const char *psz_out = jack_port_name( p_sys->p_jack_ports[i] );
+ for (const char **psz_in = port_connections; psz_in && *psz_in;
+ psz_in++)
+ {
+ i_error = jack_connect( client, psz_out, *psz_in );
+ if( i_error )
+ {
+ msg_Err( p_aout, "failed to connect ports %s and %s (error %d)",
+ psz_out, *psz_in, i_error );
+ }
+ }
+
+ if( port_connections )
+ jack_free(port_connections);
+ }
+}
+
+static int TimeGet(audio_output_t *p_aout, mtime_t *delay)
+{
+ struct aout_sys_t * p_sys = p_aout->sys;
+ jack_ringbuffer_t *rb = p_sys->p_jack_ringbuffer;
+ const size_t bytes_per_frame = p_sys->i_channels * sizeof(jack_sample_t);
+
+ *delay = (p_sys->latency +
+ (jack_ringbuffer_read_space(rb) / bytes_per_frame)) *
+ CLOCK_FREQ / p_sys->i_rate;
+
+ return 0;
+}