Cleanups and commenting.

This commit is contained in:
Jonathan Moore Liles 2008-06-18 23:14:14 -05:00
parent 6d9a5bb1d5
commit 170b11010e
29 changed files with 901 additions and 872 deletions

View File

@ -63,8 +63,10 @@ TAGS: $(SRCS)
etags $(SRCS)
.deps: .config $(SRCS)
ifneq ($(CALCULATING),yes)
@ echo -n Calculating dependencies...
@ makedepend -f- -- $(CXXFLAGS) $(INCLUDES) -- $(SRCS) > .deps 2>/dev/null && echo $(DONE)
@ makedepend -f- -- $(CXXFLAGS) $(INCLUDES) -- $(SRCS) 2>/dev/null > .deps && echo $(DONE)
endif
clean_deps:
@ rm -f .deps

View File

@ -57,6 +57,7 @@ static Fl_Color fl_invert_color ( Fl_Color c )
return fl_rgb_color( 255 - r, 255 - g, 255 - b );
}
void
Audio_Region::get ( Log_Entry &e ) const
@ -154,7 +155,6 @@ Audio_Region::Audio_Region ( Audio_File *c )
log_create();
}
/* used when DND importing */
Audio_Region::Audio_Region ( Audio_File *c, Sequence *t, nframes_t o )
{
@ -189,12 +189,13 @@ Audio_Region::Audio_Region ( Audio_File *c, Sequence *t, nframes_t o )
log_create();
}
const char *
Audio_Region::source_name ( void ) const
Audio_Region::~Audio_Region ( )
{
return _clip->name();
log_destroy();
}
void
Audio_Region::menu_cb ( Fl_Widget *w, void *v )
{
@ -309,123 +310,6 @@ Audio_Region::menu ( void )
return m;
}
int
Audio_Region::handle ( int m )
{
static int ox, oy;
static bool copied = false;
static nframes_t os;
int X = Fl::event_x();
int Y = Fl::event_y();
Logger _log( this );
switch ( m )
{
case FL_FOCUS:
case FL_UNFOCUS:
return 1;
case FL_KEYBOARD:
return menu().test_shortcut() != 0;
case FL_ENTER:
return Sequence_Region::handle( m );
case FL_LEAVE:
return Sequence_Region::handle( m );
case FL_PUSH:
{
/* splitting */
if ( test_press( FL_BUTTON2 | FL_SHIFT ) )
{
/* split */
if ( ! copied )
{
Loggable::block_start();
Audio_Region *copy = new Audio_Region( *this );
trim( RIGHT, X );
copy->trim( LEFT, X );
sequence()->add( copy );
log_end();
Loggable::block_end();
}
return 0;
}
else
{
ox = x() - X;
oy = y() - Y;
/* for panning */
os = _r->offset;
if ( test_press( FL_BUTTON2 | FL_CTRL ) )
{
normalize();
/* FIXME: wrong place for this? */
sequence()->handle_widget_change( start(), length() );
redraw();
return 1;
}
else if ( test_press( FL_BUTTON3 ) )
{
/* context menu */
menu_popup( &menu() );
return 1;
}
else
return Sequence_Region::handle( m );
}
break;
}
case FL_RELEASE:
{
Sequence_Region::handle( m );
copied = false;
return 1;
}
case FL_DRAG:
if ( ! _drag )
{
begin_drag( Drag( x() - X, y() - Y, x_to_offset( X ) ) );
_log.hold();
}
if ( test_press( FL_BUTTON1 | FL_SHIFT | FL_CTRL ) )
{
/* panning */
int d = (ox + X) - x();
long td = timeline->x_to_ts( d );
if ( td > 0 && os < (nframes_t)td )
_r->offset = 0;
else
_r->offset = os - td;
redraw();
return 1;
}
return Sequence_Region::handle( m );
default:
return Sequence_Region::handle( m );
break;
}
return 0;
}
/** Draws the curve for a single fade. /X/ and /W/ repersent the
portion of the region covered by this draw, which may or may not
cover the fade in question. */
@ -705,7 +589,137 @@ Audio_Region::draw ( void )
}
int
Audio_Region::handle ( int m )
{
static int ox, oy;
static bool copied = false;
static nframes_t os;
int X = Fl::event_x();
int Y = Fl::event_y();
Logger _log( this );
switch ( m )
{
case FL_FOCUS:
case FL_UNFOCUS:
return 1;
case FL_KEYBOARD:
return menu().test_shortcut() != 0;
case FL_ENTER:
return Sequence_Region::handle( m );
case FL_LEAVE:
return Sequence_Region::handle( m );
case FL_PUSH:
{
/* splitting */
if ( test_press( FL_BUTTON2 | FL_SHIFT ) )
{
/* split */
if ( ! copied )
{
Loggable::block_start();
Audio_Region *copy = new Audio_Region( *this );
trim( RIGHT, X );
copy->trim( LEFT, X );
sequence()->add( copy );
log_end();
Loggable::block_end();
}
return 0;
}
else
{
ox = x() - X;
oy = y() - Y;
/* for panning */
os = _r->offset;
if ( test_press( FL_BUTTON2 | FL_CTRL ) )
{
normalize();
/* FIXME: wrong place for this? */
sequence()->handle_widget_change( start(), length() );
redraw();
return 1;
}
else if ( test_press( FL_BUTTON3 ) )
{
/* context menu */
menu_popup( &menu() );
return 1;
}
else
return Sequence_Region::handle( m );
}
break;
}
case FL_RELEASE:
{
Sequence_Region::handle( m );
copied = false;
return 1;
}
case FL_DRAG:
if ( ! _drag )
{
begin_drag( Drag( x() - X, y() - Y, x_to_offset( X ) ) );
_log.hold();
}
if ( test_press( FL_BUTTON1 | FL_SHIFT | FL_CTRL ) )
{
/* panning */
int d = (ox + X) - x();
long td = timeline->x_to_ts( d );
if ( td > 0 && os < (nframes_t)td )
_r->offset = 0;
else
_r->offset = os - td;
redraw();
return 1;
}
return Sequence_Region::handle( m );
default:
return Sequence_Region::handle( m );
break;
}
return 0;
}
/**********/
/* Public */
/**********/
/** return the name of the audio source this region represents */
const char *
Audio_Region::source_name ( void ) const
{
return _clip->name();
}
/** set the amplitude scaling for this region from the normalization
* factor for the range of samples represented by this region */
void
Audio_Region::normalize ( void )
{

View File

@ -111,13 +111,24 @@ private:
static void menu_cb ( Fl_Widget *w, void *v );
void menu_cb ( const Fl_Menu_ *m );
void draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool filled, int X, int W );
protected:
virtual void get ( Log_Entry &e ) const;
virtual void set ( Log_Entry &e );
int handle ( int m );
void draw_box( void );
void draw ( void );
void resize ( void );
public:
LOG_CREATE_FUNC( Audio_Region );
SEQUENCE_WIDGET_CLONE_FUNC( Audio_Region );
static Fl_Boxtype _box;
static Fl_Color _selection_color;
Fl_Color selection_color ( void ) const { return _selection_color; }
@ -132,37 +143,18 @@ public:
bool current ( void ) const { return this == belowmouse(); }
public:
const char * source_name ( void ) const;
LOG_CREATE_FUNC( Audio_Region );
SEQUENCE_WIDGET_CLONE_FUNC( Audio_Region );
~Audio_Region ( )
{
log_destroy();
}
Fl_Boxtype box ( void ) const { return Audio_Region::_box; }
Fl_Align align ( void ) const { return (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_BOTTOM /*| FL_ALIGN_CLIP*/ | FL_ALIGN_INSIDE); }
Audio_Region ( const Audio_Region & rhs );
Audio_Region ( Audio_File *c );
Audio_Region ( Audio_File *c, Sequence *t, nframes_t o );
~Audio_Region ( );
void draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool filled, int X, int W );
int handle ( int m );
void draw_box( void );
void draw ( void );
void resize ( void );
Fl_Boxtype box ( void ) const { return Audio_Region::_box; }
Fl_Align align ( void ) const { return (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_BOTTOM /*| FL_ALIGN_CLIP*/ | FL_ALIGN_INSIDE); }
void normalize ( void );
/* Engine */
nframes_t read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) const;
nframes_t write ( nframes_t nframes );

View File

@ -61,7 +61,9 @@ Audio_Sequence::~Audio_Sequence ( )
Loggable::block_end();
}
/** return a pointer to the current capture region for this sequence */
const Audio_Region *
Audio_Sequence::capture_region ( void ) const
{
@ -129,7 +131,6 @@ deurlify ( char *url )
*w = NULL;
}
void
Audio_Sequence::handle_widget_change ( nframes_t start, nframes_t length )
{

View File

@ -41,16 +41,17 @@ protected:
void handle_widget_change ( nframes_t start, nframes_t length );
void draw ( void );
int handle ( int m );
public:
LOG_CREATE_FUNC( Audio_Sequence );
Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; }
Audio_Sequence ( Track *track );
~Audio_Sequence ( );
Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; }
Sequence * clone_empty ( void )
{
@ -59,13 +60,6 @@ public:
return t;
}
// const char *class_name ( void ) { return "Audio_Sequence"; }
void draw ( void );
int handle ( int m );
void dump ( void );
void remove_selected ( void );
const Audio_Region *capture_region ( void ) const;
nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels );

View File

@ -28,7 +28,6 @@
class Control_Sequence : public Sequence
{
/* not permitted */
Control_Sequence ( const Control_Sequence &rhs );
Control_Sequence & operator = ( const Control_Sequence &rhs );
@ -47,6 +46,7 @@ private:
void init ( void );
void draw_curve ( bool flip, bool filled );
protected:
@ -59,9 +59,9 @@ protected:
init();
}
private:
void draw_curve ( bool flip, bool filled );
void draw ( void );
int handle ( int m );
public:
@ -76,12 +76,6 @@ public:
Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; }
// const char *class_name ( void ) { return "Control_Sequence"; }
void draw ( void );
int handle ( int m );
/* Engine */
void output ( Port *p ) { _output = p; }
nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes );

View File

@ -17,7 +17,6 @@
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
#include "../Track.H"
// #include "Audio_Sequence.H"
class Audio_Sequence;
@ -28,6 +27,8 @@ class Audio_Sequence;
#include "Disk_Stream.H"
#include "dsp.h"
/**********/
/* Engine */
/**********/
@ -40,12 +41,6 @@ class Audio_Sequence;
that is, at startup time. The default is 5 seconds, which may or
may not be excessive depending on various external factors. */
/* FIXME: deal with (jack) buffer size changes */
/* FIXME: needs error handling everywhere! */
/* TODO: read/write data from/to disk in larger chunks to avoid
* excessive seeking. 256k is supposedly the sweetspot. */
//float Disk_Stream::seconds_to_buffer = 5.0f;
float Disk_Stream::seconds_to_buffer = 2.0f;
/* this is really only a rough estimate. The actual amount of data
read depends on many factors. Overlapping regions, for example, will
@ -53,6 +48,8 @@ float Disk_Stream::seconds_to_buffer = 2.0f;
counts.*/
size_t Disk_Stream::disk_io_kbytes = 256;
Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track )
{
assert( channels );
@ -85,6 +82,7 @@ Disk_Stream::~Disk_Stream ( )
engine->unlock();
}
/** flush buffers and reset. Must only be called from the RT thread. */
void

View File

@ -30,6 +30,8 @@
#include "util/Thread.H"
Engine::Engine ( ) : _thread( "RT" )
{
_freewheeling = false;
@ -39,6 +41,8 @@ Engine::Engine ( ) : _thread( "RT" )
_xruns = 0;
}
/*******************/
/* Static Wrappers */
/*******************/
@ -79,15 +83,24 @@ Engine::buffer_size ( nframes_t nframes, void *arg )
return ((Engine*)arg)->buffer_size( nframes );
}
void
Engine::thread_init ( void *arg )
{
((Engine*)arg)->thread_init();
}
void
Engine::request_locate ( nframes_t frame )
Engine::shutdown ( void *arg )
{
if ( timeline )
timeline->seek( frame );
((Engine*)arg)->shutdown();
}
/*************/
/* Callbacks */
/*************/
/* THREAD: RT */
/** This is the jack xrun callback */
int
@ -114,7 +127,6 @@ Engine::freewheel ( bool starting )
int
Engine::buffer_size ( nframes_t nframes )
{
/* TODO: inform all disktreams the the buffer size has changed */
timeline->resize_buffers( nframes );
return 0;
@ -166,7 +178,6 @@ Engine::sync ( jack_transport_state_t state, jack_position_t *pos )
return 0;
}
/* THREAD: RT */
void
Engine::timebase ( jack_transport_state_t, jack_nframes_t, jack_position_t *pos, int )
@ -189,7 +200,6 @@ Engine::timebase ( jack_transport_state_t, jack_nframes_t, jack_position_t *pos,
}
/* THREAD: RT */
int
Engine::process ( nframes_t nframes )
@ -235,7 +245,7 @@ Engine::process ( nframes_t nframes )
return 0;
}
/* THREAD: RT */
/** enter or leave freehweeling mode */
void
Engine::freewheeling ( bool yes )
@ -244,31 +254,22 @@ Engine::freewheeling ( bool yes )
WARNING( "Unkown error while setting freewheeling mode" );
}
void
Engine::thread_init ( void *arg )
{
((Engine*)arg)->thread_init();
}
/* TRHEAD: RT */
void
Engine::thread_init ( void )
{
_thread.set( "RT" );
}
void
Engine::shutdown ( void *arg )
{
((Engine*)arg)->shutdown();
}
/* THREAD: RT */
void
Engine::shutdown ( void )
{
_zombified = true;
}
/** Connect to JACK */
int
Engine::init ( void )
{
@ -300,3 +301,10 @@ Engine::init ( void )
/* we don't need to create any ports until tracks are created */
return 1;
}
void
Engine::request_locate ( nframes_t frame )
{
if ( timeline )
timeline->seek( frame );
}

View File

@ -35,23 +35,12 @@ class Engine : public Mutex
Thread _thread; /* only used for thread checking */
/* 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 */
nframes_t _sample_rate;
volatile int _xruns;
volatile bool _freewheeling;
volatile bool _zombified;
static void shutdown ( void *arg );
void shutdown ( void );
static int process ( nframes_t nframes, void *arg );
@ -72,6 +61,8 @@ class Engine : public Mutex
Engine ( const Engine &rhs );
Engine & operator = ( const Engine &rhs );
void request_locate ( nframes_t frame );
private:
friend class Port;
@ -85,8 +76,6 @@ public:
int init ( void );
void request_locate ( nframes_t frame );
nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); }
float frame_rate ( void ) const { return jack_get_sample_rate( _client ); }
nframes_t sample_rate ( void ) const { return _sample_rate; }

View File

@ -22,6 +22,8 @@
peakfile reading/writing.
*/
/* Code for peakfile reading, resampling, generation and streaming */
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -39,6 +41,7 @@
#include "assert.h"
#include "util/debug.h"
#include "util/Thread.H"
#include "util/file.h"
#include <errno.h>
@ -47,6 +50,7 @@
using std::min;
using std::max;
/* whether to cache peaks at multiple resolutions on disk to
* drastically improve performance */
@ -56,7 +60,6 @@ const int Peaks::cache_minimum = 256; /* minimum chunksize to build pea
const int Peaks::cache_levels = 8; /* number of sampling levels in peak cache */
const int Peaks::cache_step = 1; /* powers of two between each level. 4 == 256, 2048, 16384, ... */
Peaks::peakbuffer Peaks::_peakbuf;
@ -72,17 +75,6 @@ peakname ( const char *filename )
return (const char*)&file;
}
/** update the modification time of file referred to by /fd/ */
static void
touch ( int fd )
{
struct stat st;
fstat( fd, &st );
fchmod( fd, st.st_mode );
}
Peaks::Peaks ( Audio_File *c )
@ -97,6 +89,8 @@ Peaks::~Peaks ( )
delete _peak_writer;
}
/** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be
* called before any calls to operator[] */
int
@ -389,7 +383,6 @@ Peaks::read_peakfile_peaks ( Peak *peaks, nframes_t s, int npeaks, nframes_t chu
return _peakfile.read_peaks( peaks, s, npeaks, chunksize );
}
int
Peaks::read_source_peaks ( Peak *peaks, int npeaks, nframes_t chunksize ) const
{
@ -472,27 +465,9 @@ Peaks::read_peaks ( nframes_t s, int npeaks, nframes_t chunksize ) const
bool
Peaks::current ( void ) const
{
int sfd, pfd;
if ( ( sfd = ::open( _clip->name(), O_RDONLY ) ) < 0 )
return true;
if ( ( pfd = ::open( peakname( _clip->name() ), O_RDONLY ) ) < 0 )
return false;
struct stat sst, pst;
fstat( sfd, &sst );
fstat( pfd, &pst );
close( sfd );
close( pfd );
return sst.st_mtime <= pst.st_mtime;
return ! newer( _clip->name(), peakname( _clip->name() ) );
}
bool
Peaks::make_peaks ( void ) const
{
@ -817,7 +792,6 @@ Peaks::Builder::make_peaks ( void )
return true;
}
Peaks::Builder::Builder ( const Peaks *peaks ) : _peaks( peaks )
{
fp = NULL;

View File

@ -17,6 +17,8 @@
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
/* Wrapper for a JACK audio port */
#include "Port.H"
#include <string.h>
@ -25,6 +27,8 @@
#include <stdio.h> // sprintf
static const char *name_for_port ( Port::type_e dir, const char *base, int n, const char *type );
/* nframes is the number of frames to buffer */
@ -39,6 +43,22 @@ Port::Port ( const char *name, type_e dir )
activate( name, dir );
}
Port::Port ( type_e dir, const char *base, int n, const char *type )
{
const char *name = name_for_port( dir, base, n, type );
activate( name, dir );
}
Port::~Port ( )
{
/* if ( _port ) */
/* jack_port_unregister( engine->client(), _port ); */
}
static const char *
name_for_port ( Port::type_e dir, const char *base, int n, const char *type )
{
@ -54,27 +74,6 @@ name_for_port ( Port::type_e dir, const char *base, int n, const char *type )
return pname;
}
Port::Port ( type_e dir, const char *base, int n, const char *type )
{
const char *name = name_for_port( dir, base, n, type );
activate( name, dir );
}
/* Port::Port ( ) */
/* { */
/* _name = NULL; */
/* _port = NULL; */
/* } */
Port::~Port ( )
{
/* if ( _port ) */
/* jack_port_unregister( engine->client(), _port ); */
}
void
Port::activate ( const char *name, type_e dir )
{

View File

@ -25,6 +25,8 @@
#include "Record_DS.H"
#include "Engine.H"
/**********/
/* Engine */
/**********/
@ -195,9 +197,6 @@ Track::resize_buffers ( nframes_t nframes )
playback_ds->resize_buffers( nframes );
}
/* #include "Audio_Region.H" */
#include <time.h>
/** very cheap UUID generator... */

View File

@ -305,44 +305,6 @@ Loggable::do_this ( const char *s, bool reverse )
return true;
}
static int
backwards_fgetc ( FILE *fp )
{
int c;
if ( fseek( fp, -1, SEEK_CUR ) != 0 )
return -1;
c = fgetc( fp );
fseek( fp, -1, SEEK_CUR );
return c;
}
static char *
backwards_fgets ( char *s, int size, FILE *fp )
{
if ( fseek( fp, -1, SEEK_CUR ) != 0 )
return NULL;
int c;
while ( ( c = backwards_fgetc( fp ) ) >= 0 )
if ( '\n' == c )
break;
long here = ftell( fp );
fseek( fp, 1, SEEK_CUR );
char *r = fgets( s, size, fp );
fseek( fp, here, SEEK_SET );
return r;
}
/** Reverse the last journal transaction */
void
Loggable::undo ( void )
@ -386,6 +348,9 @@ Loggable::undo ( void )
_undo_offset = uo;
}
/** Make all loggable ids consecutive. This invalidates any existing
* journal or snapshot, so you *must* write out a new one after
* performing this operation*/
void
Loggable::compact_ids ( void )
{
@ -406,9 +371,8 @@ Loggable::compact_ids ( void )
_log_id = id;
}
/* FIXME: we need a version of this that is fully const, right? */
/** write a snapshot of the state of all loggable objects, sufficient
* for later reconstruction, to /fp/ */
/** write a snapshot of the current state of all loggable objects to
* file handle /fp/ */
bool
Loggable::snapshot ( FILE *fp )
{
@ -437,6 +401,8 @@ Loggable::snapshot ( FILE *fp )
return true;
}
/** write a snapshot of the current state of all loggable objects to
* file /name/ */
bool
Loggable::snapshot ( const char *name )
{
@ -575,7 +541,6 @@ Loggable::log_print( const Log_Entry *o, const Log_Entry *n ) const
log( "\n" );
}
/** Remember current object state for later comparison. *Must* be
* called before any user action that might change one of the object's
* journaled properties. */

View File

@ -56,6 +56,10 @@ int Project::_lockfd = 0;
/***********/
/* Private */
/***********/
void
Project::set_name ( const char *name )
{
@ -75,27 +79,6 @@ Project::set_name ( const char *name )
*s = ' ';
}
bool
Project::close ( void )
{
if ( ! open() )
return true;
tle->save_timeline_settings();
Loggable::close();
write_info();
_is_open = false;
*Project::_name = '\0';
release_lock( &_lockfd, ".lock" );
return true;
}
bool
Project::write_info ( void )
{
@ -139,7 +122,33 @@ Project::read_info ( void )
return true;
}
/** ensure a project is valid before opening it... */
/**********/
/* Public */
/**********/
/** Close the project (reclaiming all memory) */
bool
Project::close ( void )
{
if ( ! open() )
return true;
tle->save_timeline_settings();
Loggable::close();
write_info();
_is_open = false;
*Project::_name = '\0';
release_lock( &_lockfd, ".lock" );
return true;
}
/** Ensure a project is valid before opening it... */
bool
Project::validate ( const char *name )
{
@ -169,7 +178,8 @@ Project::validate ( const char *name )
return r;
}
/** try to open project /name/. Returns 0 if sucsessful, an error code otherwise */
/** Try to open project /name/. Returns 0 if sucsessful, an error code
* otherwise */
int
Project::open ( const char *name )
{
@ -207,6 +217,8 @@ Project::open ( const char *name )
return 0;
}
/** Create a new project /name/ from existing template
* /template_name/ */
bool
Project::create ( const char *name, const char *template_name )
{
@ -251,3 +263,10 @@ Project::create ( const char *name, const char *template_name )
return false;
}
}
/** Replace the journal with a snapshot of the current state */
void
Project::compact ( void )
{
Loggable::compact();
}

View File

@ -28,6 +28,10 @@ class Project
static char _name[256];
static char _path[512];
static bool write_info ( void );
static bool read_info ( void );
static void set_name ( const char *name );
public:
enum
@ -37,10 +41,8 @@ public:
E_PERM = -3,
};
static bool write_info ( void );
static bool read_info ( void );
static const char *name ( void ) { return Project::_name; }
static void set_name ( const char *name );
static void compact ( void );
static bool close ( void );
static bool validate ( const char *name );
static int open ( const char *name );

View File

@ -17,7 +17,6 @@
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
#include "Sequence.H"
#include "Timeline.H"
@ -25,12 +24,20 @@
#include "Track.H"
#include "FL/event_name.H"
#include "Transport.H" // for locate()
#include "../FL/Boxtypes.H"
using namespace std;
queue <Sequence_Widget *> Sequence::_delete_queue;
Sequence::Sequence ( Track *track ) : Fl_Widget( 0, 0, 0, 0 ), Loggable( true )
{
init();
@ -59,22 +66,6 @@ Sequence::init ( void )
// clear_visible_focus();
}
void
Sequence::clear ( void )
{
for ( std::list <Sequence_Widget*>::iterator i = _widgets.begin();
i != _widgets.end(); ++i )
{
Sequence_Widget *w = *i;
*i = NULL;
delete w;
}
_widgets.clear();
}
Sequence::~Sequence ( )
{
DMESSAGE( "destroying sequence" );
@ -86,12 +77,37 @@ Sequence::~Sequence ( )
FATAL( "programming error: leaf destructor must call Sequence::clear()!" );
}
/** remove all widgets from this sequence */
void
Sequence::clear ( void )
{
Loggable::block_start();
for ( std::list <Sequence_Widget*>::iterator i = _widgets.begin();
i != _widgets.end(); ++i )
{
Sequence_Widget *w = *i;
*i = NULL;
delete w;
}
_widgets.clear();
Loggable::block_end();
}
/** given screen pixel coordinate X, return an absolute frame offset into this sequence */
nframes_t
Sequence::x_to_offset ( int X )
{
return timeline->xoffset + timeline->x_to_ts( X - x() );
}
/** sort the widgets in this sequence by position */
void
Sequence::sort ( void )
{
@ -112,95 +128,12 @@ Sequence::overlaps ( Sequence_Widget *r )
return NULL;
}
void
Sequence::draw ( void )
{
if ( ! fl_not_clipped( x(), y(), w(), h() ) )
return;
fl_push_clip( x(), y(), w(), h() );
/* draw the box with the ends cut off. */
draw_box( box(), x() - Fl::box_dx( box() ) - 1, y(), w() + Fl::box_dw( box() ) + 2, h(), color() );
int X, Y, W, H;
fl_clip_box( x(), y(), w(), h(), X, Y, W, H );
/* if ( Sequence_Widget::pushed() && Sequence_Widget::pushed()->sequence() == this ) */
/* { */
/* /\* make sure the Sequence_Widget::pushed widget is above all others *\/ */
/* remove( Sequence_Widget::pushed() ); */
/* add( Sequence_Widget::pushed() ); */
/* } */
// printf( "track::draw %d,%d %dx%d\n", X,Y,W,H );
timeline->draw_measure_lines( X, Y, W, H, color() );
for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r )
(*r)->draw_box();
for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r )
(*r)->draw();
fl_pop_clip();
}
void
Sequence::remove ( Sequence_Widget *r )
{
timeline->wrlock();
_widgets.remove( r );
timeline->unlock();
handle_widget_change( r->start(), r->length() );
}
void
Sequence::remove_selected ( void )
{
Loggable::block_start();
for ( list <Sequence_Widget *>::iterator r = _widgets.begin(); r != _widgets.end(); )
if ( (*r)->selected() )
{
Sequence_Widget *t = *r;
_widgets.erase( r++ );
delete t;
}
else
++r;
Loggable::block_end();
}
void
Sequence::handle_widget_change ( nframes_t start, nframes_t length )
{
// timeline->update_length( start + length );
}
/** calculate the length of this sequence by looking at the end of the
* least widget it contains */
nframes_t
Sequence::length ( void ) const
{
nframes_t l = 0;
for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r )
l = max( l, (*r)->start() + (*r)->length() );
return l;
}
Sequence_Widget *
Sequence::widget_at ( nframes_t ts, int Y )
{
@ -212,6 +145,8 @@ Sequence::widget_at ( nframes_t ts, int Y )
return NULL;
}
/** return a pointer to the widget under the current mouse event, or
* NULL if no widget intersects the event coordinates */
Sequence_Widget *
Sequence::event_widget ( void )
{
@ -219,17 +154,6 @@ Sequence::event_widget ( void )
return widget_at( ets, Fl::event_y() );
}
void
Sequence::select_range ( int X, int W )
{
nframes_t sts = x_to_offset( X );
nframes_t ets = sts + timeline->x_to_ts( W );
for ( list <Sequence_Widget *>::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); ++r )
if ( ! ( (*r)->start() > ets || (*r)->start() + (*r)->length() < sts ) )
(*r)->select();
}
void
Sequence::add ( Sequence_Widget *r )
{
@ -254,13 +178,25 @@ Sequence::add ( Sequence_Widget *r )
handle_widget_change( r->start(), r->length() );
}
void
Sequence::remove ( Sequence_Widget *r )
{
timeline->wrlock();
_widgets.remove( r );
timeline->unlock();
handle_widget_change( r->start(), r->length() );
}
static nframes_t
abs_diff ( nframes_t n1, nframes_t n2 )
{
return n1 > n2 ? n1 - n2 : n2 - n1;
}
/* snap /r/ to nearest edge */
/** snap widget /r/ to nearest edge */
void
Sequence::snap ( Sequence_Widget *r )
{
@ -306,38 +242,45 @@ Sequence::snap ( Sequence_Widget *r )
r->start( f );
}
/** return the location of the next widget from frame /from/ */
nframes_t
Sequence::next ( nframes_t from ) const
void
Sequence::draw ( void )
{
for ( list <Sequence_Widget*>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ )
if ( (*i)->start() > from )
return (*i)->start();
if ( _widgets.size() )
return _widgets.back()->start();
else
return 0;
if ( ! fl_not_clipped( x(), y(), w(), h() ) )
return;
fl_push_clip( x(), y(), w(), h() );
/* draw the box with the ends cut off. */
draw_box( box(), x() - Fl::box_dx( box() ) - 1, y(), w() + Fl::box_dw( box() ) + 2, h(), color() );
int X, Y, W, H;
fl_clip_box( x(), y(), w(), h(), X, Y, W, H );
/* if ( Sequence_Widget::pushed() && Sequence_Widget::pushed()->sequence() == this ) */
/* { */
/* /\* make sure the Sequence_Widget::pushed widget is above all others *\/ */
/* remove( Sequence_Widget::pushed() ); */
/* add( Sequence_Widget::pushed() ); */
/* } */
// printf( "track::draw %d,%d %dx%d\n", X,Y,W,H );
timeline->draw_measure_lines( X, Y, W, H, color() );
for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r )
(*r)->draw_box();
for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r )
(*r)->draw();
fl_pop_clip();
}
/** return the location of the next widget from frame /from/ */
nframes_t
Sequence::prev ( nframes_t from ) const
{
for ( list <Sequence_Widget*>::const_reverse_iterator i = _widgets.rbegin(); i != _widgets.rend(); i++ )
if ( (*i)->start() < from )
return (*i)->start();
if ( _widgets.size() )
return _widgets.front()->start();
else
return 0;
}
#include "FL/event_name.H"
#include "Transport.H" // for locate()
int
Sequence::handle ( int m )
{
@ -509,3 +452,85 @@ Sequence::handle ( int m )
}
}
}
/**********/
/* Public */
/**********/
/** calculate the length of this sequence by looking at the end of the
* least widget it contains */
/** return the length in frames of this sequence calculated from the
* right edge of the rightmost widget */
nframes_t
Sequence::length ( void ) const
{
nframes_t l = 0;
for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); ++r )
l = max( l, (*r)->start() + (*r)->length() );
return l;
}
/** return the location of the next widget from frame /from/ */
nframes_t
Sequence::next ( nframes_t from ) const
{
for ( list <Sequence_Widget*>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ )
if ( (*i)->start() > from )
return (*i)->start();
if ( _widgets.size() )
return _widgets.back()->start();
else
return 0;
}
/** return the location of the next widget from frame /from/ */
nframes_t
Sequence::prev ( nframes_t from ) const
{
for ( list <Sequence_Widget*>::const_reverse_iterator i = _widgets.rbegin(); i != _widgets.rend(); i++ )
if ( (*i)->start() < from )
return (*i)->start();
if ( _widgets.size() )
return _widgets.front()->start();
else
return 0;
}
/** delete all selected widgets in this sequence */
void
Sequence::remove_selected ( void )
{
Loggable::block_start();
for ( list <Sequence_Widget *>::iterator r = _widgets.begin(); r != _widgets.end(); )
if ( (*r)->selected() )
{
Sequence_Widget *t = *r;
_widgets.erase( r++ );
delete t;
}
else
++r;
Loggable::block_end();
}
/** select all widgets intersecting with the range defined by the
* pixel coordinates X through W */
void
Sequence::select_range ( int X, int W )
{
nframes_t sts = x_to_offset( X );
nframes_t ets = sts + timeline->x_to_ts( W );
for ( list <Sequence_Widget *>::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); ++r )
if ( ! ( (*r)->start() > ets || (*r)->start() + (*r)->length() < sts ) )
(*r)->select();
}

View File

@ -21,6 +21,29 @@
#include <FL/fl_draw.H>
Sequence_Point::Sequence_Point ( const Sequence_Point &rhs ) : Sequence_Widget( rhs )
{
if ( _label )
_label = strdup( rhs._label );
}
Sequence_Point::Sequence_Point ( )
{
_label = NULL;
color( FL_CYAN );
}
Sequence_Point::~Sequence_Point ( )
{
if ( _label )
free( _label );
}
void
Sequence_Point::get ( Log_Entry &e ) const
{

View File

@ -33,11 +33,13 @@ protected:
void get ( Log_Entry &e ) const;
void set ( Log_Entry &e );
Sequence_Point ( const Sequence_Point &rhs ) : Sequence_Widget( rhs )
{
if ( _label )
_label = strdup( rhs._label );
}
virtual void draw_box ( void );
virtual void draw ( void );
Sequence_Point ( const Sequence_Point &rhs );
Sequence_Point ( );
~Sequence_Point ( );
public:
@ -68,21 +70,4 @@ public:
nframes_t length ( void ) const { return timeline->x_to_ts( abs_w() ); }
Sequence_Point ( )
{
_label = NULL;
color( FL_CYAN );
}
virtual ~Sequence_Point ( )
{
if ( _label )
free( _label );
}
virtual void draw_box ( void );
virtual void draw ( void );
};

View File

@ -20,6 +20,23 @@
#include "Sequence_Region.H"
#include "Track.H"
Sequence_Region::Sequence_Region ( )
{
color( FL_CYAN );
}
Sequence_Region::Sequence_Region ( const Sequence_Region &rhs ) : Sequence_Widget( rhs )
{
}
Sequence_Region::~Sequence_Region ( )
{
}
void
Sequence_Region::get ( Log_Entry &e ) const
{
@ -29,7 +46,6 @@ Sequence_Region::get ( Log_Entry &e ) const
Sequence_Widget::get( e );
}
void
Sequence_Region::set ( Log_Entry &e )
{
@ -49,18 +65,6 @@ Sequence_Region::set ( Log_Entry &e )
Sequence_Widget::set( e );
}
void
Sequence_Region::draw_box ( void )
{
fl_draw_box( box(), line_x(), y(), abs_w(), h(), box_color() );
}
void
Sequence_Region::draw ( void )
{
}
void
Sequence_Region::trim ( enum trim_e t, int X )
{
@ -232,3 +236,14 @@ Sequence_Region::handle ( int m )
return 0;
}
void
Sequence_Region::draw_box ( void )
{
fl_draw_box( box(), line_x(), y(), abs_w(), h(), box_color() );
}
void
Sequence_Region::draw ( void )
{
}

View File

@ -33,20 +33,13 @@ protected:
virtual void get ( Log_Entry &e ) const;
virtual void set ( Log_Entry &e );
Sequence_Region ( )
{
color( FL_CYAN );
}
Sequence_Region ( );
Sequence_Region ( const Sequence_Region &rhs );
virtual ~Sequence_Region ( );
virtual ~Sequence_Region ( )
{
}
Sequence_Region ( const Sequence_Region &rhs ) : Sequence_Widget( rhs )
{
}
virtual int handle ( int m );
virtual void draw_box( void );
virtual void draw ( void );
public:
@ -55,8 +48,4 @@ public:
enum trim_e { NO, LEFT, RIGHT };
void trim ( enum trim_e t, int X );
virtual int handle ( int m );
virtual void draw_box( void );
virtual void draw ( void );
};

View File

@ -63,6 +63,8 @@ Sequence_Widget::~Sequence_Widget ( )
_selection.remove( this );
}
void
Sequence_Widget::get ( Log_Entry &e ) const
{

View File

@ -230,7 +230,7 @@ if ( r < 0 )
if ( n != 2 )
return;
Loggable::compact();}
Project::compact();} selected
xywh {20 20 40 25}
}
Submenu {} {
@ -868,7 +868,7 @@ while ( _window->shown() )
Function {make_window()} {open
} {
Fl_Window _window {
label {New Project} open selected
label {New Project} open
xywh {615 414 550 195} type Double modal xclass Non_DAW visible
} {
Fl_File_Input _name {

View File

@ -23,6 +23,32 @@
Tempo_Point::Tempo_Point ( )
{
timeline->tempo_track->add( this );
}
Tempo_Point::Tempo_Point ( nframes_t when, float bpm )
{
_tempo = bpm;
_make_label();
timeline->tempo_track->add( this );
start( when );
log_create();
}
Tempo_Point::~Tempo_Point ( )
{
timeline->tempo_track->remove( this );
log_destroy();
}
void
Tempo_Point::get ( Log_Entry &e ) const
{
@ -58,33 +84,6 @@ Tempo_Point::set ( Log_Entry &e )
}
Tempo_Point::Tempo_Point ( )
{
timeline->tempo_track->add( this );
}
Tempo_Point::Tempo_Point ( nframes_t when, float bpm )
{
_tempo = bpm;
_make_label();
timeline->tempo_track->add( this );
start( when );
log_create();
}
Tempo_Point::~Tempo_Point ( )
{
timeline->tempo_track->remove( this );
log_destroy();
}
int
Tempo_Point::handle ( int m )

View File

@ -23,6 +23,39 @@
Time_Point::Time_Point ( ) : _time( 4, 4 )
{
timeline->time_track->add( this );
}
Time_Point::Time_Point ( nframes_t when, int bpb, int note ) : _time( bpb, note )
{
_make_label();
timeline->time_track->add( this );
start( when );
log_create();
}
Time_Point::Time_Point ( const Time_Point &rhs ) : Sequence_Point( rhs )
{
_time = rhs._time;
log_create();
}
Time_Point::~Time_Point ( )
{
timeline->time_track->remove( this );
log_destroy();
}
void
Time_Point::get ( Log_Entry &e ) const
{
@ -60,39 +93,6 @@ Time_Point::set ( Log_Entry &e )
_make_label();
}
Time_Point::Time_Point ( ) : _time( 4, 4 )
{
timeline->time_track->add( this );
}
Time_Point::Time_Point ( nframes_t when, int bpb, int note ) : _time( bpb, note )
{
_make_label();
timeline->time_track->add( this );
start( when );
log_create();
}
Time_Point::Time_Point ( const Time_Point &rhs ) : Sequence_Point( rhs )
{
_time = rhs._time;
log_create();
}
Time_Point::~Time_Point ( )
{
timeline->time_track->remove( this );
log_destroy();
}
int
Time_Point::handle ( int m )
{
@ -113,12 +113,9 @@ Time_Point::handle ( int m )
return Sequence_Point::handle( m );
}
#include <FL/Fl_Int_Input.H>
#include <FL/Fl_Menu_Window.H>
class Time_Point_Editor : public Fl_Menu_Window
{
@ -196,7 +193,6 @@ public:
}
};
bool
Time_Point::edit ( time_sig *sig )
{

View File

@ -106,6 +106,7 @@ Timeline::adjust_vscroll ( void )
vscroll->value( _yposition, h() - rulers->h() - hscroll->h(), 0, pack_visible_height( tracks ) );
}
/** recalculate the size of horizontal scrolling area and inform scrollbar */
void
Timeline::adjust_hscroll ( void )
{
@ -157,6 +158,7 @@ Timeline::menu_cb ( Fl_Widget *w, void *v )
((Timeline*)v)->menu_cb( (Fl_Menu_*)w );
}
/** ensure that p1 is less than p2 */
void
Timeline::fix_range ( void )
{
@ -466,24 +468,6 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi
}
/* float */
/* Timeline::beats_per_minute ( nframes_t when ) const */
/* { */
/* /\* return tempo_track->beats_per_minute( when ); *\/ */
/* } */
/* int */
/* Timeline::beats_per_bar ( nframes_t when ) const */
/* { */
/* time_sig t = time_track->time( when ); */
/* return t.beats_per_bar; */
/* } */
void
Timeline::beats_per_minute ( nframes_t when, float bpm )
{
@ -496,7 +480,6 @@ Timeline::time ( nframes_t when, int bpb, int note_type )
time_track->add( new Time_Point( when, bpb, note_type ) );
}
/************/
/* Snapping */
/************/
@ -590,7 +573,6 @@ Timeline::next_line ( nframes_t *frame, bool bar ) const
}
}
/** Set the value pointed to by /frame/ to the frame number of the of
the nearest measure line to *less than* /when/. Returns true if
the new value of *frame is valid, false otherwise. */
@ -612,17 +594,17 @@ Timeline::prev_line ( nframes_t *frame, bool bar ) const
}
}
/** given screen pixel coordinate /x/ return frame offset into
* timeline, taking into account the current scroll position, widget
* layout, etc. */
nframes_t
Timeline::x_to_offset ( int x ) const
{
return x_to_ts( max( 0, x - Track::width() ) ) + xoffset;
}
/** draws a single measure line */
static void
draw_measure_cb ( nframes_t frame, const BBT &bbt, void *arg )
@ -647,6 +629,7 @@ draw_measure_cb ( nframes_t frame, const BBT &bbt, void *arg )
/* FIXME: wrong place for this */
const float ticks_per_beat = 1920.0;
/** re-render the unified tempomap based on the current contents of the Time and Tempo sequences */
void
Timeline::update_tempomap ( void )
{
@ -664,6 +647,7 @@ Timeline::update_tempomap ( void )
_tempomap.sort( Sequence_Widget::sort_func );
}
/** return a stucture containing the BBT info which applies at /frame/ */
position_info
Timeline::solve_tempomap ( nframes_t frame ) const
{
@ -782,6 +766,7 @@ done:
return pos;
}
/** maybe draw appropriate measure lines in rectangle defined by X, Y, W, and H, using color /color/ as a base */
void
Timeline::draw_measure_lines ( int X, int Y, int W, int H, Fl_Color color )
{
@ -804,36 +789,6 @@ Timeline::draw_measure_lines ( int X, int Y, int W, int H, Fl_Color color )
}
/* /\** just like draw mesure lines except that it also draws the BBT values. *\/ */
/* void */
/* Timeline::draw_measure_BBT ( int X, int Y, int W, int H, Fl_Color color ) */
/* { */
/* // render_tempomap( X, Y, W, H, color, true ); */
/* } */
void
Timeline::xposition ( int X )
{
// _old_xposition = xoffset;
/* /\* FIXME: shouldn't have to do this... *\/ */
/* X = min( X, ts_to_x( length() ) - tracks->w() - Track::width() ); */
xoffset = x_to_ts( X );
damage( FL_DAMAGE_SCROLL );
}
void
Timeline::yposition ( int Y )
{
// _old_yposition = _yposition;
_yposition = Y;
damage( FL_DAMAGE_SCROLL );
}
void
Timeline::draw_clip ( void * v, int X, int Y, int W, int H )
{
@ -855,6 +810,7 @@ Timeline::draw_clip ( void * v, int X, int Y, int W, int H )
fl_pop_clip();
}
/** handle resize event */
void
Timeline::resize ( int X, int Y, int W, int H )
{
@ -868,6 +824,7 @@ Timeline::resize ( int X, int Y, int W, int H )
vscroll->size( vscroll->w(), H - 18 );
}
/** draw ancillary cursors (not necessarily in the overlay plane) */
void
Timeline::draw_cursors ( void ) const
{
@ -960,7 +917,7 @@ done:
}
/** draw a single cursor line at /frame/ with color /color/ using symbol routine /symbol/ for the cap */
void
Timeline::draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const
{
@ -1031,8 +988,7 @@ Timeline::redraw_playhead ( void )
}
}
/** called so many times a second to redraw the playhead etc. */
/** called so many times a second to redraw the playhead etc. */
void
Timeline::update_cb ( void *arg )
{
@ -1043,6 +999,7 @@ Timeline::update_cb ( void *arg )
tl->redraw_playhead();
}
/** draw cursors in overlay plane */
void
Timeline::draw_overlay ( void )
{
@ -1075,9 +1032,7 @@ Timeline::draw_overlay ( void )
}
// #include "Sequence_Widget.H"
/** select all widgets in inside rectangle /r/ */
/** select sequence widgets within rectangle /r/ */
void
Timeline::select ( const Rectangle &r )
{
@ -1092,19 +1047,20 @@ Timeline::select ( const Rectangle &r )
}
}
/** delete all selected sequence widgets */
void
Timeline::delete_selected ( void )
{
Sequence_Widget::delete_selected();
}
/** clear the selection of seqeunce widgets */
void
Timeline::select_none ( void )
{
Sequence_Widget::select_none();
}
/** An unfortunate necessity for implementing our own DND aside from
* the (bogus) native FLTK system */
Track *
@ -1137,19 +1093,6 @@ Timeline::handle_scroll ( int m )
return 0;
}
nframes_t
Timeline::length ( void ) const
{
nframes_t l = 0;
for ( int i = tracks->children(); i--; )
l = max( l, ((Track*)tracks->child( i ))->sequence()->length() );
// adjust_hscroll();
return l;
}
int
Timeline::handle ( int m )
{
@ -1293,13 +1236,82 @@ Timeline::handle ( int m )
}
}
/** retrun a pointer to the track named /name/, or NULL if no track is named /name/ */
Track *
Timeline::track_by_name ( const char *name )
{
for ( int i = tracks->children(); i-- ; )
{
Track *t = (Track*)tracks->child( i );
if ( ! strcmp( name, t->name() ) )
return t;
}
return NULL;
}
/** return a malloc'd string representing a unique name for a new track */
char *
Timeline::get_unique_track_name ( const char *name )
{
char pat[256];
strcpy( pat, name );
for ( int i = 1; track_by_name( pat ); ++i )
snprintf( pat, sizeof( pat ), "%s.%d", name, i );
return strdup( pat );
}
/**********/
/* Public */
/**********/
/** return the current length of the timeline, which is arrived at by
* calculating the end frame of the rightmost audio region on an
* active audio sequence. Control_Points, etc. do not factor into this
* calcaulation. */
nframes_t
Timeline::length ( void ) const
{
nframes_t l = 0;
for ( int i = tracks->children(); i--; )
l = max( l, ((Track*)tracks->child( i ))->sequence()->length() );
// adjust_hscroll();
return l;
}
/** set horizontal scroll postion to absolute pixel coordinate /X/ */
void
Timeline::xposition ( int X )
{
xoffset = x_to_ts( X );
damage( FL_DAMAGE_SCROLL );
}
/** set vertical scroll position to absolute pixel coordinate /Y/ */
void
Timeline::yposition ( int Y )
{
_yposition = Y;
damage( FL_DAMAGE_SCROLL );
}
/** zoom in by one zoom step */
void
Timeline::zoom_in ( void )
{
hscroll->zoom_in();
}
/** zoom out by one zoom step */
void
Timeline::zoom_out ( void )
{
@ -1322,6 +1334,7 @@ Timeline::zoom ( float secs )
redraw();
}
/** fit the zoom to the current length of the timeline (subject to nearest power of two) */
void
Timeline::zoom_fit ( void )
{
@ -1329,33 +1342,7 @@ Timeline::zoom_fit ( void )
zoom( length() / (float)sample_rate() );
}
Track *
Timeline::track_by_name ( const char *name )
{
for ( int i = tracks->children(); i-- ; )
{
Track *t = (Track*)tracks->child( i );
if ( ! strcmp( name, t->name() ) )
return t;
}
return NULL;
}
char *
Timeline::get_unique_track_name ( const char *name )
{
char pat[256];
strcpy( pat, name );
for ( int i = 1; track_by_name( pat ); ++i )
snprintf( pat, sizeof( pat ), "%s.%d", name, i );
return strdup( pat );
}
/** add /track/ to the timeline */
void
Timeline::add_track ( Track *track )
{
@ -1372,6 +1359,7 @@ Timeline::add_track ( Track *track )
}
/** remove /track/ from the timeline */
void
Timeline::remove_track ( Track *track )
{

View File

@ -21,8 +21,6 @@
#include "Transport.H"
/* #include "Port.H" */
#include "../FL/Fl_Sometimes_Input.H"
#include <FL/fl_ask.H>
#include <FL/Fl_Color_Chooser.H>
@ -41,76 +39,54 @@ const char *Track::capture_format = "Wav 24";
void
Track::cb_input_field ( Fl_Widget *, void *v )
Track::Track ( const char *L, int channels ) :
Fl_Group ( 0, 0, 0, 0, 0 )
{
((Track*)v)->cb_input_field();
}
init();
void
Track::cb_button ( Fl_Widget *w, void *v )
{
((Track*)v)->cb_button( w );
if ( L )
name( L );
color( (Fl_Color)rand() );
configure_inputs( channels );
configure_outputs( channels );
log_create();
}
void
Track::cb_input_field ( void )
Track::Track ( ) : Fl_Group( 0, 0, 1, 1 )
{
log_start();
init();
name( name_field->value() );
log_end();
timeline->add_track( this );
}
void
Track::cb_button ( Fl_Widget *w )
Track::~Track ( )
{
Loggable::block_start();
if ( w == record_button )
{
takes = NULL;
control = NULL;
annotation = NULL;
}
if ( w == mute_button )
{
Fl_Group::clear();
}
if ( w == solo_button )
{
if ( solo_button->value() )
++_soloing;
else
--_soloing;
}
else
if ( w == take_menu )
{
int v = take_menu->value();
log_destroy();
switch ( v )
{
case 0: /* show all takes */
show_all_takes( take_menu->menu()[ v ].value() );
return;
case 1: /* new */
sequence( (Audio_Sequence*)sequence()->clone_empty() );
return;
}
timeline->remove_track( this );
const char *s = take_menu->menu()[ v ].text;
/* give up our ports */
configure_inputs( 0 );
configure_outputs( 0 );
for ( int i = takes->children(); i--; )
{
Audio_Sequence *t = (Audio_Sequence*)takes->child( i );
if ( ! strcmp( s, t->name() ) )
{
sequence( t );
redraw();
break;
}
}
}
_sequence = NULL;
if ( _name )
free( _name );
Loggable::block_end();
}
void
@ -231,50 +207,149 @@ Track::init ( void )
}
Track::Track ( const char *L, int channels ) :
Fl_Group ( 0, 0, 0, 0, 0 )
void
Track::set ( Log_Entry &e )
{
init();
for ( int i = 0; i < e.size(); ++i )
{
const char *s, *v;
if ( L )
name( L );
e.get( i, &s, &v );
color( (Fl_Color)rand() );
if ( ! strcmp( s, ":height" ) )
{
size( atoi( v ) );
configure_inputs( channels );
configure_outputs( channels );
// Fl_Widget::size( w(), height() );
resize();
}
else if ( ! strcmp( s, ":selected" ) )
_selected = atoi( v );
// else if ( ! strcmp( s, ":armed"
else if ( ! strcmp( s, ":name" ) )
name( v );
else if ( ! strcmp( s, ":inputs" ) )
configure_inputs( atoi( v ) );
else if ( ! strcmp( s, ":outputs" ) )
configure_outputs( atoi( v ) );
else if ( ! strcmp( s, ":color" ) )
{
color( (Fl_Color)atoll( v ) );
redraw();
}
else if ( ! strcmp( s, ":sequence" ) )
{
int i;
sscanf( v, "%X", &i );
log_create();
if ( i )
{
Audio_Sequence *t = (Audio_Sequence*)Loggable::find( i );
/* FIXME: our track might not have been
* defined yet... what should we do about this
* chicken/egg problem? */
if ( t )
{
// assert( t );
sequence( t );
}
}
}
}
}
Track::~Track ( )
void
Track::get ( Log_Entry &e ) const
{
Loggable::block_start();
takes = NULL;
control = NULL;
annotation = NULL;
Fl_Group::clear();
log_destroy();
timeline->remove_track( this );
/* give up our ports */
configure_inputs( 0 );
configure_outputs( 0 );
_sequence = NULL;
if ( _name )
free( _name );
Loggable::block_end();
e.add( ":name", _name );
e.add( ":sequence", sequence() );
e.add( ":selected", _selected );
e.add( ":height", size() );
e.add( ":inputs", input.size() );
e.add( ":outputs", output.size() );
e.add( ":color", (unsigned long)color());
}
void
Track::cb_input_field ( Fl_Widget *, void *v )
{
((Track*)v)->cb_input_field();
}
void
Track::cb_button ( Fl_Widget *w, void *v )
{
((Track*)v)->cb_button( w );
}
void
Track::cb_input_field ( void )
{
log_start();
name( name_field->value() );
log_end();
}
void
Track::cb_button ( Fl_Widget *w )
{
if ( w == record_button )
{
}
if ( w == mute_button )
{
}
if ( w == solo_button )
{
if ( solo_button->value() )
++_soloing;
else
--_soloing;
}
else
if ( w == take_menu )
{
int v = take_menu->value();
switch ( v )
{
case 0: /* show all takes */
show_all_takes( take_menu->menu()[ v ].value() );
return;
case 1: /* new */
sequence( (Audio_Sequence*)sequence()->clone_empty() );
return;
}
const char *s = take_menu->menu()[ v ].text;
for ( int i = takes->children(); i--; )
{
Audio_Sequence *t = (Audio_Sequence*)takes->child( i );
if ( ! strcmp( s, t->name() ) )
{
sequence( t );
redraw();
break;
}
}
}
}
static int pack_visible( Fl_Pack *p )
{
int v = 0;
@ -342,7 +417,6 @@ Track::size ( int v )
resize();
}
void
Track::add ( Audio_Sequence * t )
{
@ -471,22 +545,6 @@ Track::select ( int X, int Y, int W, int H,
}
}
void
Track::draw ( void )
{
if ( _selected )
{
Fl_Color c = color();
color( FL_RED );
Fl_Group::draw();
color( c );
}
else
Fl_Group::draw();
}
#include <FL/Fl_Menu_Button.H>
@ -601,6 +659,23 @@ Track::menu ( void ) const
#include "FL/event_name.H"
#include "FL/test_press.H"
void
Track::draw ( void )
{
if ( _selected )
{
Fl_Color c = color();
color( FL_RED );
Fl_Group::draw();
color( c );
}
else
Fl_Group::draw();
}
int
Track::handle ( int m )
{

View File

@ -97,16 +97,14 @@ private:
void update_port_names ( void );
const char *name_for_port( Port::type_e type, int n );
Track ( ) : Fl_Group( 0, 0, 1, 1 )
{
init();
timeline->add_track( this );
}
Track ( );
void init ( void );
protected:
void get ( Log_Entry &e ) const;
void set ( Log_Entry &e );
public:
Fl_Input *name_field;
@ -128,76 +126,6 @@ public:
Playback_DS *playback_ds;
Record_DS *record_ds;
// const char *class_name ( void ) { return "Track"; }
void
set ( Log_Entry &e )
{
for ( int i = 0; i < e.size(); ++i )
{
const char *s, *v;
e.get( i, &s, &v );
if ( ! strcmp( s, ":height" ) )
{
size( atoi( v ) );
// Fl_Widget::size( w(), height() );
resize();
}
else if ( ! strcmp( s, ":selected" ) )
_selected = atoi( v );
// else if ( ! strcmp( s, ":armed"
else if ( ! strcmp( s, ":name" ) )
name( v );
else if ( ! strcmp( s, ":inputs" ) )
configure_inputs( atoi( v ) );
else if ( ! strcmp( s, ":outputs" ) )
configure_outputs( atoi( v ) );
else if ( ! strcmp( s, ":color" ) )
{
color( (Fl_Color)atoll( v ) );
redraw();
}
else if ( ! strcmp( s, ":sequence" ) )
{
int i;
sscanf( v, "%X", &i );
if ( i )
{
Audio_Sequence *t = (Audio_Sequence*)Loggable::find( i );
/* FIXME: our track might not have been
* defined yet... what should we do about this
* chicken/egg problem? */
if ( t )
{
// assert( t );
sequence( t );
}
}
}
}
}
virtual void get ( Log_Entry &e ) const
{
e.add( ":name", _name );
e.add( ":sequence", sequence() );
e.add( ":selected", _selected );
e.add( ":height", size() );
e.add( ":inputs", input.size() );
e.add( ":outputs", output.size() );
e.add( ":color", (unsigned long)color());
}
/* for loggable */
LOG_CREATE_FUNC( Track );
@ -270,7 +198,6 @@ public:
void draw ( void );
int handle ( int m );
/* Engine */
const Audio_Region *capture_region ( void ) const;

View File

@ -21,6 +21,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
unsigned long
mtime ( const char *file )
@ -86,3 +87,52 @@ release_lock ( int *lockfd, const char *filename )
*lockfd = 0;
}
int
backwards_fgetc ( FILE *fp )
{
int c;
if ( fseek( fp, -1, SEEK_CUR ) != 0 )
return -1;
c = fgetc( fp );
fseek( fp, -1, SEEK_CUR );
return c;
}
char *
backwards_fgets ( char *s, int size, FILE *fp )
{
if ( fseek( fp, -1, SEEK_CUR ) != 0 )
return NULL;
int c;
while ( ( c = backwards_fgetc( fp ) ) >= 0 )
if ( '\n' == c )
break;
long here = ftell( fp );
fseek( fp, 1, SEEK_CUR );
char *r = fgets( s, size, fp );
fseek( fp, here, SEEK_SET );
return r;
}
/** update the modification time of file referred to by /fd/ */
void
touch ( int fd )
{
struct stat st;
fstat( fd, &st );
fchmod( fd, st.st_mode );
}

View File

@ -17,9 +17,14 @@
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
#include <stdio.h>
unsigned long mtime ( const char *file );
bool newer ( const char *file1, const char *file2 );
unsigned long size ( const char *file );
int exists ( const char *name );
bool acquire_lock ( int *lockfd, const char *filename );
void release_lock ( int *lockfd, const char *filename );
int backwards_fgetc ( FILE *fp );
char * backwards_fgets ( char *s, int size, FILE *fp );
void touch ( int fd );