Exemple #1
0
			/**
			  @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);
			}
Exemple #2
0
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;
	}
Exemple #3
0
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;
	}
Exemple #4
0
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);
    }
}
Exemple #5
0
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;
}
Exemple #6
0
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();
}