/** @brief Read into an array Read from the buffer into an array. \param dest an array to be read into \param cnt the number of elements to read into this array */ void read(Type *dest, unsigned cnt){ jack_ringbuffer_data_t readVec[2]; unsigned int read_size = sizeof(Type) * cnt; if(getReadSpace() <= 0){ //throw error!!!! return; } //get the readvector jack_ringbuffer_get_read_vector(mRingBufferPtr, readVec); //if the first vector has enough data then just read from there if(readVec[0].len >= read_size){ memcpy(dest, readVec[0].buf, read_size); } else { //if the first vector is zero length then read from the second if(readVec[0].len == 0){ memcpy(dest, readVec[1].buf, read_size); } else { //this gets tricky char * byterep = (char *)dest; //first read the data out of the first vector memcpy(byterep, readVec[0].buf, readVec[0].len); //then read the rest out of the second memcpy(byterep + readVec[0].len, readVec[1].buf, read_size - readVec[0].len); } } //advance the read pointer jack_ringbuffer_read_advance(mRingBufferPtr, read_size); }
int ringbuffer_cread(jack_ringbuffer_t *rbuf, void *buf, size_t bufsz, int advance, uint32_t *tag, size_t *len) /* C version: returns 1 on success and 0 on error */ { jack_ringbuffer_data_t vec[2]; hdr_t hdr; uint32_t len0; size_t cnt; /* peek for header */ cnt = jack_ringbuffer_peek(rbuf, (char*)&hdr, sizeof(hdr)); if(cnt != sizeof(hdr)) return 0; /* see if there are 'len' bytes of data available */ cnt = jack_ringbuffer_read_space(rbuf); if( cnt < (sizeof(hdr) + hdr.len) ) return 0; /* check if data fits in the user provided buffer */ if(hdr.len > bufsz ) return luajack_error("not enough space for ringbuffer_read() " "(at least %u bytes needed)", hdr.len); *tag = hdr.tag; *len = hdr.len; if(hdr.len == 0) /* tag only */ { if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr)); if(bufsz>0) ((char*)buf)[0]='\0'; return 1; } /* get the read vector */ jack_ringbuffer_get_read_vector(rbuf, vec); /* copy the data part in the user provided buffer */ if(vec[0].len >= (sizeof(hdr) + hdr.len)) /* all the data are in vec[0] */ memcpy(buf, vec[0].buf + sizeof(hdr), hdr.len); else if(vec[0].len > sizeof(hdr)) /* part of the data are in vec[0] */ { len0 = vec[0].len - sizeof(hdr); memcpy(buf, vec[0].buf + sizeof(hdr), len0); memcpy((char*)buf + len0, vec[1].buf, hdr.len - len0); } else /* part of the header and all of the data are in vec[1] */ { len0 = sizeof(hdr) - vec[0].len; /* bytes oh header in vec[1] */ memcpy((char*)buf, vec[1].buf + len0, hdr.len); } if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr) + hdr.len); return 1; }
int ringbuffer_luaread(jack_ringbuffer_t *rbuf, lua_State *L, int advance) /* tag, data = read() * returns tag=nil if there is not a complete message (header+data) in * the ringbuffer * if the header.len is 0, data is returned as an empty string ("") */ { jack_ringbuffer_data_t vec[2]; hdr_t hdr; uint32_t len; size_t cnt; /* peek for header */ cnt = jack_ringbuffer_peek(rbuf, (char*)&hdr, sizeof(hdr)); if(cnt != sizeof(hdr)) { lua_pushnil(L); return 1; } /* see if there are 'len' bytes of data available */ cnt = jack_ringbuffer_read_space(rbuf); if( cnt < (sizeof(hdr) + hdr.len) ) { lua_pushnil(L); return 1; } lua_pushinteger(L, hdr.tag); if(hdr.len == 0) /* header only */ { if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr)); lua_pushstring(L, ""); return 2; } /* get the read vector */ jack_ringbuffer_get_read_vector(rbuf, vec); //printf("vec[0].len=%u, vec[1].len=%u hdr.len=%u\n",vec[0].len,vec[1].len,hdr.len); if(vec[0].len >= (sizeof(hdr) + hdr.len)) /* data fits in vec[0] */ lua_pushlstring(L, vec[0].buf + sizeof(hdr), hdr.len); else if(vec[0].len > sizeof(hdr)) { len = vec[0].len - sizeof(hdr); lua_pushlstring(L, vec[0].buf + sizeof(hdr), len); lua_pushlstring(L, vec[1].buf, hdr.len - len); lua_concat(L, 2); } else /* vec[0] contains only the header or part of it (data is all in vec[1]) */ { len = sizeof(hdr) - vec[0].len; /* the first len bytes in vec1 are part of the header */ lua_pushlstring(L, vec[1].buf + len, hdr.len); } if(advance) jack_ringbuffer_read_advance(rbuf, sizeof(hdr) + hdr.len); return 2; }
static void do_jack_input(process_jack_t *p) { input_port_t *port = (input_port_t*) p->port; event_head_t event; while (jack_ringbuffer_read_space(port->base.event_ring) >= sizeof(event)) { jack_ringbuffer_data_t vec[2]; jack_nframes_t time; int i, todo; jack_ringbuffer_read(port->base.event_ring, (char*)&event, sizeof(event)); // TODO: take into account possible warping if ((event.time + p->nframes) < p->frame_time) time = 0; else if (event.time >= p->frame_time) time = p->nframes -1; else time = event.time + p->nframes - p->frame_time; jack_ringbuffer_get_read_vector(port->base.data_ring, vec); assert ((vec[0].len + vec[1].len) >= event.size); if (event.overruns) midi_unpack_reset(&port->unpack); todo = event.size; for (i=0; i<2 && todo>0; ++i) { int avail = todo < vec[i].len ? todo : vec[i].len; int done = midi_unpack_buf(&port->unpack, (unsigned char*)vec[i].buf, avail, p->buffer, time); if (done != avail) { debug_log("jack_in: buffer overflow in port %s", port->base.name); break; } todo -= done; } jack_ringbuffer_read_advance(port->base.data_ring, event.size); } }
static int do_midi_output(process_midi_t *proc) { int worked = 0; output_port_t *port = (output_port_t*) proc->port; if (!midi_is_ready(proc)) return 0; // eat events while (port->next_event.time <= proc->cur_time) { port->todo += port->next_event.size; if (jack_ringbuffer_read(port->base.event_ring, (char*)&port->next_event, sizeof(port->next_event))!=sizeof(port->next_event)) { port->next_event.time = 0; port->next_event.size = 0; break; } else debug_log("midi_out: at %ld got %d bytes for %ld", (long)proc->cur_time, (int)port->next_event.size, (long)port->next_event.time); } if (port->todo) debug_log("midi_out: todo = %d at %ld", (int)port->todo, (long)proc->cur_time); // calc next wakeup time if (!port->todo && port->next_event.time && port->next_event.time < proc->next_time) { proc->next_time = port->next_event.time; debug_log("midi_out: next_time = %ld", (long)proc->next_time); } if (port->todo && port->base.is_ready) { // write data int size = port->todo; int res; jack_ringbuffer_data_t vec[2]; jack_ringbuffer_get_read_vector(port->base.data_ring, vec); if (size > vec[0].len) { size = vec[0].len; assert (size > 0); } res = snd_rawmidi_write(port->base.rawmidi, vec[0].buf, size); if (res > 0) { jack_ringbuffer_read_advance(port->base.data_ring, res); debug_log("midi_out: written %d bytes to %s", res, port->base.name); port->todo -= res; worked = 1; } else if (res == -EWOULDBLOCK) { port->base.is_ready = 0; debug_log("midi_out: -EWOULDBLOCK on %s", port->base.name); return 1; } else { error_log("midi_out: writing to port %s failed: %s", port->base.name, snd_strerror(res)); return 0; } snd_rawmidi_drain(port->base.rawmidi); } // update pfds for this port if (!midi_update_pfds(proc)) return 0; if (!port->todo) { int i; if (worked) debug_log("midi_out: relaxing on %s", port->base.name); for (i=0; i<port->base.npfds; ++i) proc->wpfds[i].events &= ~POLLOUT; } else { int i; for (i=0; i<port->base.npfds; ++i) proc->wpfds[i].events |= POLLOUT; } return 1; }
void Record_DS::disk_thread ( void ) { _thread.name( "Capture" ); DMESSAGE( "capture thread running..." ); track()->record( _capture, _frame ); const nframes_t nframes = _nframes * _disk_io_blocks; /* buffer to hold the interleaved data returned by the track reader */ sample_t *buf = new sample_t[ nframes * channels() ]; #ifndef AVOID_UNNECESSARY_COPYING sample_t *cbuf = new sample_t[ nframes ]; #endif const size_t block_size = nframes * sizeof( sample_t ); int blocks_ready = 0; while ( wait_for_block() ) { if ( ++blocks_ready < _disk_io_blocks ) continue; else blocks_ready = 0; /* pull data from the per-channel ringbuffers and interlace it */ for ( int i = channels(); i--; ) { #ifdef AVOID_UNNECESSARY_COPYING /* interleave direcectly from the ringbuffer to avoid * unnecessary copying */ jack_ringbuffer_data_t rbd[2]; memset( rbd, 0, sizeof( rbd ) ); jack_ringbuffer_get_read_vector( _rb[ i ], rbd ); if ( rbd[ 0 ].len >= block_size ) { /* it'll all fit in one go */ buffer_interleave_one_channel( buf, (sample_t*)rbd[ 0 ].buf, i, channels(), nframes ); } else if ( rbd[ 0 ].len + rbd[ 1 ].len >= block_size ) { /* there's enough space in the ringbuffer, but it's not contiguous */ assert( ! ( rbd[ 0 ].len % sizeof( sample_t ) ) ); const nframes_t f = rbd[ 0 ].len / sizeof( sample_t ); /* do the first half */ buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), f ); buffer_interleave_one_channel( buf, (sample_t*)rbd[ 0 ].buf, i, channels(), f ); assert( rbd[ 1 ].len >= ( nframes - f ) * sizeof( sample_t ) ); /* do the second half */ buffer_interleave_one_channel( buf + f, (sample_t*)rbd[ 0 ].buf, i, channels(), nframes - f ); } else ++_xruns; jack_ringbuffer_read_advance( _rb[ i ], block_size ); #else if ( jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ) < block_size ) ++_xruns; buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); #endif } write_block( buf, nframes ); } DMESSAGE( "capture thread terminating" ); /* flush what remains in the buffer out to disk */ { /* use JACk sized blocks for this last bit */ const nframes_t nframes = _nframes; const size_t block_size = _nframes * sizeof( sample_t ); #ifdef AVOID_UNNECESSARY_COPYING sample_t *cbuf = new sample_t[ nframes ]; #endif while ( blocks_ready-- > 0 || ( ! sem_trywait( &_blocks ) && errno != EAGAIN ) ) { for ( int i = channels(); i--; ) { jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ); buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); } const nframes_t frames_remaining = (_stop_frame - _frame ) - _frames_written; if ( frames_remaining < nframes ) { /* this is the last block, might be partial */ write_block( buf, frames_remaining ); break; } else write_block( buf, nframes ); } #ifdef AVOID_UNNECESSARY_COPYING delete[] cbuf; #endif } delete[] buf; #ifndef AVOID_UNNECESSARY_COPYING delete[] cbuf; #endif DMESSAGE( "finalzing capture" ); Track::Capture *c = _capture; _capture = NULL; /* now finalize the recording */ track()->finalize( c, _stop_frame ); delete c; _terminate = false; DMESSAGE( "capture thread gone" ); _thread.exit(); }