+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;
+
+ /* Sleep if wait was requested */
+ if( wait )
+ {
+ mtime_t delay;
+ if (!TimeGet(p_aout, &delay))
+ msleep(delay);
+ }
+
+ /* reset ringbuffer read and write pointers */
+ jack_ringbuffer_reset(rb);
+}
+
+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;
+}