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) etags $(SRCS)
.deps: .config $(SRCS) .deps: .config $(SRCS)
ifneq ($(CALCULATING),yes)
@ echo -n Calculating dependencies... @ 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: clean_deps:
@ rm -f .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 ); return fl_rgb_color( 255 - r, 255 - g, 255 - b );
} }
void void
Audio_Region::get ( Log_Entry &e ) const Audio_Region::get ( Log_Entry &e ) const
@ -154,7 +155,6 @@ Audio_Region::Audio_Region ( Audio_File *c )
log_create(); log_create();
} }
/* used when DND importing */ /* used when DND importing */
Audio_Region::Audio_Region ( Audio_File *c, Sequence *t, nframes_t o ) 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(); log_create();
} }
const char * Audio_Region::~Audio_Region ( )
Audio_Region::source_name ( void ) const
{ {
return _clip->name(); log_destroy();
} }
void void
Audio_Region::menu_cb ( Fl_Widget *w, void *v ) Audio_Region::menu_cb ( Fl_Widget *w, void *v )
{ {
@ -309,123 +310,6 @@ Audio_Region::menu ( void )
return m; 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 /** 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 portion of the region covered by this draw, which may or may not
cover the fade in question. */ 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 void
Audio_Region::normalize ( void ) Audio_Region::normalize ( void )
{ {

View File

@ -111,13 +111,24 @@ private:
static void menu_cb ( Fl_Widget *w, void *v ); static void menu_cb ( Fl_Widget *w, void *v );
void menu_cb ( const Fl_Menu_ *m ); 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: protected:
virtual void get ( Log_Entry &e ) const; virtual void get ( Log_Entry &e ) const;
virtual void set ( Log_Entry &e ); virtual void set ( Log_Entry &e );
int handle ( int m );
void draw_box( void );
void draw ( void );
void resize ( void );
public: public:
LOG_CREATE_FUNC( Audio_Region );
SEQUENCE_WIDGET_CLONE_FUNC( Audio_Region );
static Fl_Boxtype _box; static Fl_Boxtype _box;
static Fl_Color _selection_color; static Fl_Color _selection_color;
Fl_Color selection_color ( void ) const { return _selection_color; } Fl_Color selection_color ( void ) const { return _selection_color; }
@ -132,37 +143,18 @@ public:
bool current ( void ) const { return this == belowmouse(); } bool current ( void ) const { return this == belowmouse(); }
public:
const char * source_name ( void ) const; 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 ( const Audio_Region & rhs );
Audio_Region ( Audio_File *c ); Audio_Region ( Audio_File *c );
Audio_Region ( Audio_File *c, Sequence *t, nframes_t o ); 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 ); 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); }
int handle ( int m );
void draw_box( void );
void draw ( void );
void resize ( void );
void normalize ( void ); void normalize ( void );
/* Engine */ /* Engine */
nframes_t read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) const; nframes_t read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) const;
nframes_t write ( nframes_t nframes ); nframes_t write ( nframes_t nframes );

View File

@ -61,7 +61,9 @@ Audio_Sequence::~Audio_Sequence ( )
Loggable::block_end(); Loggable::block_end();
} }
/** return a pointer to the current capture region for this sequence */
const Audio_Region * const Audio_Region *
Audio_Sequence::capture_region ( void ) const Audio_Sequence::capture_region ( void ) const
{ {
@ -129,7 +131,6 @@ deurlify ( char *url )
*w = NULL; *w = NULL;
} }
void void
Audio_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) 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 handle_widget_change ( nframes_t start, nframes_t length );
void draw ( void );
int handle ( int m );
public: public:
LOG_CREATE_FUNC( Audio_Sequence ); LOG_CREATE_FUNC( Audio_Sequence );
Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; }
Audio_Sequence ( Track *track ); Audio_Sequence ( Track *track );
~Audio_Sequence ( ); ~Audio_Sequence ( );
Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; }
Sequence * clone_empty ( void ) Sequence * clone_empty ( void )
{ {
@ -59,13 +60,6 @@ public:
return t; 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; const Audio_Region *capture_region ( void ) const;
nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ); 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 class Control_Sequence : public Sequence
{ {
/* not permitted */ /* not permitted */
Control_Sequence ( const Control_Sequence &rhs ); Control_Sequence ( const Control_Sequence &rhs );
Control_Sequence & operator = ( const Control_Sequence &rhs ); Control_Sequence & operator = ( const Control_Sequence &rhs );
@ -47,6 +46,7 @@ private:
void init ( void ); void init ( void );
void draw_curve ( bool flip, bool filled );
protected: protected:
@ -59,9 +59,9 @@ protected:
init(); init();
} }
private:
void draw_curve ( bool flip, bool filled ); void draw ( void );
int handle ( int m );
public: public:
@ -76,12 +76,6 @@ public:
Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; } 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 */ /* Engine */
void output ( Port *p ) { _output = p; } void output ( Port *p ) { _output = p; }
nframes_t play ( sample_t *buf, nframes_t frame, nframes_t nframes ); 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. */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/ /*******************************************************************************/
#include "../Track.H" #include "../Track.H"
// #include "Audio_Sequence.H" // #include "Audio_Sequence.H"
class Audio_Sequence; class Audio_Sequence;
@ -28,6 +27,8 @@ class Audio_Sequence;
#include "Disk_Stream.H" #include "Disk_Stream.H"
#include "dsp.h" #include "dsp.h"
/**********/ /**********/
/* Engine */ /* Engine */
/**********/ /**********/
@ -40,12 +41,6 @@ class Audio_Sequence;
that is, at startup time. The default is 5 seconds, which may or that is, at startup time. The default is 5 seconds, which may or
may not be excessive depending on various external factors. */ 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; float Disk_Stream::seconds_to_buffer = 2.0f;
/* this is really only a rough estimate. The actual amount of data /* this is really only a rough estimate. The actual amount of data
read depends on many factors. Overlapping regions, for example, will read depends on many factors. Overlapping regions, for example, will
@ -53,6 +48,8 @@ float Disk_Stream::seconds_to_buffer = 2.0f;
counts.*/ counts.*/
size_t Disk_Stream::disk_io_kbytes = 256; size_t Disk_Stream::disk_io_kbytes = 256;
Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track ) Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track )
{ {
assert( channels ); assert( channels );
@ -85,6 +82,7 @@ Disk_Stream::~Disk_Stream ( )
engine->unlock(); engine->unlock();
} }
/** flush buffers and reset. Must only be called from the RT thread. */ /** flush buffers and reset. Must only be called from the RT thread. */
void void

View File

@ -30,6 +30,8 @@
#include "util/Thread.H" #include "util/Thread.H"
Engine::Engine ( ) : _thread( "RT" ) Engine::Engine ( ) : _thread( "RT" )
{ {
_freewheeling = false; _freewheeling = false;
@ -39,6 +41,8 @@ Engine::Engine ( ) : _thread( "RT" )
_xruns = 0; _xruns = 0;
} }
/*******************/ /*******************/
/* Static Wrappers */ /* Static Wrappers */
/*******************/ /*******************/
@ -79,15 +83,24 @@ Engine::buffer_size ( nframes_t nframes, void *arg )
return ((Engine*)arg)->buffer_size( nframes ); return ((Engine*)arg)->buffer_size( nframes );
} }
void
Engine::thread_init ( void *arg )
{
((Engine*)arg)->thread_init();
}
void void
Engine::request_locate ( nframes_t frame ) Engine::shutdown ( void *arg )
{ {
if ( timeline ) ((Engine*)arg)->shutdown();
timeline->seek( frame );
} }
/*************/
/* Callbacks */
/*************/
/* THREAD: RT */ /* THREAD: RT */
/** This is the jack xrun callback */ /** This is the jack xrun callback */
int int
@ -114,7 +127,6 @@ Engine::freewheel ( bool starting )
int int
Engine::buffer_size ( nframes_t nframes ) Engine::buffer_size ( nframes_t nframes )
{ {
/* TODO: inform all disktreams the the buffer size has changed */
timeline->resize_buffers( nframes ); timeline->resize_buffers( nframes );
return 0; return 0;
@ -166,7 +178,6 @@ Engine::sync ( jack_transport_state_t state, jack_position_t *pos )
return 0; return 0;
} }
/* THREAD: RT */ /* THREAD: RT */
void void
Engine::timebase ( jack_transport_state_t, jack_nframes_t, jack_position_t *pos, int ) 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 */ /* THREAD: RT */
int int
Engine::process ( nframes_t nframes ) Engine::process ( nframes_t nframes )
@ -235,7 +245,7 @@ Engine::process ( nframes_t nframes )
return 0; return 0;
} }
/* THREAD: RT */
/** enter or leave freehweeling mode */ /** enter or leave freehweeling mode */
void void
Engine::freewheeling ( bool yes ) Engine::freewheeling ( bool yes )
@ -244,31 +254,22 @@ Engine::freewheeling ( bool yes )
WARNING( "Unkown error while setting freewheeling mode" ); WARNING( "Unkown error while setting freewheeling mode" );
} }
void /* TRHEAD: RT */
Engine::thread_init ( void *arg )
{
((Engine*)arg)->thread_init();
}
void void
Engine::thread_init ( void ) Engine::thread_init ( void )
{ {
_thread.set( "RT" ); _thread.set( "RT" );
} }
/* THREAD: RT */
void
Engine::shutdown ( void *arg )
{
((Engine*)arg)->shutdown();
}
void void
Engine::shutdown ( void ) Engine::shutdown ( void )
{ {
_zombified = true; _zombified = true;
} }
/** Connect to JACK */
int int
Engine::init ( void ) Engine::init ( void )
{ {
@ -300,3 +301,10 @@ Engine::init ( void )
/* we don't need to create any ports until tracks are created */ /* we don't need to create any ports until tracks are created */
return 1; 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 */ 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 */ int _buffers_dropped; /* buffers dropped because of locking */
nframes_t _sample_rate; nframes_t _sample_rate;
volatile int _xruns; volatile int _xruns;
volatile bool _freewheeling; volatile bool _freewheeling;
volatile bool _zombified; volatile bool _zombified;
static void shutdown ( void *arg ); static void shutdown ( void *arg );
void shutdown ( void ); void shutdown ( void );
static int process ( nframes_t nframes, void *arg ); static int process ( nframes_t nframes, void *arg );
@ -72,6 +61,8 @@ class Engine : public Mutex
Engine ( const Engine &rhs ); Engine ( const Engine &rhs );
Engine & operator = ( const Engine &rhs ); Engine & operator = ( const Engine &rhs );
void request_locate ( nframes_t frame );
private: private:
friend class Port; friend class Port;
@ -85,8 +76,6 @@ public:
int init ( void ); int init ( void );
void request_locate ( nframes_t frame );
nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); } nframes_t nframes ( void ) const { return jack_get_buffer_size( _client ); }
float frame_rate ( void ) const { return jack_get_sample_rate( _client ); } float frame_rate ( void ) const { return jack_get_sample_rate( _client ); }
nframes_t sample_rate ( void ) const { return _sample_rate; } nframes_t sample_rate ( void ) const { return _sample_rate; }

View File

@ -22,6 +22,8 @@
peakfile reading/writing. peakfile reading/writing.
*/ */
/* Code for peakfile reading, resampling, generation and streaming */
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -39,6 +41,7 @@
#include "assert.h" #include "assert.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/Thread.H" #include "util/Thread.H"
#include "util/file.h"
#include <errno.h> #include <errno.h>
@ -47,6 +50,7 @@
using std::min; using std::min;
using std::max; using std::max;
/* whether to cache peaks at multiple resolutions on disk to /* whether to cache peaks at multiple resolutions on disk to
* drastically improve performance */ * 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_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, ... */ const int Peaks::cache_step = 1; /* powers of two between each level. 4 == 256, 2048, 16384, ... */
Peaks::peakbuffer Peaks::_peakbuf; Peaks::peakbuffer Peaks::_peakbuf;
@ -72,17 +75,6 @@ peakname ( const char *filename )
return (const char*)&file; 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 ) Peaks::Peaks ( Audio_File *c )
@ -97,6 +89,8 @@ Peaks::~Peaks ( )
delete _peak_writer; delete _peak_writer;
} }
/** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be /** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be
* called before any calls to operator[] */ * called before any calls to operator[] */
int 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 ); return _peakfile.read_peaks( peaks, s, npeaks, chunksize );
} }
int int
Peaks::read_source_peaks ( Peak *peaks, int npeaks, nframes_t chunksize ) const 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 bool
Peaks::current ( void ) const Peaks::current ( void ) const
{ {
int sfd, pfd; return ! newer( _clip->name(), peakname( _clip->name() ) );
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;
} }
bool bool
Peaks::make_peaks ( void ) const Peaks::make_peaks ( void ) const
{ {
@ -817,7 +792,6 @@ Peaks::Builder::make_peaks ( void )
return true; return true;
} }
Peaks::Builder::Builder ( const Peaks *peaks ) : _peaks( peaks ) Peaks::Builder::Builder ( const Peaks *peaks ) : _peaks( peaks )
{ {
fp = NULL; fp = NULL;

View File

@ -17,6 +17,8 @@
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/ /*******************************************************************************/
/* Wrapper for a JACK audio port */
#include "Port.H" #include "Port.H"
#include <string.h> #include <string.h>
@ -25,6 +27,8 @@
#include <stdio.h> // sprintf #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 */ /* nframes is the number of frames to buffer */
@ -39,6 +43,22 @@ Port::Port ( const char *name, type_e dir )
activate( name, 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 * static const char *
name_for_port ( Port::type_e dir, const char *base, int n, const char *type ) 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; 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 void
Port::activate ( const char *name, type_e dir ) Port::activate ( const char *name, type_e dir )
{ {

View File

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

View File

@ -305,44 +305,6 @@ Loggable::do_this ( const char *s, bool reverse )
return true; 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 */ /** Reverse the last journal transaction */
void void
Loggable::undo ( void ) Loggable::undo ( void )
@ -386,6 +348,9 @@ Loggable::undo ( void )
_undo_offset = uo; _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 void
Loggable::compact_ids ( void ) Loggable::compact_ids ( void )
{ {
@ -406,9 +371,8 @@ Loggable::compact_ids ( void )
_log_id = id; _log_id = id;
} }
/* FIXME: we need a version of this that is fully const, right? */ /** write a snapshot of the current state of all loggable objects to
/** write a snapshot of the state of all loggable objects, sufficient * file handle /fp/ */
* for later reconstruction, to /fp/ */
bool bool
Loggable::snapshot ( FILE *fp ) Loggable::snapshot ( FILE *fp )
{ {
@ -437,6 +401,8 @@ Loggable::snapshot ( FILE *fp )
return true; return true;
} }
/** write a snapshot of the current state of all loggable objects to
* file /name/ */
bool bool
Loggable::snapshot ( const char *name ) Loggable::snapshot ( const char *name )
{ {
@ -575,7 +541,6 @@ Loggable::log_print( const Log_Entry *o, const Log_Entry *n ) const
log( "\n" ); log( "\n" );
} }
/** Remember current object state for later comparison. *Must* be /** Remember current object state for later comparison. *Must* be
* called before any user action that might change one of the object's * called before any user action that might change one of the object's
* journaled properties. */ * journaled properties. */

View File

@ -56,6 +56,10 @@ int Project::_lockfd = 0;
/***********/
/* Private */
/***********/
void void
Project::set_name ( const char *name ) Project::set_name ( const char *name )
{ {
@ -75,27 +79,6 @@ Project::set_name ( const char *name )
*s = ' '; *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 bool
Project::write_info ( void ) Project::write_info ( void )
{ {
@ -139,7 +122,33 @@ Project::read_info ( void )
return true; 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 bool
Project::validate ( const char *name ) Project::validate ( const char *name )
{ {
@ -169,7 +178,8 @@ Project::validate ( const char *name )
return r; 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 int
Project::open ( const char *name ) Project::open ( const char *name )
{ {
@ -207,6 +217,8 @@ Project::open ( const char *name )
return 0; return 0;
} }
/** Create a new project /name/ from existing template
* /template_name/ */
bool bool
Project::create ( const char *name, const char *template_name ) Project::create ( const char *name, const char *template_name )
{ {
@ -251,3 +263,10 @@ Project::create ( const char *name, const char *template_name )
return false; 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 _name[256];
static char _path[512]; static char _path[512];
static bool write_info ( void );
static bool read_info ( void );
static void set_name ( const char *name );
public: public:
enum enum
@ -37,10 +41,8 @@ public:
E_PERM = -3, E_PERM = -3,
}; };
static bool write_info ( void );
static bool read_info ( void );
static const char *name ( void ) { return Project::_name; } 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 close ( void );
static bool validate ( const char *name ); static bool validate ( const char *name );
static int open ( 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. */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/ /*******************************************************************************/
#include "Sequence.H" #include "Sequence.H"
#include "Timeline.H" #include "Timeline.H"
@ -25,12 +24,20 @@
#include "Track.H" #include "Track.H"
#include "FL/event_name.H"
#include "Transport.H" // for locate()
#include "../FL/Boxtypes.H" #include "../FL/Boxtypes.H"
using namespace std; using namespace std;
queue <Sequence_Widget *> Sequence::_delete_queue; queue <Sequence_Widget *> Sequence::_delete_queue;
Sequence::Sequence ( Track *track ) : Fl_Widget( 0, 0, 0, 0 ), Loggable( true ) Sequence::Sequence ( Track *track ) : Fl_Widget( 0, 0, 0, 0 ), Loggable( true )
{ {
init(); init();
@ -59,22 +66,6 @@ Sequence::init ( void )
// clear_visible_focus(); // 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 ( ) Sequence::~Sequence ( )
{ {
DMESSAGE( "destroying sequence" ); DMESSAGE( "destroying sequence" );
@ -86,12 +77,37 @@ Sequence::~Sequence ( )
FATAL( "programming error: leaf destructor must call Sequence::clear()!" ); 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 nframes_t
Sequence::x_to_offset ( int X ) Sequence::x_to_offset ( int X )
{ {
return timeline->xoffset + timeline->x_to_ts( X - x() ); return timeline->xoffset + timeline->x_to_ts( X - x() );
} }
/** sort the widgets in this sequence by position */
void void
Sequence::sort ( void ) Sequence::sort ( void )
{ {
@ -112,95 +128,12 @@ Sequence::overlaps ( Sequence_Widget *r )
return NULL; 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 void
Sequence::handle_widget_change ( nframes_t start, nframes_t length ) Sequence::handle_widget_change ( nframes_t start, nframes_t length )
{ {
// timeline->update_length( start + 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 *
Sequence::widget_at ( nframes_t ts, int Y ) Sequence::widget_at ( nframes_t ts, int Y )
{ {
@ -212,6 +145,8 @@ Sequence::widget_at ( nframes_t ts, int Y )
return NULL; 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_Widget *
Sequence::event_widget ( void ) Sequence::event_widget ( void )
{ {
@ -219,17 +154,6 @@ Sequence::event_widget ( void )
return widget_at( ets, Fl::event_y() ); 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 void
Sequence::add ( Sequence_Widget *r ) Sequence::add ( Sequence_Widget *r )
{ {
@ -254,13 +178,25 @@ Sequence::add ( Sequence_Widget *r )
handle_widget_change( r->start(), r->length() ); 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 static nframes_t
abs_diff ( nframes_t n1, nframes_t n2 ) abs_diff ( nframes_t n1, nframes_t n2 )
{ {
return n1 > n2 ? n1 - n2 : n2 - n1; return n1 > n2 ? n1 - n2 : n2 - n1;
} }
/* snap /r/ to nearest edge */ /** snap widget /r/ to nearest edge */
void void
Sequence::snap ( Sequence_Widget *r ) Sequence::snap ( Sequence_Widget *r )
{ {
@ -306,38 +242,45 @@ Sequence::snap ( Sequence_Widget *r )
r->start( f ); r->start( f );
} }
/** return the location of the next widget from frame /from/ */
nframes_t void
Sequence::next ( nframes_t from ) const 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() ) if ( ! fl_not_clipped( x(), y(), w(), h() ) )
return _widgets.back()->start(); return;
else
return 0; 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 int
Sequence::handle ( int m ) 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> #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 void
Sequence_Point::get ( Log_Entry &e ) const Sequence_Point::get ( Log_Entry &e ) const
{ {

View File

@ -33,11 +33,13 @@ protected:
void get ( Log_Entry &e ) const; void get ( Log_Entry &e ) const;
void set ( Log_Entry &e ); void set ( Log_Entry &e );
Sequence_Point ( const Sequence_Point &rhs ) : Sequence_Widget( rhs )
{ virtual void draw_box ( void );
if ( _label ) virtual void draw ( void );
_label = strdup( rhs._label );
} Sequence_Point ( const Sequence_Point &rhs );
Sequence_Point ( );
~Sequence_Point ( );
public: public:
@ -68,21 +70,4 @@ public:
nframes_t length ( void ) const { return timeline->x_to_ts( abs_w() ); } 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 "Sequence_Region.H"
#include "Track.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 void
Sequence_Region::get ( Log_Entry &e ) const Sequence_Region::get ( Log_Entry &e ) const
{ {
@ -29,7 +46,6 @@ Sequence_Region::get ( Log_Entry &e ) const
Sequence_Widget::get( e ); Sequence_Widget::get( e );
} }
void void
Sequence_Region::set ( Log_Entry &e ) Sequence_Region::set ( Log_Entry &e )
{ {
@ -49,18 +65,6 @@ Sequence_Region::set ( Log_Entry &e )
Sequence_Widget::set( 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 void
Sequence_Region::trim ( enum trim_e t, int X ) Sequence_Region::trim ( enum trim_e t, int X )
{ {
@ -232,3 +236,14 @@ Sequence_Region::handle ( int m )
return 0; 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 get ( Log_Entry &e ) const;
virtual void set ( Log_Entry &e ); virtual void set ( Log_Entry &e );
Sequence_Region ( ) Sequence_Region ( );
{ Sequence_Region ( const Sequence_Region &rhs );
color( FL_CYAN ); virtual ~Sequence_Region ( );
}
virtual ~Sequence_Region ( ) virtual int handle ( int m );
{ virtual void draw_box( void );
virtual void draw ( void );
}
Sequence_Region ( const Sequence_Region &rhs ) : Sequence_Widget( rhs )
{
}
public: public:
@ -55,8 +48,4 @@ public:
enum trim_e { NO, LEFT, RIGHT }; enum trim_e { NO, LEFT, RIGHT };
void trim ( enum trim_e t, int X ); 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 ); _selection.remove( this );
} }
void void
Sequence_Widget::get ( Log_Entry &e ) const Sequence_Widget::get ( Log_Entry &e ) const
{ {

View File

@ -230,7 +230,7 @@ if ( r < 0 )
if ( n != 2 ) if ( n != 2 )
return; return;
Loggable::compact();} Project::compact();} selected
xywh {20 20 40 25} xywh {20 20 40 25}
} }
Submenu {} { Submenu {} {
@ -868,7 +868,7 @@ while ( _window->shown() )
Function {make_window()} {open Function {make_window()} {open
} { } {
Fl_Window _window { Fl_Window _window {
label {New Project} open selected label {New Project} open
xywh {615 414 550 195} type Double modal xclass Non_DAW visible xywh {615 414 550 195} type Double modal xclass Non_DAW visible
} { } {
Fl_File_Input _name { 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 void
Tempo_Point::get ( Log_Entry &e ) const 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 int
Tempo_Point::handle ( int m ) 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 void
Time_Point::get ( Log_Entry &e ) const Time_Point::get ( Log_Entry &e ) const
{ {
@ -60,39 +93,6 @@ Time_Point::set ( Log_Entry &e )
_make_label(); _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 int
Time_Point::handle ( int m ) Time_Point::handle ( int m )
{ {
@ -113,12 +113,9 @@ Time_Point::handle ( int m )
return Sequence_Point::handle( m ); return Sequence_Point::handle( m );
} }
#include <FL/Fl_Int_Input.H> #include <FL/Fl_Int_Input.H>
#include <FL/Fl_Menu_Window.H> #include <FL/Fl_Menu_Window.H>
class Time_Point_Editor : public Fl_Menu_Window class Time_Point_Editor : public Fl_Menu_Window
{ {
@ -196,7 +193,6 @@ public:
} }
}; };
bool bool
Time_Point::edit ( time_sig *sig ) 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 ) ); vscroll->value( _yposition, h() - rulers->h() - hscroll->h(), 0, pack_visible_height( tracks ) );
} }
/** recalculate the size of horizontal scrolling area and inform scrollbar */
void void
Timeline::adjust_hscroll ( void ) Timeline::adjust_hscroll ( void )
{ {
@ -157,6 +158,7 @@ Timeline::menu_cb ( Fl_Widget *w, void *v )
((Timeline*)v)->menu_cb( (Fl_Menu_*)w ); ((Timeline*)v)->menu_cb( (Fl_Menu_*)w );
} }
/** ensure that p1 is less than p2 */
void void
Timeline::fix_range ( 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 void
Timeline::beats_per_minute ( nframes_t when, float bpm ) 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 ) ); time_track->add( new Time_Point( when, bpb, note_type ) );
} }
/************/ /************/
/* Snapping */ /* 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 /** 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 nearest measure line to *less than* /when/. Returns true if
the new value of *frame is valid, false otherwise. */ 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 nframes_t
Timeline::x_to_offset ( int x ) const Timeline::x_to_offset ( int x ) const
{ {
return x_to_ts( max( 0, x - Track::width() ) ) + xoffset; return x_to_ts( max( 0, x - Track::width() ) ) + xoffset;
} }
/** draws a single measure line */ /** draws a single measure line */
static void static void
draw_measure_cb ( nframes_t frame, const BBT &bbt, void *arg ) 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 */ /* FIXME: wrong place for this */
const float ticks_per_beat = 1920.0; const float ticks_per_beat = 1920.0;
/** re-render the unified tempomap based on the current contents of the Time and Tempo sequences */
void void
Timeline::update_tempomap ( void ) Timeline::update_tempomap ( void )
{ {
@ -664,6 +647,7 @@ Timeline::update_tempomap ( void )
_tempomap.sort( Sequence_Widget::sort_func ); _tempomap.sort( Sequence_Widget::sort_func );
} }
/** return a stucture containing the BBT info which applies at /frame/ */
position_info position_info
Timeline::solve_tempomap ( nframes_t frame ) const Timeline::solve_tempomap ( nframes_t frame ) const
{ {
@ -782,6 +766,7 @@ done:
return pos; return pos;
} }
/** maybe draw appropriate measure lines in rectangle defined by X, Y, W, and H, using color /color/ as a base */
void void
Timeline::draw_measure_lines ( int X, int Y, int W, int H, Fl_Color color ) 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 void
Timeline::draw_clip ( void * v, int X, int Y, int W, int H ) 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(); fl_pop_clip();
} }
/** handle resize event */
void void
Timeline::resize ( int X, int Y, int W, int H ) 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 ); vscroll->size( vscroll->w(), H - 18 );
} }
/** draw ancillary cursors (not necessarily in the overlay plane) */
void void
Timeline::draw_cursors ( void ) const 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 void
Timeline::draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const 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 void
Timeline::update_cb ( void *arg ) Timeline::update_cb ( void *arg )
{ {
@ -1043,6 +999,7 @@ Timeline::update_cb ( void *arg )
tl->redraw_playhead(); tl->redraw_playhead();
} }
/** draw cursors in overlay plane */
void void
Timeline::draw_overlay ( void ) Timeline::draw_overlay ( void )
{ {
@ -1075,9 +1032,7 @@ Timeline::draw_overlay ( void )
} }
// #include "Sequence_Widget.H" /** select sequence widgets within rectangle /r/ */
/** select all widgets in inside rectangle /r/ */
void void
Timeline::select ( const Rectangle &r ) Timeline::select ( const Rectangle &r )
{ {
@ -1092,19 +1047,20 @@ Timeline::select ( const Rectangle &r )
} }
} }
/** delete all selected sequence widgets */
void void
Timeline::delete_selected ( void ) Timeline::delete_selected ( void )
{ {
Sequence_Widget::delete_selected(); Sequence_Widget::delete_selected();
} }
/** clear the selection of seqeunce widgets */
void void
Timeline::select_none ( void ) Timeline::select_none ( void )
{ {
Sequence_Widget::select_none(); Sequence_Widget::select_none();
} }
/** An unfortunate necessity for implementing our own DND aside from /** An unfortunate necessity for implementing our own DND aside from
* the (bogus) native FLTK system */ * the (bogus) native FLTK system */
Track * Track *
@ -1137,19 +1093,6 @@ Timeline::handle_scroll ( int m )
return 0; 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 int
Timeline::handle ( int m ) 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 void
Timeline::zoom_in ( void ) Timeline::zoom_in ( void )
{ {
hscroll->zoom_in(); hscroll->zoom_in();
} }
/** zoom out by one zoom step */
void void
Timeline::zoom_out ( void ) Timeline::zoom_out ( void )
{ {
@ -1322,6 +1334,7 @@ Timeline::zoom ( float secs )
redraw(); redraw();
} }
/** fit the zoom to the current length of the timeline (subject to nearest power of two) */
void void
Timeline::zoom_fit ( void ) Timeline::zoom_fit ( void )
{ {
@ -1329,33 +1342,7 @@ Timeline::zoom_fit ( void )
zoom( length() / (float)sample_rate() ); zoom( length() / (float)sample_rate() );
} }
Track * /** add /track/ to the timeline */
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 );
}
void void
Timeline::add_track ( Track *track ) Timeline::add_track ( Track *track )
{ {
@ -1372,6 +1359,7 @@ Timeline::add_track ( Track *track )
} }
/** remove /track/ from the timeline */
void void
Timeline::remove_track ( Track *track ) Timeline::remove_track ( Track *track )
{ {

View File

@ -21,8 +21,6 @@
#include "Transport.H" #include "Transport.H"
/* #include "Port.H" */
#include "../FL/Fl_Sometimes_Input.H" #include "../FL/Fl_Sometimes_Input.H"
#include <FL/fl_ask.H> #include <FL/fl_ask.H>
#include <FL/Fl_Color_Chooser.H> #include <FL/Fl_Color_Chooser.H>
@ -41,76 +39,54 @@ const char *Track::capture_format = "Wav 24";
void Track::Track ( const char *L, int channels ) :
Track::cb_input_field ( Fl_Widget *, void *v ) Fl_Group ( 0, 0, 0, 0, 0 )
{ {
((Track*)v)->cb_input_field(); init();
}
void if ( L )
Track::cb_button ( Fl_Widget *w, void *v ) name( L );
{
((Track*)v)->cb_button( w ); color( (Fl_Color)rand() );
configure_inputs( channels );
configure_outputs( channels );
log_create();
} }
void Track::Track ( ) : Fl_Group( 0, 0, 1, 1 )
Track::cb_input_field ( void )
{ {
log_start(); init();
name( name_field->value() ); timeline->add_track( this );
log_end();
} }
void Track::~Track ( )
Track::cb_button ( Fl_Widget *w )
{ {
Loggable::block_start();
if ( w == record_button ) takes = NULL;
{ control = NULL;
annotation = NULL;
} Fl_Group::clear();
if ( w == mute_button )
{
} log_destroy();
if ( w == solo_button )
{
if ( solo_button->value() )
++_soloing;
else
--_soloing;
}
else
if ( w == take_menu )
{
int v = take_menu->value();
switch ( v ) timeline->remove_track( this );
{
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; /* give up our ports */
configure_inputs( 0 );
configure_outputs( 0 );
for ( int i = takes->children(); i--; ) _sequence = NULL;
{
Audio_Sequence *t = (Audio_Sequence*)takes->child( i ); if ( _name )
if ( ! strcmp( s, t->name() ) ) free( _name );
{
sequence( t ); Loggable::block_end();
redraw();
break;
}
}
}
} }
void void
@ -231,50 +207,149 @@ Track::init ( void )
} }
Track::Track ( const char *L, int channels ) : void
Fl_Group ( 0, 0, 0, 0, 0 ) Track::set ( Log_Entry &e )
{ {
init(); for ( int i = 0; i < e.size(); ++i )
{
const char *s, *v;
if ( L ) e.get( i, &s, &v );
name( L );
color( (Fl_Color)rand() ); if ( ! strcmp( s, ":height" ) )
{
size( atoi( v ) );
configure_inputs( channels ); // Fl_Widget::size( w(), height() );
configure_outputs( channels ); 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(); e.add( ":name", _name );
e.add( ":sequence", sequence() );
takes = NULL; e.add( ":selected", _selected );
control = NULL; e.add( ":height", size() );
annotation = NULL; e.add( ":inputs", input.size() );
e.add( ":outputs", output.size() );
Fl_Group::clear(); e.add( ":color", (unsigned long)color());
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();
} }
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 ) static int pack_visible( Fl_Pack *p )
{ {
int v = 0; int v = 0;
@ -342,7 +417,6 @@ Track::size ( int v )
resize(); resize();
} }
void void
Track::add ( Audio_Sequence * t ) 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> #include <FL/Fl_Menu_Button.H>
@ -601,6 +659,23 @@ Track::menu ( void ) const
#include "FL/event_name.H" #include "FL/event_name.H"
#include "FL/test_press.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 int
Track::handle ( int m ) Track::handle ( int m )
{ {

View File

@ -97,16 +97,14 @@ private:
void update_port_names ( void ); void update_port_names ( void );
const char *name_for_port( Port::type_e type, int n ); const char *name_for_port( Port::type_e type, int n );
Track ( );
Track ( ) : Fl_Group( 0, 0, 1, 1 )
{
init();
timeline->add_track( this );
}
void init ( void ); void init ( void );
protected:
void get ( Log_Entry &e ) const;
void set ( Log_Entry &e );
public: public:
Fl_Input *name_field; Fl_Input *name_field;
@ -128,76 +126,6 @@ public:
Playback_DS *playback_ds; Playback_DS *playback_ds;
Record_DS *record_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 */ /* for loggable */
LOG_CREATE_FUNC( Track ); LOG_CREATE_FUNC( Track );
@ -270,7 +198,6 @@ public:
void draw ( void ); void draw ( void );
int handle ( int m ); int handle ( int m );
/* Engine */ /* Engine */
const Audio_Region *capture_region ( void ) const; const Audio_Region *capture_region ( void ) const;

View File

@ -21,6 +21,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h>
unsigned long unsigned long
mtime ( const char *file ) mtime ( const char *file )
@ -86,3 +87,52 @@ release_lock ( int *lockfd, const char *filename )
*lockfd = 0; *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. */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/ /*******************************************************************************/
#include <stdio.h>
unsigned long mtime ( const char *file ); unsigned long mtime ( const char *file );
bool newer ( const char *file1, const char *file2 ); bool newer ( const char *file1, const char *file2 );
unsigned long size ( const char *file ); unsigned long size ( const char *file );
int exists ( const char *name ); int exists ( const char *name );
bool acquire_lock ( int *lockfd, const char *filename ); bool acquire_lock ( int *lockfd, const char *filename );
void release_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 );