Actually get playback through JACK, kind of.
This commit is contained in:
parent
0dff4be584
commit
7f43a99030
|
@ -25,6 +25,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
Audio_File_SF *
|
Audio_File_SF *
|
||||||
Audio_File_SF::from_file ( const char *filename )
|
Audio_File_SF::from_file ( const char *filename )
|
||||||
{
|
{
|
||||||
|
@ -100,6 +102,11 @@ Audio_File_SF::read ( sample_t *buf, int channel, nframes_t len )
|
||||||
return sf_readf_float( _in, buf, len );
|
return sf_readf_float( _in, buf, len );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if ( len > 256 * 100 )
|
||||||
|
printf( "warning: attempt to read an insane number of frames (%lu) from soundfile\n", len );
|
||||||
|
|
||||||
|
printf( "len = %lu, channels = %d\n", len, _channels );
|
||||||
|
|
||||||
sample_t *tmp = new sample_t[ len * _channels ];
|
sample_t *tmp = new sample_t[ len * _channels ];
|
||||||
|
|
||||||
nframes_t rlen = sf_readf_float( _in, tmp, len );
|
nframes_t rlen = sf_readf_float( _in, tmp, len );
|
||||||
|
@ -118,6 +125,8 @@ Audio_File_SF::read ( sample_t *buf, int channel, nframes_t len )
|
||||||
nframes_t
|
nframes_t
|
||||||
Audio_File_SF::read ( sample_t *buf, int channel, nframes_t start, nframes_t end )
|
Audio_File_SF::read ( sample_t *buf, int channel, nframes_t start, nframes_t end )
|
||||||
{
|
{
|
||||||
|
assert( end > start );
|
||||||
|
|
||||||
open();
|
open();
|
||||||
|
|
||||||
seek( start );
|
seek( start );
|
||||||
|
|
|
@ -99,7 +99,8 @@ Audio_Track::handle ( int m )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Region *r = new Region( c, this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ) );
|
// Region *r =
|
||||||
|
new Region( c, this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ) );
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -123,7 +124,7 @@ Audio_Track::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int chann
|
||||||
sample_t *cbuf = new sample_t[ nframes ];
|
sample_t *cbuf = new sample_t[ nframes ];
|
||||||
|
|
||||||
/* quick and dirty--let the regions figure out coverage for themselves */
|
/* quick and dirty--let the regions figure out coverage for themselves */
|
||||||
for ( list <Track_Widget *>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ )
|
for ( list <Track_Widget *>::const_iterator i = _widgets.begin(); i != _widgets.end(); ++i )
|
||||||
{
|
{
|
||||||
const Region *r = (Region*)(*i);
|
const Region *r = (Region*)(*i);
|
||||||
|
|
||||||
|
@ -141,6 +142,15 @@ Audio_Track::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int chann
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete[] cbuf;
|
||||||
|
|
||||||
/* FIXME: bogus */
|
/* FIXME: bogus */
|
||||||
return nframes;
|
return nframes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* /\* THREAD: RT *\/ */
|
||||||
|
/* nframes_t */
|
||||||
|
/* Audio_Track::process ( nframes_t nframes ) */
|
||||||
|
/* { */
|
||||||
|
/* return disktream->process( nframes ); */
|
||||||
|
/* } */
|
||||||
|
|
|
@ -46,7 +46,7 @@ Disk_Stream::Disk_Stream ( Track_Header *th, float frame_rate, nframes_t nframes
|
||||||
size_t bufsize = blocks * nframes * sizeof( sample_t );
|
size_t bufsize = blocks * nframes * sizeof( sample_t );
|
||||||
|
|
||||||
for ( int i = channels; i--; )
|
for ( int i = channels; i--; )
|
||||||
_rb[ i ] = jack_ringbuffer_create( bufsize );
|
_rb.push_back( jack_ringbuffer_create( bufsize ) );
|
||||||
|
|
||||||
sem_init( &_blocks, 0, blocks );
|
sem_init( &_blocks, 0, blocks );
|
||||||
|
|
||||||
|
@ -97,10 +97,27 @@ Disk_Stream::io_thread ( void *arg )
|
||||||
void
|
void
|
||||||
Disk_Stream::read_block ( sample_t *buf )
|
Disk_Stream::read_block ( sample_t *buf )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/* stupid chicken/egg */
|
||||||
|
if ( ! timeline )
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf( "IO: attempting to read block @ %lu\n", _frame );
|
||||||
|
|
||||||
|
if ( ! track() )
|
||||||
|
{
|
||||||
|
// _frame += _nframes;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline->rdlock();
|
||||||
|
|
||||||
if ( track()->play( buf, _frame, _nframes, channels() ) )
|
if ( track()->play( buf, _frame, _nframes, channels() ) )
|
||||||
_frame += _nframes;
|
_frame += _nframes;
|
||||||
else
|
else
|
||||||
/* error */;
|
/* error */;
|
||||||
|
|
||||||
|
timeline->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* THREAD: IO */
|
/* THREAD: IO */
|
||||||
|
@ -119,6 +136,8 @@ Disk_Stream::io_thread ( void )
|
||||||
|
|
||||||
while ( wait_for_block() )
|
while ( wait_for_block() )
|
||||||
{
|
{
|
||||||
|
// printf( "IO: RT thread is ready for more data...\n" );
|
||||||
|
|
||||||
read_block( buf );
|
read_block( buf );
|
||||||
|
|
||||||
/* deinterleave the buffer and stuff it into the per-channel ringbuffers */
|
/* deinterleave the buffer and stuff it into the per-channel ringbuffers */
|
||||||
|
@ -140,8 +159,8 @@ Disk_Stream::io_thread ( void )
|
||||||
/* THREAD: RT */
|
/* THREAD: RT */
|
||||||
/** take a block from the ringbuffers and send it out the track's
|
/** take a block from the ringbuffers and send it out the track's
|
||||||
* ports */
|
* ports */
|
||||||
void
|
nframes_t
|
||||||
Disk_Stream::process ( void )
|
Disk_Stream::process ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
const size_t block_size = _nframes * sizeof( sample_t );
|
const size_t block_size = _nframes * sizeof( sample_t );
|
||||||
|
|
||||||
|
@ -154,4 +173,7 @@ Disk_Stream::process ( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
block_processed();
|
block_processed();
|
||||||
|
|
||||||
|
/* FIXME: bogus */
|
||||||
|
return nframes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,6 @@ public:
|
||||||
void run ( void );
|
void run ( void );
|
||||||
void read_block ( sample_t *buf );
|
void read_block ( sample_t *buf );
|
||||||
void io_thread ( void );
|
void io_thread ( void );
|
||||||
void process ( void );
|
nframes_t process ( nframes_t nframes );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2008 Jonathan Moore Liles */
|
||||||
|
/* */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify it */
|
||||||
|
/* under the terms of the GNU General Public License as published by the */
|
||||||
|
/* Free Software Foundation; either version 2 of the License, or (at your */
|
||||||
|
/* option) any later version. */
|
||||||
|
/* */
|
||||||
|
/* This program is distributed in the hope that it will be useful, but WITHOUT */
|
||||||
|
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
|
||||||
|
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
|
||||||
|
/* more details. */
|
||||||
|
/* */
|
||||||
|
/* You should have received a copy of the GNU General Public License along */
|
||||||
|
/* with This program; see the file COPYING. If not,write to the Free Software */
|
||||||
|
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
|
#include "Engine.H"
|
||||||
|
|
||||||
|
#include "Timeline.H" // for process()
|
||||||
|
|
||||||
|
#define APP_NAME "Non-DAW" // FIXME: wrong place for this!
|
||||||
|
|
||||||
|
/* This is the home of the JACK process callback (does this *really*
|
||||||
|
need to be a class?) */
|
||||||
|
|
||||||
|
Engine::Engine ( )
|
||||||
|
{
|
||||||
|
_client = NULL;
|
||||||
|
_buffers_dropped = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* static wrapper */
|
||||||
|
int
|
||||||
|
Engine::process ( nframes_t nframes, void *arg )
|
||||||
|
{
|
||||||
|
return ((Engine*)arg)->process( nframes );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* THREAD: RT */
|
||||||
|
int
|
||||||
|
Engine::process ( nframes_t nframes )
|
||||||
|
{
|
||||||
|
jack_position_t pos;
|
||||||
|
jack_transport_state_t ts;
|
||||||
|
|
||||||
|
ts = jack_transport_query( _client, &pos );
|
||||||
|
|
||||||
|
if ( ts != JackTransportRolling )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( ! trylock() )
|
||||||
|
{
|
||||||
|
/* the data structures we need to access here (tracks and
|
||||||
|
* their ports, but not track contents) may be in an
|
||||||
|
* inconsistent state at the moment. Just punt and drop this
|
||||||
|
* buffer. */
|
||||||
|
++_buffers_dropped;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* handle chicken/egg problem */
|
||||||
|
if ( timeline )
|
||||||
|
/* this will initiate the process() call graph for the various
|
||||||
|
* number and types of tracks, which will in turn send data out
|
||||||
|
* the appropriate ports. */
|
||||||
|
timeline->process( nframes );
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Engine::init ( void )
|
||||||
|
{
|
||||||
|
if (( _client = jack_client_open ( APP_NAME, (jack_options_t)0, NULL )) == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
jack_set_process_callback( _client, &Engine::process, this );
|
||||||
|
|
||||||
|
jack_activate( _client );
|
||||||
|
|
||||||
|
/* we don't need to create any ports until tracks are created */
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2008 Jonathan Moore Liles */
|
||||||
|
/* */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify it */
|
||||||
|
/* under the terms of the GNU General Public License as published by the */
|
||||||
|
/* Free Software Foundation; either version 2 of the License, or (at your */
|
||||||
|
/* option) any later version. */
|
||||||
|
/* */
|
||||||
|
/* This program is distributed in the hope that it will be useful, but WITHOUT */
|
||||||
|
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
|
||||||
|
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
|
||||||
|
/* more details. */
|
||||||
|
/* */
|
||||||
|
/* You should have received a copy of the GNU General Public License along */
|
||||||
|
/* with This program; see the file COPYING. If not,write to the Free Software */
|
||||||
|
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Mutex.H"
|
||||||
|
|
||||||
|
#include <jack/jack.h>
|
||||||
|
|
||||||
|
typedef jack_nframes_t nframes_t;
|
||||||
|
|
||||||
|
class Port;
|
||||||
|
|
||||||
|
class Engine : public Mutex
|
||||||
|
{
|
||||||
|
jack_client_t *_client;
|
||||||
|
|
||||||
|
/* I know locking out the process callback is cheating, even
|
||||||
|
though we use trylock... The thing is, every other DAW does
|
||||||
|
this too and you can hear it in the glitches Ardour and friends
|
||||||
|
produce when reconfiguring I/O... Working out a message queue
|
||||||
|
system would obviously be better, but a DAW isn't a performance
|
||||||
|
instrument anyway, so I think these drop-outs are a reasonable
|
||||||
|
compromise. Obviously, this lock should never be held during
|
||||||
|
blocking operations. */
|
||||||
|
|
||||||
|
int _buffers_dropped; /* buffers dropped because of locking */
|
||||||
|
|
||||||
|
static int process ( nframes_t nframes, void *arg );
|
||||||
|
int process ( nframes_t nframes );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
friend class Port;
|
||||||
|
jack_client_t * client ( void ) { return _client; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Engine ( );
|
||||||
|
|
||||||
|
int init ( void );
|
||||||
|
|
||||||
|
nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); }
|
||||||
|
float frame_rate ( void ) const { return jack_get_sample_rate( _client ); }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern Engine * engine;
|
|
@ -31,6 +31,12 @@ public:
|
||||||
Mutex ( )
|
Mutex ( )
|
||||||
{
|
{
|
||||||
// _lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
// _lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||||
|
pthread_mutex_init( &_lock, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Mutex ( )
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy( &_lock );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Engine.H"
|
||||||
|
|
||||||
/* nframes is the number of frames to buffer */
|
/* nframes is the number of frames to buffer */
|
||||||
Port::Port ( jack_port_t *port )
|
Port::Port ( jack_port_t *port )
|
||||||
{
|
{
|
||||||
|
@ -28,9 +30,17 @@ Port::Port ( jack_port_t *port )
|
||||||
_name = jack_port_name( _port );
|
_name = jack_port_name( _port );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Port::Port ( const char *name )
|
||||||
|
{
|
||||||
|
_name = name;
|
||||||
|
|
||||||
|
_port = jack_port_register( engine->client(), _name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
Port::~Port ( )
|
Port::~Port ( )
|
||||||
{
|
{
|
||||||
/* close port? */
|
/* close port? */
|
||||||
|
// jack_port_unregister( engine->client(), _port );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -33,6 +33,7 @@ class Port
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Port ( jack_port_t *port );
|
Port ( jack_port_t *port );
|
||||||
|
Port ( const char *name );
|
||||||
~Port ( );
|
~Port ( );
|
||||||
|
|
||||||
bool connected ( void ) const { return jack_port_connected( _port ); }
|
bool connected ( void ) const { return jack_port_connected( _port ); }
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2008 Jonathan Moore Liles */
|
||||||
|
/* */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify it */
|
||||||
|
/* under the terms of the GNU General Public License as published by the */
|
||||||
|
/* Free Software Foundation; either version 2 of the License, or (at your */
|
||||||
|
/* option) any later version. */
|
||||||
|
/* */
|
||||||
|
/* This program is distributed in the hope that it will be useful, but WITHOUT */
|
||||||
|
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
|
||||||
|
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
|
||||||
|
/* more details. */
|
||||||
|
/* */
|
||||||
|
/* You should have received a copy of the GNU General Public License along */
|
||||||
|
/* with This program; see the file COPYING. If not,write to the Free Software */
|
||||||
|
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
/*******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
class RWLock
|
||||||
|
{
|
||||||
|
|
||||||
|
pthread_rwlock_t _lock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
RWLock ( )
|
||||||
|
{
|
||||||
|
// _lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||||
|
pthread_rwlock_init( &_lock, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~RWLock ( )
|
||||||
|
{
|
||||||
|
pthread_rwlock_destroy( &_lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rdlock ( void )
|
||||||
|
{
|
||||||
|
pthread_rwlock_rdlock( &_lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wrlock ( void )
|
||||||
|
{
|
||||||
|
pthread_rwlock_wrlock( &_lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unlock ( void )
|
||||||
|
{
|
||||||
|
pthread_rwlock_unlock( &_lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tryrdlock ( void )
|
||||||
|
{
|
||||||
|
return pthread_rwlock_tryrdlock( &_lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
trywrlock ( void )
|
||||||
|
{
|
||||||
|
return pthread_rwlock_trywrlock( &_lock );
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -555,9 +555,10 @@ Region::read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) co
|
||||||
{
|
{
|
||||||
const Range &r = _range;
|
const Range &r = _range;
|
||||||
|
|
||||||
/* do nothing if we aren't covered by this frame range */
|
|
||||||
const nframes_t length = r.end - r.start;
|
const nframes_t length = r.end - r.start;
|
||||||
if ( ! ( pos > r.offset + length || r.offset + length < pos ) )
|
|
||||||
|
/* do nothing if we aren't covered by this frame range */
|
||||||
|
if ( pos > r.offset + length || pos + nframes < r.offset )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* calculate offsets into file and sample buffer */
|
/* calculate offsets into file and sample buffer */
|
||||||
|
@ -576,11 +577,11 @@ Region::read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) co
|
||||||
sofs = pos - r.offset;
|
sofs = pos - r.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sofs > nframes )
|
if ( ofs > nframes )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const nframes_t start = ofs + r.start + sofs;
|
const nframes_t start = ofs + r.start + sofs;
|
||||||
const nframes_t len = min( cnt, nframes - sofs );
|
const nframes_t len = min( cnt, nframes - ofs );
|
||||||
const nframes_t end = start + len;
|
const nframes_t end = start + len;
|
||||||
|
|
||||||
if ( len == 0 )
|
if ( len == 0 )
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
#include "Control_Track.H"
|
#include "Control_Track.H"
|
||||||
#include <FL/Fl_Scrollbar.H>
|
#include <FL/Fl_Scrollbar.H>
|
||||||
|
|
||||||
#include <FL/Fl_Image.H>
|
// #include <FL/Fl_Image.H>
|
||||||
#include <FL/Fl_RGB_Image.H> // needed for alpha blending
|
// #include <FL/Fl_RGB_Image.H> // needed for alpha blending
|
||||||
|
|
||||||
#include "Track_Header.H"
|
#include "Track_Header.H"
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi
|
||||||
o->type( Fl_Pack::VERTICAL );
|
o->type( Fl_Pack::VERTICAL );
|
||||||
o->spacing( 0 );
|
o->spacing( 0 );
|
||||||
|
|
||||||
for ( int i = 8; i--; )
|
for ( int i = 1; i--; )
|
||||||
{
|
{
|
||||||
// Track_Header *t = new Track_Header( 0, 0, W, 75 );
|
// Track_Header *t = new Track_Header( 0, 0, W, 75 );
|
||||||
Track_Header *t = new Track_Header( 0, 0, W, 30 );
|
Track_Header *t = new Track_Header( 0, 0, W, 30 );
|
||||||
|
|
|
@ -79,9 +79,9 @@ struct Rectangle
|
||||||
|
|
||||||
class Engine;
|
class Engine;
|
||||||
|
|
||||||
#include "Mutex.H"
|
#include "RWLock.H"
|
||||||
|
|
||||||
class Timeline : public Fl_Overlay_Window, public Mutex
|
class Timeline : public Fl_Overlay_Window, public RWLock
|
||||||
{
|
{
|
||||||
static void draw_clip ( void * v, int X, int Y, int W, int H );
|
static void draw_clip ( void * v, int X, int Y, int W, int H );
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
#include "Track_Header.H"
|
#include "Track_Header.H"
|
||||||
|
|
||||||
|
#include "Disk_Stream.H"
|
||||||
|
#include "Engine.H"
|
||||||
|
|
||||||
void
|
void
|
||||||
Track_Header::cb_input_field ( Fl_Widget *w, void *v )
|
Track_Header::cb_input_field ( Fl_Widget *w, void *v )
|
||||||
{
|
{
|
||||||
|
@ -85,6 +88,7 @@ Track_Header::cb_button ( Fl_Widget *w )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "Port.H"
|
||||||
|
|
||||||
Track_Header::Track_Header ( int X, int Y, int W, int H, const char *L ) :
|
Track_Header::Track_Header ( int X, int Y, int W, int H, const char *L ) :
|
||||||
Fl_Group ( X, Y, W, H, L )
|
Fl_Group ( X, Y, W, H, L )
|
||||||
|
@ -96,7 +100,9 @@ Track_Header::Track_Header ( int X, int Y, int W, int H, const char *L ) :
|
||||||
_show_all_takes = false;
|
_show_all_takes = false;
|
||||||
_size = 1;
|
_size = 1;
|
||||||
|
|
||||||
// diskstream = new Disk_Stream( this );
|
output.push_back( Port( "foo" ) );
|
||||||
|
|
||||||
|
diskstream = new Disk_Stream( this, engine->frame_rate(), engine->nframes(), 1 );
|
||||||
|
|
||||||
Fl_Group::size( w(), height() );
|
Fl_Group::size( w(), height() );
|
||||||
|
|
||||||
|
@ -284,8 +290,12 @@ Track_Header::add_control( Track *t )
|
||||||
/* Engine */
|
/* Engine */
|
||||||
/**********/
|
/**********/
|
||||||
|
|
||||||
|
/* THREAD: RT */
|
||||||
nframes_t
|
nframes_t
|
||||||
Track_Header::process ( nframes_t nframes )
|
Track_Header::process ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
return track()->process( nframes );
|
if ( diskstream )
|
||||||
|
return diskstream->process( nframes );
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,9 @@
|
||||||
#include "Track_Header.H"
|
#include "Track_Header.H"
|
||||||
// #include "const.h"
|
// #include "const.h"
|
||||||
|
|
||||||
|
#include "Engine.H"
|
||||||
|
|
||||||
|
Engine *engine;
|
||||||
Timeline *timeline;
|
Timeline *timeline;
|
||||||
|
|
||||||
void cb_undo ( Fl_Widget *w, void *v )
|
void cb_undo ( Fl_Widget *w, void *v )
|
||||||
|
@ -78,6 +81,10 @@ main ( int argc, char **argv )
|
||||||
Loggable::register_create( "Control_Point", &Control_Point::create );
|
Loggable::register_create( "Control_Point", &Control_Point::create );
|
||||||
Loggable::register_create( "Track_Header", &Track_Header::create );
|
Loggable::register_create( "Track_Header", &Track_Header::create );
|
||||||
|
|
||||||
|
/* we don't really need a pointer for this */
|
||||||
|
engine = new Engine;
|
||||||
|
engine->init();
|
||||||
|
|
||||||
timeline = new Timeline( 0, 24, main_window->w(), main_window->h() - 24, "Timeline" );
|
timeline = new Timeline( 0, 24, main_window->w(), main_window->h() - 24, "Timeline" );
|
||||||
|
|
||||||
Fl_Button *o = new Fl_Button( 0, 0, 50, 24, "undo" );
|
Fl_Button *o = new Fl_Button( 0, 0, 50, 24, "undo" );
|
||||||
|
|
Loading…
Reference in New Issue