diff --git a/Makefile b/Makefile index b5079ea..dd3a377 100644 --- a/Makefile +++ b/Makefile @@ -26,9 +26,11 @@ else endif CXXFLAGS += $(SNDFILE_CFLAGS) $(LASH_CFLAGS) $(FLTK_CFLAGS) -DINSTALL_PREFIX="\"$(prefix)\"" -DVERSION=\"$(VERSION)\" +INCLUDES := -Iutil include scripts/colors + .C.o: @ echo "Compiling: $(BOLD)$(YELLOW)$<$(SGR0)" @ $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ diff --git a/Timeline/Audio_Region.C b/Timeline/Audio_Region.C index 40fdfc9..2915ead 100644 --- a/Timeline/Audio_Region.C +++ b/Timeline/Audio_Region.C @@ -17,16 +17,6 @@ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************************/ -#include "Sequence.H" -#include "Audio_Region.H" -#include "Timeline.H" -#include "Waveform.H" - -#include "Audio_Sequence.H" -#include "Track.H" - -#include "dsp.h" - #include #include #include @@ -35,6 +25,16 @@ #include #include + +#include "Sequence.H" +#include "Audio_Region.H" +#include "Timeline.H" +#include "Waveform.H" +#include "Audio_Sequence.H" +#include "Track.H" + +#include "Engine/Audio_File.H" + #include // using std::algorithm; using namespace std; @@ -185,6 +185,12 @@ Audio_Region::Audio_Region ( Audio_File *c, Sequence *t, nframes_t o ) log_create(); } +const char * +Audio_Region::source_name ( void ) const +{ + return _clip->name(); +} + int Audio_Region::handle ( int m ) @@ -671,214 +677,3 @@ Audio_Region::normalize ( void ) peaks ) _scale = pbuf->normalization_factor(); } - - - - -/**********/ -/* Engine */ -/**********/ - - -/** Apply a (portion of) fade from /start/ to /end/ assuming a - * buffer size of /nframes/. /start/ and /end/ are relative to the - * given buffer, and /start/ may be negative. */ -void -Audio_Region::Fade::apply ( sample_t *buf, Audio_Region::Fade::fade_dir_e dir, long start, nframes_t end, nframes_t nframes ) const -{ -// printf( "apply fade %s: start=%ld end=%lu\n", dir == Fade::Out ? "out" : "in", start, end ); - - if ( ! nframes ) - return; - - const nframes_t i = start > 0 ? start : 0; - const nframes_t e = end > nframes ? nframes : end; - - assert( i < nframes ); - - const float inc = increment(); - float fi = ( i - start ) / (float)length; - -// buf += i; - buf = &buf[ i ]; - - nframes_t n = e - i; - - assert( i + n <= nframes ); - - if ( dir == Fade::Out ) - { - fi = 1.0f - fi; - for ( ; n--; fi -= inc ) - *(buf++) *= gain( fi ); - } - else - for ( ; n--; fi += inc ) - *(buf++) *= gain( fi ); -} - -/* THREAD: IO */ -/** read the overlapping part of /channel/ at /pos/ for /nframes/ of - this region into /buf/, where /pos/ is in timeline frames */ -/* this runs in the diskstream thread. */ -/* FIXME: it is far more efficient to read all the channels from a - multichannel source at once... But how should we handle the case of a - mismatch between the number of channels in this region's source and - the number of channels on the track/buffer this data is being read - for? Would it not be better to simply buffer and deinterlace the - frames in the Audio_File class instead, so that sequential requests - for different channels at the same position avoid hitting the disk - again? */ -nframes_t -Audio_Region::read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) const -{ - const Range r = _range; - - /* do nothing if we aren't covered by this frame range */ - if ( pos > r.start + r.length || pos + nframes < r.start ) - return 0; - - /* calculate offsets into file and sample buffer */ - - nframes_t sofs, ofs, cnt; - - cnt = nframes; - - if ( pos < r.start ) - { - sofs = 0; - ofs = r.start - pos; - cnt -= ofs; - } - else - { - ofs = 0; - sofs = pos - r.start; - } - - if ( ofs >= nframes ) - return 0; - -// const nframes_t start = ofs + r.start + sofs; - const nframes_t start = r.offset + sofs; - const nframes_t len = min( cnt, nframes - ofs ); - const nframes_t end = start + len; - - if ( len == 0 ) - return 0; - - /* now that we know how much and where to read, get on with it */ - - // printf( "reading region ofs = %lu, sofs = %lu, %lu-%lu\n", ofs, sofs, start, end ); - - cnt = _clip->read( buf + ofs, channel, start, end ); - - /* apply gain */ - - buffer_apply_gain( buf + ofs, cnt, _scale ); - - /* perform declicking if necessary */ - - /* FIXME: keep the declick defults someplace else */ - Fade declick; - - declick.length = 256; - declick.type = Fade::Linear; - - { - Fade fade; - - fade = declick < _fade_in ? _fade_in : declick; - - /* do fade in if necessary */ - if ( sofs < fade.length ) - { - const long d = 0 - sofs; - - assert( cnt <= nframes ); - - fade.apply( buf + ofs, Fade::In, d, d + fade.length, cnt ); - } - - fade = declick < _fade_out ? _fade_out : declick; - - /* do fade out if necessary */ -// if ( start + cnt + fade.length > r.end ) - if ( start + fade.length > ( r.offset + r.length ) ) - { - const nframes_t d = ( r.offset + r.length ) - start; - - assert( cnt <= nframes ); - - fade.apply( buf, Fade::Out, cnt + (long)d - fade.length, cnt + d, cnt ); - } - } -// printf( "read %lu frames\n", cnt ); - - return cnt; -} - - -/** prepare for capturing */ -void -Audio_Region::prepare ( void ) -{ - log_start(); -} - -/* THREAD: IO */ -/** write /nframes/ from /buf/ to source. /buf/ is interleaved and - must match the channel layout of the write source! */ -nframes_t -Audio_Region::write ( nframes_t nframes ) -{ - _range.length += nframes; - - /* FIXME: too much? */ -// _track->damage( FL_DAMAGE_EXPOSE, x() + w(), y(), 10/* FIXME: guess */, h() ); - - if ( 0 == ( timeline->ts_to_x( _range.length ) % 20 ) ) - { - nframes_t oldl = _clip->length(); - - /* get the new size. Remember, this is a read-only handle on the source--not the same - one being written to */ - _clip->close(); - _clip->open(); - - int W = timeline->ts_to_x( _clip->length() - oldl ); - - /* why - 1? */ - - if ( W ) - { - ++W; - Fl::lock(); - sequence()->damage( FL_DAMAGE_ALL, x() + w() - W, y(), W, h() ); - Fl::awake(); - Fl::unlock(); - } - } - - return nframes; -} - -/* THREAD: IO */ -/** finalize region capture. Assumes that this *is* a captured region - and that no other regions refer to the same source */ -bool -Audio_Region::finalize ( nframes_t frame ) -{ - _range.length = frame - _range.start; - - log_end(); - - _clip->close(); - _clip->open(); - - /* FIXME: should we attempt to truncate the file? */ - - redraw(); - - return true; -} diff --git a/Timeline/Audio_Region.H b/Timeline/Audio_Region.H index 7befe17..1228a5d 100644 --- a/Timeline/Audio_Region.H +++ b/Timeline/Audio_Region.H @@ -19,15 +19,10 @@ #pragma once -#include "Audio_File.H" #include "Timeline.H" - -/* Audio_Regions are "virtual" FLTK widgets; this is necessary because the - * dimensions of real FLTK widgets are limited to 16-bits, which is - * far too little for our purposes */ - #include "Sequence_Region.H" +class Audio_File; class Peaks_Redraw_Request; class Audio_Region : public Sequence_Region @@ -131,7 +126,7 @@ public: public: - const char *source_name ( void ) const { return _clip->name(); } + const char * source_name ( void ) const; LOG_CREATE_FUNC( Audio_Region ); diff --git a/Timeline/Audio_Sequence.C b/Timeline/Audio_Sequence.C index 7b9a7e5..b9b1cb4 100644 --- a/Timeline/Audio_Sequence.C +++ b/Timeline/Audio_Sequence.C @@ -20,12 +20,12 @@ #include "Audio_Sequence.H" #include "Waveform.H" -#include "dsp.h" - #include #include "Track.H" +#include "Engine/Audio_File.H" // for ::from_file() + Audio_Sequence::Audio_Sequence ( Track *track ) : Sequence( track ) { @@ -250,52 +250,3 @@ Audio_Sequence::handle ( int m ) return Sequence::handle( m ); } } - - -/**********/ -/* Engine */ -/**********/ - -/* THREAD: IO */ -/** determine region coverage and fill /buf/ with interleaved samples - * from /frame/ to /nframes/ for exactly /channels/ channels. */ -nframes_t -Audio_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ) -{ - sample_t *cbuf = new sample_t[ nframes ]; - - memset( cbuf, 0, nframes * sizeof( sample_t ) ); - - /* quick and dirty--let the regions figure out coverage for themselves */ - for ( list ::const_iterator i = _widgets.begin(); - i != _widgets.end(); ++i ) - { - const Audio_Region *r = (Audio_Region*)(*i); - - for ( int i = channels; i--; ) - { - int nfr; - - if ( ! ( nfr = r->read( cbuf, frame, nframes, i ) ) ) - /* error ? */ - continue; - - if ( channels == 1 ) - buffer_mix( buf, cbuf, nframes ); - else - buffer_interleave_one_channel_and_mix( buf, cbuf, i, channels, nframes ); - } - } - - delete[] cbuf; - - /* FIXME: bogus */ - return nframes; -} - -/* /\* THREAD: RT *\/ */ -/* nframes_t */ -/* Audio_Sequence::process ( nframes_t nframes ) */ -/* { */ -/* return disktream->process( nframes ); */ -/* } */ diff --git a/Timeline/Control_Sequence.C b/Timeline/Control_Sequence.C index 5396dd8..0110804 100644 --- a/Timeline/Control_Sequence.C +++ b/Timeline/Control_Sequence.C @@ -21,7 +21,7 @@ #include "Control_Sequence.H" #include "Track.H" - +#include "Engine/Port.H" #include "Transport.H" // for transport->frame @@ -38,7 +38,7 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) if ( track ) track->add( this ); -// output.activate( track->name(), + _output = new Port( Port::Output, track->name(), track->ncontrols(), "cv" ); log_create(); } @@ -47,6 +47,8 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 ) Control_Sequence::~Control_Sequence ( ) { log_destroy(); + + delete _output; } void @@ -83,6 +85,8 @@ Control_Sequence::set ( Log_Entry &e ) assert( t ); + _output = new Port( Port::Output, t->name(), t->ncontrols(), "cv" ); + t->add( this ); } else if ( ! strcmp( ":name", s ) ) diff --git a/Timeline/Control_Sequence.H b/Timeline/Control_Sequence.H index 54e1e50..789a8af 100644 --- a/Timeline/Control_Sequence.H +++ b/Timeline/Control_Sequence.H @@ -21,7 +21,9 @@ #include "Sequence.H" #include "Control_Point.H" -#include "Port.H" + + +#include "Engine/Port.H" class Control_Sequence : public Sequence { diff --git a/Timeline/Audio_File.C b/Timeline/Engine/Audio_File.C similarity index 99% rename from Timeline/Audio_File.C rename to Timeline/Engine/Audio_File.C index 17df1a7..d384e09 100644 --- a/Timeline/Audio_File.C +++ b/Timeline/Engine/Audio_File.C @@ -21,7 +21,7 @@ #include "Audio_File_SF.H" #include "Audio_File_Dummy.H" -#include "debug.h" +#include "util/debug.h" std::map Audio_File::_open_files; diff --git a/Timeline/Audio_File.H b/Timeline/Engine/Audio_File.H similarity index 99% rename from Timeline/Audio_File.H rename to Timeline/Engine/Audio_File.H index 0784ecc..aea0d80 100644 --- a/Timeline/Audio_File.H +++ b/Timeline/Engine/Audio_File.H @@ -20,16 +20,15 @@ #pragma once /* Base class for all audio file library interfaces */ + #include - -#include "types.h" - -#include "Peaks.H" #include #include #include -#include "Mutex.H" +#include "types.h" +#include "util/Mutex.H" +#include "Peaks.H" class Peak_Writer; diff --git a/Timeline/Audio_File_Dummy.H b/Timeline/Engine/Audio_File_Dummy.H similarity index 100% rename from Timeline/Audio_File_Dummy.H rename to Timeline/Engine/Audio_File_Dummy.H diff --git a/Timeline/Audio_File_SF.C b/Timeline/Engine/Audio_File_SF.C similarity index 99% rename from Timeline/Audio_File_SF.C rename to Timeline/Engine/Audio_File_SF.C index c9effe5..e32693d 100644 --- a/Timeline/Audio_File_SF.C +++ b/Timeline/Engine/Audio_File_SF.C @@ -31,7 +31,7 @@ // #define HAS_SF_FORMAT_VORBIS -#include "debug.h" +#include "util/debug.h" const Audio_File::format_desc Audio_File_SF::supported_formats[] = { diff --git a/Timeline/Audio_File_SF.H b/Timeline/Engine/Audio_File_SF.H similarity index 100% rename from Timeline/Audio_File_SF.H rename to Timeline/Engine/Audio_File_SF.H diff --git a/Timeline/Engine/Audio_Region.C b/Timeline/Engine/Audio_Region.C new file mode 100644 index 0000000..614c7ad --- /dev/null +++ b/Timeline/Engine/Audio_Region.C @@ -0,0 +1,230 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +/**********/ +/* Engine */ +/**********/ + +#include "../Audio_Region.H" + +#include "Audio_File.H" +#include "dsp.h" + +/** Apply a (portion of) fade from /start/ to /end/ assuming a + * buffer size of /nframes/. /start/ and /end/ are relative to the + * given buffer, and /start/ may be negative. */ +void +Audio_Region::Fade::apply ( sample_t *buf, Audio_Region::Fade::fade_dir_e dir, long start, nframes_t end, nframes_t nframes ) const +{ +// printf( "apply fade %s: start=%ld end=%lu\n", dir == Fade::Out ? "out" : "in", start, end ); + + if ( ! nframes ) + return; + + const nframes_t i = start > 0 ? start : 0; + const nframes_t e = end > nframes ? nframes : end; + + assert( i < nframes ); + + const float inc = increment(); + float fi = ( i - start ) / (float)length; + +// buf += i; + buf = &buf[ i ]; + + nframes_t n = e - i; + + assert( i + n <= nframes ); + + if ( dir == Fade::Out ) + { + fi = 1.0f - fi; + for ( ; n--; fi -= inc ) + *(buf++) *= gain( fi ); + } + else + for ( ; n--; fi += inc ) + *(buf++) *= gain( fi ); +} + +/* THREAD: IO */ +/** read the overlapping part of /channel/ at /pos/ for /nframes/ of + this region into /buf/, where /pos/ is in timeline frames */ +/* this runs in the diskstream thread. */ +/* FIXME: it is far more efficient to read all the channels from a + multichannel source at once... But how should we handle the case of a + mismatch between the number of channels in this region's source and + the number of channels on the track/buffer this data is being read + for? Would it not be better to simply buffer and deinterlace the + frames in the Audio_File class instead, so that sequential requests + for different channels at the same position avoid hitting the disk + again? */ +nframes_t +Audio_Region::read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) const +{ + const Range r = _range; + + /* do nothing if we aren't covered by this frame range */ + if ( pos > r.start + r.length || pos + nframes < r.start ) + return 0; + + /* calculate offsets into file and sample buffer */ + + nframes_t sofs, ofs, cnt; + + cnt = nframes; + + if ( pos < r.start ) + { + sofs = 0; + ofs = r.start - pos; + cnt -= ofs; + } + else + { + ofs = 0; + sofs = pos - r.start; + } + + if ( ofs >= nframes ) + return 0; + +// const nframes_t start = ofs + r.start + sofs; + const nframes_t start = r.offset + sofs; + const nframes_t len = min( cnt, nframes - ofs ); + const nframes_t end = start + len; + + if ( len == 0 ) + return 0; + + /* now that we know how much and where to read, get on with it */ + + // printf( "reading region ofs = %lu, sofs = %lu, %lu-%lu\n", ofs, sofs, start, end ); + + cnt = _clip->read( buf + ofs, channel, start, end ); + + /* apply gain */ + + buffer_apply_gain( buf + ofs, cnt, _scale ); + + /* perform declicking if necessary */ + + /* FIXME: keep the declick defults someplace else */ + Fade declick; + + declick.length = 256; + declick.type = Fade::Linear; + + { + Fade fade; + + fade = declick < _fade_in ? _fade_in : declick; + + /* do fade in if necessary */ + if ( sofs < fade.length ) + { + const long d = 0 - sofs; + + assert( cnt <= nframes ); + + fade.apply( buf + ofs, Fade::In, d, d + fade.length, cnt ); + } + + fade = declick < _fade_out ? _fade_out : declick; + + /* do fade out if necessary */ +// if ( start + cnt + fade.length > r.end ) + if ( start + fade.length > ( r.offset + r.length ) ) + { + const nframes_t d = ( r.offset + r.length ) - start; + + assert( cnt <= nframes ); + + fade.apply( buf, Fade::Out, cnt + (long)d - fade.length, cnt + d, cnt ); + } + } +// printf( "read %lu frames\n", cnt ); + + return cnt; +} + + +/** prepare for capturing */ +void +Audio_Region::prepare ( void ) +{ + log_start(); +} + +/* THREAD: IO */ +/** write /nframes/ from /buf/ to source. /buf/ is interleaved and + must match the channel layout of the write source! */ +nframes_t +Audio_Region::write ( nframes_t nframes ) +{ + _range.length += nframes; + + /* FIXME: too much? */ +// _track->damage( FL_DAMAGE_EXPOSE, x() + w(), y(), 10/* FIXME: guess */, h() ); + + if ( 0 == ( timeline->ts_to_x( _range.length ) % 20 ) ) + { + nframes_t oldl = _clip->length(); + + /* get the new size. Remember, this is a read-only handle on the source--not the same + one being written to */ + _clip->close(); + _clip->open(); + + int W = timeline->ts_to_x( _clip->length() - oldl ); + + /* why - 1? */ + + if ( W ) + { + ++W; + Fl::lock(); + sequence()->damage( FL_DAMAGE_ALL, x() + w() - W, y(), W, h() ); + Fl::awake(); + Fl::unlock(); + } + } + + return nframes; +} + +/* THREAD: IO */ +/** finalize region capture. Assumes that this *is* a captured region + and that no other regions refer to the same source */ +bool +Audio_Region::finalize ( nframes_t frame ) +{ + _range.length = frame - _range.start; + + log_end(); + + _clip->close(); + _clip->open(); + + /* FIXME: should we attempt to truncate the file? */ + + redraw(); + + return true; +} diff --git a/Timeline/Engine/Audio_Sequence.C b/Timeline/Engine/Audio_Sequence.C new file mode 100644 index 0000000..2185429 --- /dev/null +++ b/Timeline/Engine/Audio_Sequence.C @@ -0,0 +1,70 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include "../Audio_Sequence.H" + +#include "dsp.h" + +/**********/ +/* Engine */ +/**********/ + +/* THREAD: IO */ +/** determine region coverage and fill /buf/ with interleaved samples + * from /frame/ to /nframes/ for exactly /channels/ channels. */ +nframes_t +Audio_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ) +{ + sample_t *cbuf = new sample_t[ nframes ]; + + memset( cbuf, 0, nframes * sizeof( sample_t ) ); + + /* quick and dirty--let the regions figure out coverage for themselves */ + for ( list ::const_iterator i = _widgets.begin(); + i != _widgets.end(); ++i ) + { + const Audio_Region *r = (Audio_Region*)(*i); + + for ( int i = channels; i--; ) + { + int nfr; + + if ( ! ( nfr = r->read( cbuf, frame, nframes, i ) ) ) + /* error ? */ + continue; + + if ( channels == 1 ) + buffer_mix( buf, cbuf, nframes ); + else + buffer_interleave_one_channel_and_mix( buf, cbuf, i, channels, nframes ); + } + } + + delete[] cbuf; + + /* FIXME: bogus */ + return nframes; +} + +/* /\* THREAD: RT *\/ */ +/* nframes_t */ +/* Audio_Sequence::process ( nframes_t nframes ) */ +/* { */ +/* return disktream->process( nframes ); */ +/* } */ diff --git a/Timeline/Disk_Stream.C b/Timeline/Engine/Disk_Stream.C similarity index 98% rename from Timeline/Disk_Stream.C rename to Timeline/Engine/Disk_Stream.C index b2611f4..64d10c3 100644 --- a/Timeline/Disk_Stream.C +++ b/Timeline/Engine/Disk_Stream.C @@ -17,12 +17,15 @@ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************************/ -#include "Disk_Stream.H" -#include "Track.H" -#include "Audio_Sequence.H" -#include "Port.H" + +#include "../Track.H" +// #include "Audio_Sequence.H" +class Audio_Sequence; + +// #include "Port.H" #include "Engine.H" // for locking. +#include "Disk_Stream.H" #include "dsp.h" /**********/ diff --git a/Timeline/Disk_Stream.H b/Timeline/Engine/Disk_Stream.H similarity index 99% rename from Timeline/Disk_Stream.H rename to Timeline/Engine/Disk_Stream.H index 871a06c..55d2583 100644 --- a/Timeline/Disk_Stream.H +++ b/Timeline/Engine/Disk_Stream.H @@ -27,7 +27,7 @@ #include -#include "Mutex.H" +#include "util/Mutex.H" #include using std::vector; diff --git a/Timeline/Engine.C b/Timeline/Engine/Engine.C similarity index 97% rename from Timeline/Engine.C rename to Timeline/Engine/Engine.C index 2d8f582..67a6369 100644 --- a/Timeline/Engine.C +++ b/Timeline/Engine/Engine.C @@ -18,10 +18,10 @@ /*******************************************************************************/ #include "Engine.H" -#include "Transport.H" +#include "../Transport.H" -#include "Timeline.H" // for process() -#include "Sequence_Widget.H" // for BBT and position info. +#include "../Timeline.H" // for process() +#include "../Sequence_Widget.H" // for BBT and position info. #define APP_NAME "Non-DAW" // FIXME: wrong place for this! @@ -260,6 +260,8 @@ Engine::init ( void ) _sample_rate = frame_rate(); + timeline->_sample_rate = frame_rate(); + /* we don't need to create any ports until tracks are created */ return 1; } diff --git a/Timeline/Engine.H b/Timeline/Engine/Engine.H similarity index 99% rename from Timeline/Engine.H rename to Timeline/Engine/Engine.H index d21e36a..736cbc4 100644 --- a/Timeline/Engine.H +++ b/Timeline/Engine/Engine.H @@ -19,7 +19,7 @@ #pragma once -#include "Mutex.H" +#include "util/Mutex.H" #include diff --git a/Timeline/Engine/Peak.H b/Timeline/Engine/Peak.H new file mode 100644 index 0000000..fd3ac15 --- /dev/null +++ b/Timeline/Engine/Peak.H @@ -0,0 +1,27 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#pragma once + +struct Peak { + float min; + float max; + + float normalization_factor ( void ) const; +}; diff --git a/Timeline/Peaks.C b/Timeline/Engine/Peaks.C similarity index 99% rename from Timeline/Peaks.C rename to Timeline/Engine/Peaks.C index eaba682..f1c679b 100644 --- a/Timeline/Peaks.C +++ b/Timeline/Engine/Peaks.C @@ -22,9 +22,6 @@ peakfile reading/writing. */ - -#include "Peaks.H" - #include #include #include @@ -34,15 +31,15 @@ #include #include +#include "../Transport.H" // for .recording + #include "Audio_File.H" +#include "Peaks.H" #include "assert.h" - -#include "debug.h" +#include "util/debug.h" #include -#include "Transport.H" // for .recording - #include #include using std::min; diff --git a/Timeline/Peaks.H b/Timeline/Engine/Peaks.H similarity index 97% rename from Timeline/Peaks.H rename to Timeline/Engine/Peaks.H index 1f9533a..423a310 100644 --- a/Timeline/Peaks.H +++ b/Timeline/Engine/Peaks.H @@ -23,12 +23,7 @@ #include "types.h" -struct Peak { - float min; - float max; - - float normalization_factor ( void ) const; -}; +#include "Peak.H" #include diff --git a/Timeline/Playback_DS.C b/Timeline/Engine/Playback_DS.C similarity index 98% rename from Timeline/Playback_DS.C rename to Timeline/Engine/Playback_DS.C index 863b998..9ab8559 100644 --- a/Timeline/Playback_DS.C +++ b/Timeline/Engine/Playback_DS.C @@ -21,17 +21,16 @@ /* Handles streaming regions from disk to track outputs. */ /* FIXME: we shouldn't depend on these */ -#include "Timeline.H" -#include "Engine.H" -#include "Audio_Sequence.H" -#include "Track.H" +#include "../Timeline.H" // for locking +#include "../Audio_Sequence.H" +#include "../Track.H" + #include "Port.H" #include "Playback_DS.H" - - +#include "Engine.H" #include "dsp.h" -#include "debug.h" +#include "util/debug.h" bool Playback_DS::seek_pending ( void ) diff --git a/Timeline/Playback_DS.H b/Timeline/Engine/Playback_DS.H similarity index 100% rename from Timeline/Playback_DS.H rename to Timeline/Engine/Playback_DS.H diff --git a/Timeline/Port.C b/Timeline/Engine/Port.C similarity index 100% rename from Timeline/Port.C rename to Timeline/Engine/Port.C diff --git a/Timeline/Port.H b/Timeline/Engine/Port.H similarity index 100% rename from Timeline/Port.H rename to Timeline/Engine/Port.H diff --git a/Timeline/Record_DS.C b/Timeline/Engine/Record_DS.C similarity index 98% rename from Timeline/Record_DS.C rename to Timeline/Engine/Record_DS.C index f65dd3e..57b83a1 100644 --- a/Timeline/Record_DS.C +++ b/Timeline/Engine/Record_DS.C @@ -20,16 +20,16 @@ /* Handles streaming from track inputs to disk */ /* FIXME: we shouldn't depend on these */ -#include "Timeline.H" -#include "Engine.H" -#include "Audio_Sequence.H" -#include "Track.H" +#include "../Timeline.H" // for locking +#include "../Audio_Sequence.H" +#include "../Track.H" + #include "Port.H" #include "Record_DS.H" - +#include "Engine.H" #include "dsp.h" -#include "debug.h" +#include "util/debug.h" /* THREAD: IO */ /** write /nframes/ from buf to the capture file of the attached track */ diff --git a/Timeline/Record_DS.H b/Timeline/Engine/Record_DS.H similarity index 100% rename from Timeline/Record_DS.H rename to Timeline/Engine/Record_DS.H diff --git a/Timeline/Engine/Timeline.C b/Timeline/Engine/Timeline.C new file mode 100644 index 0000000..96d8e40 --- /dev/null +++ b/Timeline/Engine/Timeline.C @@ -0,0 +1,222 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include "../Timeline.H" + +#include "../Transport.H" // for .rolling +#include "../Track.H" + +#include "Record_DS.H" +#include "Playback_DS.H" + +/** Initiate recording for all armed tracks */ +bool +Timeline::record ( void ) +{ + /* FIXME: right place for this? */ + transport->recording = true; + + Loggable::block_start(); + + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + if ( t->armed() && t->record_ds ) + t->record_ds->start( transport->frame ); + } + + deactivate(); + + return true; +} + +/** stop recording for all armed tracks */ +void +Timeline::stop ( void ) +{ + nframes_t frame = transport->frame; + + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + if ( t->armed() && t->record_ds ) + t->record_ds->stop( frame ); + } + + Loggable::block_end(); + + activate(); + + transport->recording = false; +} + + +/**********/ +/* Engine */ +/**********/ + +/** call process() on each track header */ +nframes_t +Timeline::process ( nframes_t nframes ) +{ + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + t->process( nframes ); + } + + /* FIXME: BOGUS */ + return nframes; +} + +/* THREAD: RT */ +void +Timeline::seek ( nframes_t frame ) +{ + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + t->seek( frame ); + } +} + +/* THREAD: RT (non-RT) */ +void +Timeline::resize_buffers ( nframes_t nframes ) +{ + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + t->resize_buffers( nframes ); + } +} + +/* THREAD: RT */ +int +Timeline::seek_pending ( void ) +{ + int r = 0; + + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + if ( t->playback_ds ) + r += t->playback_ds->buffer_percent() < 50; + } + + return r; +} + + +/* FIXME: shouldn't these belong to the engine? */ +int +Timeline::total_input_buffer_percent ( void ) +{ + int r = 0; + + int cnt = 0; + + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + if ( t->record_ds ) + { + ++cnt; + r += t->record_ds->buffer_percent(); + } + } + + if ( ! cnt ) + return 0; + + return r / cnt; +} + +int +Timeline::total_output_buffer_percent ( void ) +{ + + int r = 0; + + int cnt = 0; + + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + if ( t->playback_ds ) + { + ++cnt; + r += t->playback_ds->buffer_percent(); + } + } + + if ( ! cnt ) + return 0; + + return r / cnt; +} + +/** wait for I/O threads to fill their buffers */ +void +Timeline::wait_for_buffers ( void ) +{ + while ( total_output_buffer_percent() + total_input_buffer_percent() < 200 ) + usleep( 5000 ); +} + + +int +Timeline::total_playback_xruns ( void ) +{ + int r = 0; + + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + if ( t->playback_ds ) + r += t->playback_ds->xruns(); + } + + return r; +} + +int +Timeline::total_capture_xruns ( void ) +{ + int r = 0; + + for ( int i = tracks->children(); i-- ; ) + { + Track *t = (Track*)tracks->child( i ); + + if ( t->record_ds ) + r += t->record_ds->xruns(); + } + + return r; +} diff --git a/Timeline/Engine/Track.C b/Timeline/Engine/Track.C new file mode 100644 index 0000000..ca046fe --- /dev/null +++ b/Timeline/Engine/Track.C @@ -0,0 +1,265 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include "../Track.H" +#include "../Transport.H" // for rolling +#include "../Control_Sequence.H" + +#include "Playback_DS.H" +#include "Record_DS.H" +#include "Engine.H" + +/**********/ +/* Engine */ +/**********/ + +void +Track::update_port_names ( void ) +{ + for ( unsigned int i = 0; i < output.size(); ++i ) + output[ i ].name( name(), i ); + + for ( unsigned int i = 0; i < input.size(); ++i ) + input[ i ].name( name(), i ); + + for ( unsigned int i = 0; i < control_out.size(); ++i ) + control_out[ i ]->name( name(), i, "cv" ); + + +/* /\* tell any attached control sequences to do the same *\/ */ +/* for ( int i = control->children(); i-- ) */ +/* ((Control_Sequence*)control->child( i ))->update_port_names(); */ + +} + +bool +Track::configure_outputs ( int n ) +{ + int on = output.size(); + + if ( n == on ) + return true; + +// engine->lock(); + + if ( playback_ds ) + { + Playback_DS *ds = playback_ds; + playback_ds = NULL; + + ds->shutdown(); + delete ds; + } + + if ( n > on ) + { + for ( int i = on; i < n; ++i ) + { + Port p( Port::Output, name(), i ); + + if ( p.valid() ) + output.push_back( p ); + else + WARNING( "could not create output port!" ); + } + } + else + { + for ( int i = on; i > n; --i ) + { + output.back().shutdown(); + output.pop_back(); + } + } + + if ( output.size() ) + playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), output.size() ); + +// engine->unlock(); + /* FIXME: bogus */ + return true; +} + +bool +Track::configure_inputs ( int n ) +{ + int on = input.size(); + + if ( n == on ) + return true; + +// engine->lock(); + + if ( record_ds ) + { + Record_DS *ds = record_ds; + record_ds = NULL; + + ds->shutdown(); + delete ds; + } + + if ( n > on ) + { + for ( int i = on; i < n; ++i ) + { + Port p( Port::Input, name(), i ); + + if ( p.valid() ) + input.push_back( p ); + else + WARNING( "could not create input port!" ); + } + } + else + { + for ( int i = on; i > n; --i ) + { + input.back().shutdown(); + input.pop_back(); + } + } + + if ( input.size() ) + record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), input.size() ); + +// engine->unlock(); + + /* FIXME: bogus */ + return true; +} + +/* THREAD: RT */ +nframes_t +Track::process ( nframes_t nframes ) +{ + if ( ! transport->rolling ) + { + for ( int i = output.size(); i--; ) + output[ i ].silence( nframes ); + + for ( int i = input.size(); i--; ) + input[ i ].silence( nframes ); + + /* FIXME: is this really the right thing to do for control ports? */ + for ( int i = control_out.size(); i--; ) + control_out[ i ]->silence( nframes ); + + return 0; + } + + for ( int i = control->children(); i--; ) + ((Control_Sequence*)control->child( i ))->process( nframes ); + + if ( playback_ds ) + { + record_ds->process( nframes ); + return playback_ds->process( nframes ); + } + else + return 0; +} + +/* THREAD: RT */ +void +Track::seek ( nframes_t frame ) +{ + if ( playback_ds ) + return playback_ds->seek( frame ); +} + +/* THREAD: RT (non-RT) */ +void +Track::resize_buffers ( nframes_t nframes ) +{ + if ( record_ds ) + record_ds->resize_buffers( nframes ); + if ( playback_ds ) + playback_ds->resize_buffers( nframes ); +} + +/* #include "Audio_Region.H" */ + + +#include + +/** very cheap UUID generator... */ +unsigned long long +uuid ( void ) +{ + time_t t = time( NULL ); + + return (unsigned long long) t; +} + + +/* THREAD: IO */ +/** create capture region and prepare to record */ +void +Track::record ( nframes_t frame ) +{ + assert( ! _capture ); + assert( ! _capture_af ); + + char pat[256]; + + snprintf( pat, sizeof( pat ), "%s-%llu", name(), uuid() ); + + + _capture_af = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format ); + + if ( ! _capture_af ) + { + /* ERROR */ + + } + + /* open it again for reading in the GUI thread */ + Audio_File *af = Audio_File::from_file( _capture_af->name() ); + + _capture = new Audio_Region( af, sequence(), frame ); + + _capture->prepare(); +} + +/* THREAD: IO */ +/** write a block to the (already opened) capture file */ +void +Track::write ( sample_t *buf, nframes_t nframes ) +{ + nframes_t l = _capture_af->write( buf, nframes ); + + _capture->write( l ); +} + +#include + +/* THREAD: IO */ +void +Track::stop ( nframes_t frame ) +{ + _capture->finalize( frame ); + + _capture = NULL; + + _capture_af->finalize(); + + delete _capture_af; + _capture_af = NULL; +} diff --git a/Timeline/dsp.C b/Timeline/Engine/dsp.C similarity index 100% rename from Timeline/dsp.C rename to Timeline/Engine/dsp.C diff --git a/Timeline/dsp.h b/Timeline/Engine/dsp.h similarity index 100% rename from Timeline/dsp.h rename to Timeline/Engine/dsp.h diff --git a/Timeline/Engine/types.h b/Timeline/Engine/types.h new file mode 100644 index 0000000..cd3cc2c --- /dev/null +++ b/Timeline/Engine/types.h @@ -0,0 +1,25 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#pragma once + +#include + +typedef jack_nframes_t nframes_t; +typedef float sample_t; diff --git a/Timeline/LASH.C b/Timeline/LASH.C index 2e007d1..0ece855 100644 --- a/Timeline/LASH.C +++ b/Timeline/LASH.C @@ -38,7 +38,7 @@ extern TLE *tle; -#include "debug.h" +#include "util/debug.h" const float lash_poll_interval = 0.2f; diff --git a/Timeline/LASH_Client.C b/Timeline/LASH_Client.C index 775bfab..8c36bb6 100644 --- a/Timeline/LASH_Client.C +++ b/Timeline/LASH_Client.C @@ -20,7 +20,7 @@ #include "LASH_Client.H" -#include "debug.h" +#include "util/debug.h" LASH_Client::LASH_Client ( ) { diff --git a/Timeline/Loggable.H b/Timeline/Loggable.H index 9e6b7af..6536c79 100644 --- a/Timeline/Loggable.H +++ b/Timeline/Loggable.H @@ -34,7 +34,7 @@ using namespace std; #include "types.h" -#include "debug.h" +#include "util/debug.h" /* welcome to C++ */ /* This class is just a dummy to allow base classes with null ids but diff --git a/Timeline/Project.C b/Timeline/Project.C index ad3a5cd..6230cff 100644 --- a/Timeline/Project.C +++ b/Timeline/Project.C @@ -44,7 +44,7 @@ extern TLE *tle; #define PROJECT_VERSION "0.28.0" -#include "debug.h" +#include "util/debug.h" char Project::_name[256]; char Project::_path[512]; bool Project::_is_open = false; diff --git a/Timeline/TLE.fl b/Timeline/TLE.fl index 5b3c786..a0f9947 100644 --- a/Timeline/TLE.fl +++ b/Timeline/TLE.fl @@ -28,8 +28,6 @@ decl {\#include "Fl_Menu_Settings.H"} {} decl {\#include "Timeline.H"} {} -decl {\#include "Engine.H"} {} - decl {\#include "Transport.H"} {} decl {\#include "Loggable.H"} {} @@ -41,15 +39,14 @@ decl {\#include "Clock.H"} {public decl {\#include "Track.H" // for capture_format} {} -decl {\#include "Audio_File.H" // for supported formats} {} - decl {\#include "Waveform.H" // for options} {} decl {\#include "Audio_Region.H" // for options} {} decl {\#include "Control_Sequence.H" // for options} {} -decl {\#include } {} +decl {\#include } {selected +} decl {\#include } {} @@ -57,6 +54,10 @@ decl {\#include } {} decl {\#include } {} +decl {\#include "Engine/Engine.H"} {} + +decl {\#include "Engine/Audio_File.H" // for supported formats} {} + decl {extern char project_display_name[256];} {global } @@ -160,8 +161,7 @@ menubar->picked( menubar->find_item( "&Timeline/Capture Format/Wav 24" ) ); char *path; asprintf( &path, "%s/options", user_config_dir ); ((Fl_Menu_Settings*)menubar)->load( menubar->find_item( "&Options" ), path ); -free( path );} {selected - } +free( path );} {} } Function {make_window()} {open } { diff --git a/Timeline/Timeline.C b/Timeline/Timeline.C index f4593fd..dd0f3ad 100644 --- a/Timeline/Timeline.C +++ b/Timeline/Timeline.C @@ -34,8 +34,6 @@ #include "Sequence.H" #include "Annotation_Sequence.H" #include "Track.H" -#include "Playback_DS.H" -#include "Record_DS.H" #include "Transport.H" @@ -145,6 +143,7 @@ Timeline::cb_scroll ( Fl_Widget *w ) Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Window( X, Y, W, H, L ) { + _sample_rate = 0; box( FL_FLAT_BOX ); xoffset = 0; @@ -1142,199 +1141,3 @@ Timeline::remove_track ( Track *track ) /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ redraw(); } - -/** Initiate recording for all armed tracks */ -bool -Timeline::record ( void ) -{ - /* FIXME: right place for this? */ - transport->recording = true; - - Loggable::block_start(); - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->armed() && t->record_ds ) - t->record_ds->start( transport->frame ); - } - - deactivate(); - - return true; -} - -/** stop recording for all armed tracks */ -void -Timeline::stop ( void ) -{ - nframes_t frame = transport->frame; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->armed() && t->record_ds ) - t->record_ds->stop( frame ); - } - - Loggable::block_end(); - - activate(); - - transport->recording = false; -} - - -/**********/ -/* Engine */ -/**********/ - -/** call process() on each track header */ -nframes_t -Timeline::process ( nframes_t nframes ) -{ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->process( nframes ); - } - - /* FIXME: BOGUS */ - return nframes; -} - -/* THREAD: RT */ -void -Timeline::seek ( nframes_t frame ) -{ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->seek( frame ); - } -} - -/* THREAD: RT (non-RT) */ -void -Timeline::resize_buffers ( nframes_t nframes ) -{ - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - t->resize_buffers( nframes ); - } -} - -/* THREAD: RT */ -int -Timeline::seek_pending ( void ) -{ - int r = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->playback_ds ) - r += t->playback_ds->buffer_percent() < 50; - } - - return r; -} - - -/* FIXME: shouldn't these belong to the engine? */ -int -Timeline::total_input_buffer_percent ( void ) -{ - int r = 0; - - int cnt = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->record_ds ) - { - ++cnt; - r += t->record_ds->buffer_percent(); - } - } - - if ( ! cnt ) - return 0; - - return r / cnt; -} - -int -Timeline::total_output_buffer_percent ( void ) -{ - - int r = 0; - - int cnt = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->playback_ds ) - { - ++cnt; - r += t->playback_ds->buffer_percent(); - } - } - - if ( ! cnt ) - return 0; - - return r / cnt; -} - -/** wait for I/O threads to fill their buffers */ -void -Timeline::wait_for_buffers ( void ) -{ - while ( total_output_buffer_percent() + total_input_buffer_percent() < 200 ) - usleep( 5000 ); -} - - -int -Timeline::total_playback_xruns ( void ) -{ - int r = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->playback_ds ) - r += t->playback_ds->xruns(); - } - - return r; -} - -int -Timeline::total_capture_xruns ( void ) -{ - int r = 0; - - for ( int i = tracks->children(); i-- ; ) - { - Track *t = (Track*)tracks->child( i ); - - if ( t->record_ds ) - r += t->record_ds->xruns(); - } - - return r; -} diff --git a/Timeline/Timeline.H b/Timeline/Timeline.H index b410cd0..300ed83 100644 --- a/Timeline/Timeline.H +++ b/Timeline/Timeline.H @@ -75,11 +75,6 @@ struct Rectangle Rectangle ( int X, int Y, int W, int H ) : x( X ), y( Y ), w( W ), h( H ) {} }; - -#include "Engine.H" // for sample_rate() - -// class Engine; - #include "RWLock.H" class Timeline : public Fl_Overlay_Window, public RWLock @@ -137,13 +132,15 @@ public: int _yposition; + nframes_t _sample_rate; + Timeline ( int X, int Y, int W, int H, const char *L=0 ); void update_tempomap ( void ); nframes_t fpp ( void ) const { return 1 << _fpp; } nframes_t length ( void ) const { return _length; } - nframes_t sample_rate ( void ) const { return engine->sample_rate(); } + nframes_t sample_rate ( void ) const { return _sample_rate; } int ts_to_x( nframes_t ts ) const { return ts >> _fpp; } nframes_t x_to_ts ( int x ) const { return x << _fpp; } nframes_t x_to_offset ( int x ) const; diff --git a/Timeline/Track.C b/Timeline/Track.C index a7ed8ff..6aee411 100644 --- a/Timeline/Track.C +++ b/Timeline/Track.C @@ -20,12 +20,8 @@ #include "Track.H" #include "Transport.H" -#include "Playback_DS.H" -#include "Record_DS.H" -#include "Engine.H" - -#include "Port.H" +/* #include "Port.H" */ #include "../FL/Fl_Sometimes_Input.H" #include @@ -398,10 +394,6 @@ Track::add ( Control_Sequence *t ) control->add( t ); - control_out.push_back( new Port( Port::Output, name(), control_out.size(), "cv" ) ); - - t->output( control_out.back() ); - resize(); } @@ -583,247 +575,3 @@ Track::handle ( int m ) return 0; } - - -/**********/ -/* Engine */ -/**********/ - -void -Track::update_port_names ( void ) -{ - for ( unsigned int i = 0; i < output.size(); ++i ) - output[ i ].name( name(), i ); - - for ( unsigned int i = 0; i < input.size(); ++i ) - input[ i ].name( name(), i ); - - for ( unsigned int i = 0; i < control_out.size(); ++i ) - control_out[ i ]->name( name(), i, "cv" ); - - -/* /\* tell any attached control sequences to do the same *\/ */ -/* for ( int i = control->children(); i-- ) */ -/* ((Control_Sequence*)control->child( i ))->update_port_names(); */ - -} - -bool -Track::configure_outputs ( int n ) -{ - int on = output.size(); - - if ( n == on ) - return true; - -// engine->lock(); - - if ( playback_ds ) - { - Playback_DS *ds = playback_ds; - playback_ds = NULL; - - ds->shutdown(); - delete ds; - } - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - Port p( Port::Output, name(), i ); - - if ( p.valid() ) - output.push_back( p ); - else - WARNING( "could not create output port!" ); - } - } - else - { - for ( int i = on; i > n; --i ) - { - output.back().shutdown(); - output.pop_back(); - } - } - - if ( output.size() ) - playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), output.size() ); - -// engine->unlock(); - /* FIXME: bogus */ - return true; -} - -bool -Track::configure_inputs ( int n ) -{ - int on = input.size(); - - if ( n == on ) - return true; - -// engine->lock(); - - if ( record_ds ) - { - Record_DS *ds = record_ds; - record_ds = NULL; - - ds->shutdown(); - delete ds; - } - - if ( n > on ) - { - for ( int i = on; i < n; ++i ) - { - Port p( Port::Input, name(), i ); - - if ( p.valid() ) - input.push_back( p ); - else - WARNING( "could not create input port!" ); - } - } - else - { - for ( int i = on; i > n; --i ) - { - input.back().shutdown(); - input.pop_back(); - } - } - - if ( input.size() ) - record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), input.size() ); - -// engine->unlock(); - - /* FIXME: bogus */ - return true; -} - -/* THREAD: RT */ -nframes_t -Track::process ( nframes_t nframes ) -{ - - if ( ! transport->rolling ) - { - for ( int i = output.size(); i--; ) - output[ i ].silence( nframes ); - - for ( int i = input.size(); i--; ) - input[ i ].silence( nframes ); - - /* FIXME: is this really the right thing to do for control ports? */ - for ( int i = control_out.size(); i--; ) - control_out[ i ]->silence( nframes ); - - return 0; - } - - for ( int i = control->children(); i--; ) - ((Control_Sequence*)control->child( i ))->process( nframes ); - - if ( playback_ds ) - { - record_ds->process( nframes ); - return playback_ds->process( nframes ); - } - else - return 0; -} - -/* THREAD: RT */ -void -Track::seek ( nframes_t frame ) -{ - if ( playback_ds ) - return playback_ds->seek( frame ); -} - -/* THREAD: RT (non-RT) */ -void -Track::resize_buffers ( nframes_t nframes ) -{ - if ( record_ds ) - record_ds->resize_buffers( nframes ); - if ( playback_ds ) - playback_ds->resize_buffers( nframes ); -} - -/* FIXME: what about theading issues with this region/audiofile being - accessible from the UI thread? Need locking? */ - -#include "Audio_Region.H" - - -#include - -/** very cheap UUID generator... */ -unsigned long long -uuid ( void ) -{ - time_t t = time( NULL ); - - return (unsigned long long) t; -} - - -/* THREAD: IO */ -/** create capture region and prepare to record */ -void -Track::record ( nframes_t frame ) -{ - assert( ! _capture ); - assert( ! _capture_af ); - - char pat[256]; - - snprintf( pat, sizeof( pat ), "%s-%llu", name(), uuid() ); - - - _capture_af = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format ); - - if ( ! _capture_af ) - { - /* ERROR */ - - } - - /* open it again for reading in the GUI thread */ - Audio_File *af = Audio_File::from_file( _capture_af->name() ); - - _capture = new Audio_Region( af, sequence(), frame ); - - _capture->prepare(); -} - -/* THREAD: IO */ -/** write a block to the (already opened) capture file */ -void -Track::write ( sample_t *buf, nframes_t nframes ) -{ - nframes_t l = _capture_af->write( buf, nframes ); - - _capture->write( l ); -} - -#include - -/* THREAD: IO */ -void -Track::stop ( nframes_t frame ) -{ - _capture->finalize( frame ); - - _capture = NULL; - - _capture_af->finalize(); - - delete _capture_af; - _capture_af = NULL; -} diff --git a/Timeline/Track.H b/Timeline/Track.H index 8be2498..26b472d 100644 --- a/Timeline/Track.H +++ b/Timeline/Track.H @@ -36,7 +36,7 @@ #include using std::vector; -#include "Port.H" +#include "Engine/Port.H" #include "Timeline.H" @@ -212,6 +212,8 @@ public: int size ( void ) const { return _size; } + int ncontrols ( void ) { return controls->children(); } + void resize ( void ); void size ( int v ); diff --git a/Timeline/Transport.C b/Timeline/Transport.C index afe7a71..ce25ed1 100644 --- a/Timeline/Transport.C +++ b/Timeline/Transport.C @@ -17,8 +17,10 @@ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************************/ + #include "Transport.H" -#include "Engine.H" + +#include "Engine/Engine.H" // Transport transport; diff --git a/Timeline/Waveform.H b/Timeline/Waveform.H index b5d8d8d..c55ac5e 100644 --- a/Timeline/Waveform.H +++ b/Timeline/Waveform.H @@ -17,14 +17,10 @@ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************************/ + #pragma once -#include -#include - -#include "Timeline.H" - -#include "Peaks.H" +#include "Engine/Peak.H" class Waveform { diff --git a/Timeline/main.C b/Timeline/main.C index 23a5bd0..ac06e24 100644 --- a/Timeline/main.C +++ b/Timeline/main.C @@ -25,7 +25,9 @@ #include #include #include +#include +/* for registrations */ #include "Audio_Region.H" #include "Sequence.H" #include "Audio_Sequence.H" @@ -34,24 +36,16 @@ #include "Time_Sequence.H" #include "Annotation_Sequence.H" #include "Control_Sequence.H" - -#include "Transport.H" - -#include "Loggable.H" #include "Track.H" -#include "Engine.H" - #include "TLE.H" #include "../FL/Boxtypes.H" -#include -#include - #include "Project.H" - #include "LASH.H" +#include "Transport.H" +#include "Engine/Engine.H" Engine *engine; Timeline *timeline; @@ -69,7 +63,7 @@ const char COPYRIGHT[] = "Copyright (C) 2008 Jonathan Moore Liles"; #define PACKAGE "non" -#include "debug.h" +#include "util/debug.h" char *user_config_dir; diff --git a/Timeline/makefile.inc b/Timeline/makefile.inc index ab30abe..9374b0d 100644 --- a/Timeline/makefile.inc +++ b/Timeline/makefile.inc @@ -4,23 +4,15 @@ Timeline_VERSION := 0.5.0 Timeline_SRCS= \ Timeline/Annotation_Region.C \ -Timeline/Audio_File.C \ -Timeline/Audio_File_SF.C \ Timeline/Audio_Region.C \ Timeline/Audio_Sequence.C \ Timeline/Control_Point.C \ Timeline/Control_Sequence.C \ -Timeline/Disk_Stream.C \ -Timeline/Engine.C \ Timeline/Fl_Menu_Settings.C \ Timeline/LASH.C \ Timeline/LASH_Client.C \ Timeline/Loggable.C \ -Timeline/Peaks.C \ -Timeline/Playback_DS.C \ -Timeline/Port.C \ Timeline/Project.C \ -Timeline/Record_DS.C \ Timeline/Sequence.C \ Timeline/Sequence_Point.C \ Timeline/Sequence_Region.C \ @@ -34,9 +26,25 @@ Timeline/Timeline.C \ Timeline/Track.C \ Timeline/Transport.C \ Timeline/Waveform.C \ -Timeline/dsp.C \ Timeline/main.C \ -debug.C \ +util/debug.C \ + +Timeline_SRCS+=\ +Timeline/Engine/Audio_File.C \ +Timeline/Engine/Audio_File_SF.C \ +Timeline/Engine/Audio_Region.C \ +Timeline/Engine/Audio_Sequence.C \ +Timeline/Engine/Disk_Stream.C \ +Timeline/Engine/Engine.C \ +Timeline/Engine/Peaks.C \ +Timeline/Engine/Playback_DS.C \ +Timeline/Engine/Port.C \ +Timeline/Engine/Record_DS.C \ +Timeline/Engine/Timeline.C \ +Timeline/Engine/Track.C \ +Timeline/Engine/dsp.C \ + + Timeline_OBJS:=$(Timeline_SRCS:.C=.o) diff --git a/Timeline/Mutex.H b/util/Mutex.H similarity index 100% rename from Timeline/Mutex.H rename to util/Mutex.H diff --git a/debug.C b/util/debug.C similarity index 100% rename from debug.C rename to util/debug.C diff --git a/debug.h b/util/debug.h similarity index 100% rename from debug.h rename to util/debug.h