| @@ -17,7 +17,7 @@ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #include "Audio_Track.H" | |||
| #include "Audio_Sequence.H" | |||
| #include "dsp.h" | |||
| @@ -54,13 +54,13 @@ deurlify ( char *url ) | |||
| /** event handler that supports DND of audio clips */ | |||
| int | |||
| Audio_Track::handle ( int m ) | |||
| Audio_Sequence::handle ( int m ) | |||
| { | |||
| switch ( m ) | |||
| { | |||
| case FL_DND_DRAG: | |||
| return Track::handle( m ) | 1; | |||
| return Sequence::handle( m ) | 1; | |||
| /* case FL_DND_ENTER: */ | |||
| /* case FL_DND_LEAVE: */ | |||
| @@ -110,7 +110,7 @@ Audio_Track::handle ( int m ) | |||
| return 1; | |||
| } | |||
| default: | |||
| return Track::handle( m ); | |||
| return Sequence::handle( m ); | |||
| } | |||
| } | |||
| @@ -123,14 +123,14 @@ Audio_Track::handle ( int m ) | |||
| /** determine region coverage and fill /buf/ with interleaved samples | |||
| * from /frame/ to /nframes/ for exactly /channels/ channels. */ | |||
| nframes_t | |||
| Audio_Track::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels ) | |||
| 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 <Track_Widget *>::const_iterator i = _widgets.begin(); | |||
| for ( list <Sequence_Widget *>::const_iterator i = _widgets.begin(); | |||
| i != _widgets.end(); i++ ) | |||
| { | |||
| const Region *r = (Region*)(*i); | |||
| @@ -158,7 +158,7 @@ Audio_Track::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int chann | |||
| /* /\* THREAD: RT *\/ */ | |||
| /* nframes_t */ | |||
| /* Audio_Track::process ( nframes_t nframes ) */ | |||
| /* Audio_Sequence::process ( nframes_t nframes ) */ | |||
| /* { */ | |||
| /* return disktream->process( nframes ); */ | |||
| /* } */ | |||
| @@ -19,36 +19,36 @@ | |||
| #pragma once | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Region.H" | |||
| #include <FL/Fl_Input.H> | |||
| class Audio_Track : public Track | |||
| class Audio_Sequence : public Sequence | |||
| { | |||
| public: | |||
| Audio_Track ( int X, int Y, int W, int H ) : Track( X, Y, W, H ) | |||
| Audio_Sequence ( int X, int Y, int W, int H ) : Sequence( X, Y, W, H ) | |||
| { | |||
| log_create(); | |||
| } | |||
| ~Audio_Track ( ) | |||
| ~Audio_Sequence ( ) | |||
| { | |||
| log_destroy(); | |||
| } | |||
| Track * clone_empty ( void ) | |||
| Sequence * clone_empty ( void ) | |||
| { | |||
| Audio_Track *t = new Audio_Track( x(), y(), w(), h() ); | |||
| Audio_Sequence *t = new Audio_Sequence( x(), y(), w(), h() ); | |||
| return t; | |||
| } | |||
| const char *class_name ( void ) { return "Audio_Track"; } | |||
| const char *class_name ( void ) { return "Audio_Sequence"; } | |||
| int handle ( int m ); | |||
| void dump ( void ); | |||
| @@ -19,9 +19,9 @@ | |||
| #pragma once | |||
| #include "Track_Point.H" | |||
| #include "Sequence_Point.H" | |||
| class Control_Point : public Track_Point | |||
| class Control_Point : public Sequence_Point | |||
| { | |||
| float _y; | |||
| @@ -74,7 +74,7 @@ protected: | |||
| { | |||
| int i; | |||
| sscanf( v, "%X", &i ); | |||
| Track *t = (Track*)Loggable::find( i ); | |||
| Sequence *t = (Sequence*)Loggable::find( i ); | |||
| assert( t ); | |||
| @@ -113,7 +113,7 @@ public: | |||
| } | |||
| Control_Point ( Track *t, nframes_t when, float y ) | |||
| Control_Point ( Sequence *t, nframes_t when, float y ) | |||
| { | |||
| _track = t; | |||
| _y = y; | |||
| @@ -130,7 +130,7 @@ public: | |||
| _y = rhs._y; | |||
| } | |||
| Track_Widget *clone ( const Track_Widget *r ) | |||
| Sequence_Widget *clone ( const Sequence_Widget *r ) | |||
| { | |||
| return new Control_Point( *(Control_Point*)r ); | |||
| } | |||
| @@ -147,7 +147,7 @@ public: | |||
| int | |||
| handle ( int m ) | |||
| { | |||
| int r = Track_Widget::handle( m ); | |||
| int r = Sequence_Widget::handle( m ); | |||
| switch ( m ) | |||
| { | |||
| @@ -19,28 +19,28 @@ | |||
| #pragma once | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Control_Point.H" | |||
| class Control_Track : public Track | |||
| class Control_Sequence : public Sequence | |||
| { | |||
| public: | |||
| Control_Track ( int X, int Y, int W, int H ) : Track( X, Y, W, H ) | |||
| Control_Sequence ( int X, int Y, int W, int H ) : Sequence( X, Y, W, H ) | |||
| { | |||
| color( fl_darker( FL_GREEN ) ); | |||
| log_create(); | |||
| } | |||
| ~Control_Track ( ) | |||
| ~Control_Sequence ( ) | |||
| { | |||
| log_destroy(); | |||
| } | |||
| const char *class_name ( void ) { return "Control_Track"; } | |||
| const char *class_name ( void ) { return "Control_Sequence"; } | |||
| void | |||
| draw ( void ) | |||
| @@ -63,11 +63,11 @@ public: | |||
| fl_begin_complex_polygon(); | |||
| list <Track_Widget *>::const_iterator e = _widgets.end(); | |||
| list <Sequence_Widget *>::const_iterator e = _widgets.end(); | |||
| e--; | |||
| if ( _widgets.size() ) | |||
| for ( list <Track_Widget *>::const_iterator r = _widgets.begin(); ; r++ ) | |||
| for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); ; r++ ) | |||
| { | |||
| if ( r == _widgets.begin() ) | |||
| { | |||
| @@ -92,7 +92,7 @@ public: | |||
| timeline->draw_measure_lines( x(), y(), w(), h(), color() ); | |||
| for ( list <Track_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| (*r)->draw_box(); | |||
| fl_pop_clip(); | |||
| @@ -101,7 +101,7 @@ public: | |||
| int | |||
| handle ( int m ) | |||
| { | |||
| int r = Track::handle( m ); | |||
| int r = Sequence::handle( m ); | |||
| if ( r ) | |||
| return r; | |||
| @@ -18,8 +18,8 @@ | |||
| /*******************************************************************************/ | |||
| #include "Disk_Stream.H" | |||
| #include "Track_Header.H" | |||
| #include "Audio_Track.H" | |||
| #include "Track.H" | |||
| #include "Audio_Sequence.H" | |||
| #include "Port.H" | |||
| #include "Engine.H" // for locking. | |||
| @@ -53,7 +53,7 @@ | |||
| float Disk_Stream::seconds_to_buffer = 5.0f; | |||
| // size_t Disk_Stream::disk_block_frames = 2048; | |||
| Disk_Stream::Disk_Stream ( Track_Header *th, float frame_rate, nframes_t nframes, int channels ) : _th( th ) | |||
| Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ) : _th( th ) | |||
| { | |||
| _frame = 0; | |||
| _thread = 0; | |||
| @@ -99,10 +99,10 @@ Disk_Stream::shutdown ( void ) | |||
| pthread_join( _thread, NULL ); | |||
| } | |||
| Audio_Track * | |||
| Audio_Sequence * | |||
| Disk_Stream::track ( void ) | |||
| { | |||
| return (Audio_Track*)_th->track(); | |||
| return (Audio_Sequence*)_th->track(); | |||
| } | |||
| /** start Disk_Stream thread */ | |||
| @@ -32,8 +32,8 @@ | |||
| #include <vector> | |||
| using std::vector; | |||
| class Track_Header; | |||
| class Audio_Track; | |||
| class Track; | |||
| class Audio_Sequence; | |||
| class Disk_Stream : public Mutex | |||
| { | |||
| @@ -42,7 +42,7 @@ protected: | |||
| pthread_t _thread; /* io thread */ | |||
| Track_Header *_th; /* Track_Header we belong to */ | |||
| Track *_th; /* Track we belong to */ | |||
| nframes_t _nframes; /* buffer size */ | |||
| @@ -59,7 +59,7 @@ protected: | |||
| int channels ( void ) const { return _rb.size(); } | |||
| Audio_Track * track ( void ); | |||
| Audio_Sequence * track ( void ); | |||
| static void *disk_thread ( void *arg ); | |||
| @@ -84,7 +84,7 @@ public: | |||
| /* must be set before any Disk_Streams are created */ | |||
| static float seconds_to_buffer; | |||
| Disk_Stream ( Track_Header *th, float frame_rate, nframes_t nframes, int channels ); | |||
| Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ); | |||
| virtual ~Disk_Stream ( ); | |||
| @@ -3,11 +3,11 @@ SRCS= \ | |||
| Waveform.C \ | |||
| Region.C \ | |||
| main.C \ | |||
| Track.C \ | |||
| Audio_Track.C \ | |||
| Sequence.C \ | |||
| Audio_Sequence.C \ | |||
| Timeline.C \ | |||
| Track_Header.C \ | |||
| Track_Widget.C \ | |||
| Track.C \ | |||
| Sequence_Widget.C \ | |||
| Tempo_Point.C \ | |||
| Time_Point.C \ | |||
| Peaks.C \ | |||
| @@ -23,8 +23,8 @@ | |||
| /* FIXME: we shouldn't depend on these */ | |||
| #include "Timeline.H" | |||
| #include "Engine.H" | |||
| #include "Audio_Track.H" | |||
| #include "Track_Header.H" | |||
| #include "Audio_Sequence.H" | |||
| #include "Track.H" | |||
| #include "Port.H" | |||
| #include "Playback_DS.H" | |||
| @@ -27,7 +27,7 @@ class Playback_DS : public Disk_Stream | |||
| public: | |||
| Playback_DS ( Track_Header *th, float frame_rate, nframes_t nframes, int channels ) : | |||
| Playback_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) : | |||
| Disk_Stream( th, frame_rate, nframes, channels ) | |||
| { | |||
| run(); | |||
| @@ -22,8 +22,8 @@ | |||
| /* FIXME: we shouldn't depend on these */ | |||
| #include "Timeline.H" | |||
| #include "Engine.H" | |||
| #include "Audio_Track.H" | |||
| #include "Track_Header.H" | |||
| #include "Audio_Sequence.H" | |||
| #include "Track.H" | |||
| #include "Port.H" | |||
| #include "Record_DS.H" | |||
| @@ -37,7 +37,7 @@ class Record_DS : public Disk_Stream | |||
| public: | |||
| Record_DS ( Track_Header *th, float frame_rate, nframes_t nframes, int channels ) : | |||
| Record_DS ( Track *th, float frame_rate, nframes_t nframes, int channels ) : | |||
| Disk_Stream( th, frame_rate, nframes, channels ) | |||
| { | |||
| sem_destroy( &_blocks ); | |||
| @@ -17,7 +17,7 @@ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Region.H" | |||
| #include "Timeline.H" | |||
| #include "Waveform.H" | |||
| @@ -103,7 +103,7 @@ Region::init ( void ) | |||
| /* copy constructor */ | |||
| Region::Region ( const Region & rhs ) | |||
| { | |||
| *((Track_Widget*)this) = (Track_Widget &)rhs; | |||
| *((Sequence_Widget*)this) = (Sequence_Widget &)rhs; | |||
| _clip = rhs._clip; | |||
| _scale = rhs._scale; | |||
| @@ -114,8 +114,8 @@ Region::Region ( const Region & rhs ) | |||
| log_create(); | |||
| } | |||
| Track_Widget * | |||
| Region::clone ( const Track_Widget *r ) | |||
| Sequence_Widget * | |||
| Region::clone ( const Sequence_Widget *r ) | |||
| { | |||
| return new Region( *(Region*)r ); | |||
| } | |||
| @@ -132,7 +132,7 @@ Region::Region ( Audio_File *c ) | |||
| /* used when DND importing */ | |||
| Region::Region ( Audio_File *c, Track *t, nframes_t o ) | |||
| Region::Region ( Audio_File *c, Sequence *t, nframes_t o ) | |||
| { | |||
| init(); | |||
| _clip = c; | |||
| @@ -242,11 +242,11 @@ Region::handle ( int m ) | |||
| switch ( m ) | |||
| { | |||
| case FL_ENTER: | |||
| Track_Widget::handle( m ); | |||
| Sequence_Widget::handle( m ); | |||
| redraw(); | |||
| break; | |||
| case FL_LEAVE: | |||
| Track_Widget::handle( m ); | |||
| Sequence_Widget::handle( m ); | |||
| redraw(); | |||
| break; | |||
| case FL_KEYBOARD: | |||
| @@ -335,7 +335,7 @@ Region::handle ( int m ) | |||
| normalize(); | |||
| else | |||
| { | |||
| if ( Track_Widget::current() == this ) | |||
| if ( Sequence_Widget::current() == this ) | |||
| { | |||
| if ( selected() ) | |||
| deselect(); | |||
| @@ -390,14 +390,14 @@ Region::handle ( int m ) | |||
| } | |||
| else | |||
| return Track_Widget::handle( m ); | |||
| return Sequence_Widget::handle( m ); | |||
| } | |||
| break; | |||
| } | |||
| case FL_RELEASE: | |||
| { | |||
| Track_Widget::handle( m ); | |||
| Sequence_Widget::handle( m ); | |||
| copied = false; | |||
| if ( trimming != NO ) | |||
| @@ -470,10 +470,10 @@ Region::handle ( int m ) | |||
| } | |||
| } | |||
| ret = Track_Widget::handle( m ); | |||
| ret = Sequence_Widget::handle( m ); | |||
| return ret | 1; | |||
| default: | |||
| return Track_Widget::handle( m ); | |||
| return Sequence_Widget::handle( m ); | |||
| break; | |||
| } | |||
| @@ -19,18 +19,18 @@ | |||
| #pragma once | |||
| #include "Audio_File.H" | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Timeline.H" | |||
| /* 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 "Track_Widget.H" | |||
| #include "Sequence_Widget.H" | |||
| #include "Loggable.H" | |||
| class Region : public Track_Widget | |||
| class Region : public Sequence_Widget | |||
| { | |||
| public: | |||
| @@ -98,7 +98,7 @@ private: | |||
| Fade _fade_in; | |||
| Fade _fade_out; | |||
| friend class Track_Header; /* for _clip */ | |||
| friend class Track; /* for _clip */ | |||
| protected: | |||
| const char *class_name ( void ) { return "Region"; } | |||
| @@ -166,7 +166,7 @@ protected: | |||
| { | |||
| int i; | |||
| sscanf( v, "%X", &i ); | |||
| Track *t = (Track*)Loggable::find( i ); | |||
| Sequence *t = (Sequence*)Loggable::find( i ); | |||
| assert( t ); | |||
| @@ -200,7 +200,7 @@ public: | |||
| bool current ( void ) const { return this == belowmouse(); } | |||
| friend class Track_Header; /* for _clip in Track_Header::write() */ | |||
| friend class Track; /* for _clip in Track::write() */ | |||
| public: | |||
| @@ -216,7 +216,7 @@ public: | |||
| } | |||
| Track_Widget *clone ( const Track_Widget *r ); | |||
| Sequence_Widget *clone ( const Sequence_Widget *r ); | |||
| ~Region ( ) | |||
| { | |||
| @@ -228,7 +228,7 @@ public: | |||
| Region ( const Region & rhs ); | |||
| Region ( Audio_File *c ); | |||
| Region ( Audio_File *c, Track *t, nframes_t o ); | |||
| Region ( Audio_File *c, Sequence *t, nframes_t o ); | |||
| int handle ( int m ); | |||
| void draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool filled, int X, int W ); | |||
| @@ -20,9 +20,9 @@ | |||
| #pragma once | |||
| #include "Loggable.H" | |||
| #include "Track_Point.H" | |||
| #include "Sequence_Point.H" | |||
| class Ruler_Point : public Track_Point | |||
| class Ruler_Point : public Sequence_Point | |||
| { | |||
| public: | |||
| @@ -73,7 +73,7 @@ protected: | |||
| { | |||
| int i; | |||
| sscanf( v, "%X", &i ); | |||
| Track *t = (Track*)Loggable::find( i ); | |||
| Sequence *t = (Sequence*)Loggable::find( i ); | |||
| assert( t ); | |||
| @@ -123,7 +123,7 @@ public: | |||
| _label = strdup( rhs._label ); | |||
| } | |||
| Track_Widget *clone ( const Track_Widget *r ) | |||
| Sequence_Widget *clone ( const Sequence_Widget *r ) | |||
| { | |||
| return new Ruler_Point( *(Ruler_Point*)r ); | |||
| } | |||
| @@ -138,7 +138,7 @@ public: | |||
| int | |||
| handle ( int m ) | |||
| { | |||
| int r = Track_Widget::handle( m ); | |||
| int r = Sequence_Widget::handle( m ); | |||
| if ( m == FL_RELEASE ) | |||
| { | |||
| @@ -19,16 +19,16 @@ | |||
| #pragma once | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Ruler_Point.H" | |||
| #include "Timeline.H" | |||
| class Ruler_Track : public Track | |||
| class Ruler_Sequence : public Sequence | |||
| { | |||
| public: | |||
| Ruler_Track ( int X, int Y, int W, int H ) : Track ( X, Y, W, H ) | |||
| Ruler_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) | |||
| { | |||
| box( FL_UP_BOX ); | |||
| } | |||
| @@ -36,7 +36,7 @@ public: | |||
| void | |||
| draw ( void ) | |||
| { | |||
| Track::draw(); | |||
| Sequence::draw(); | |||
| timeline->draw_measure_BBT( x(), y(), w(), h(), FL_WHITE ); | |||
| } | |||
| @@ -0,0 +1,417 @@ | |||
| /*******************************************************************************/ | |||
| /* 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 "Sequence.H" | |||
| #include "Timeline.H" | |||
| #include "Region.H" | |||
| #include <FL/fl_draw.H> | |||
| queue <Sequence_Widget *> Sequence::_delete_queue; | |||
| Sequence::Sequence ( int X, int Y, int W, int H ) : Fl_Widget( X, Y, W, H ) | |||
| { | |||
| _name = NULL; | |||
| box( FL_DOWN_BOX ); | |||
| color( fl_darker( FL_GRAY ) ); | |||
| align( FL_ALIGN_LEFT ); | |||
| // log_create(); | |||
| } | |||
| Sequence::~Sequence ( ) | |||
| { | |||
| /* FIXME: what to do with regions? */ | |||
| parent()->redraw(); | |||
| parent()->remove( this ); | |||
| // log_destroy(); | |||
| } | |||
| void | |||
| Sequence::sort ( void ) | |||
| { | |||
| _widgets.sort( Sequence_Widget::sort_func ); | |||
| } | |||
| /** return a pointer to the widget that /r/ overlaps, or NULL if none. */ | |||
| Sequence_Widget * | |||
| Sequence::overlaps ( Sequence_Widget *r ) | |||
| { | |||
| for ( list <Sequence_Widget *>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) | |||
| { | |||
| if ( *i == r ) continue; | |||
| if ( ! ( (*i)->offset() > r->offset() + r->length() || (*i)->offset() + (*i)->length() < r->offset() ) ) | |||
| return *i; | |||
| } | |||
| return NULL; | |||
| } | |||
| #include "Waveform.H" | |||
| void | |||
| Sequence::draw ( void ) | |||
| { | |||
| if ( ! fl_not_clipped( x(), y(), w(), h() ) ) | |||
| return; | |||
| fl_push_clip( x(), y(), w(), h() ); | |||
| draw_box(); | |||
| int X, Y, W, H; | |||
| fl_clip_box( x(), y(), w(), h(), X, Y, W, H ); | |||
| if ( Sequence_Widget::pushed() && Sequence_Widget::pushed()->track() == this ) | |||
| { | |||
| /* make sure the Sequence_Widget::pushed widget is above all others */ | |||
| remove( Sequence_Widget::pushed() ); | |||
| add( Sequence_Widget::pushed() ); | |||
| } | |||
| int xfades = 0; | |||
| // 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(); | |||
| /* draw crossfades */ | |||
| for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| { | |||
| Sequence_Widget *o = overlaps( *r ); | |||
| if ( o ) | |||
| { | |||
| if ( *o <= **r ) | |||
| { | |||
| /* if ( o->x() == (*r)->x() && o->w() == (*r)->w() ) */ | |||
| /* printf( "complete superposition\n" ); */ | |||
| if ( (*r)->x() >= o->x() && (*r)->x() + (*r)->w() <= o->x() + o->w() ) | |||
| /* completely inside */ | |||
| continue; | |||
| ++xfades; | |||
| Rectangle b( (*r)->x(), | |||
| o->y(), | |||
| (o->x() + o->w()) - (*r)->x(), | |||
| o->h() ); | |||
| Fl_Color c = fl_color_average( o->box_color(), (*r)->box_color(), 0.50f ); | |||
| c = fl_color_average( c, FL_YELLOW, 0.30f ); | |||
| fl_push_clip( b.x, b.y, b.w, b.h ); | |||
| draw_box( FL_FLAT_BOX, b.x - 100, b.y, b.w + 200, b.h, c ); | |||
| draw_box( FL_UP_FRAME, b.x - 100, b.y, b.w + 200, b.h, c ); | |||
| fl_pop_clip(); | |||
| } | |||
| } | |||
| } | |||
| // printf( "There are %d xfades\n", xfades ); | |||
| for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| { | |||
| Sequence_Widget *o = overlaps( *r ); | |||
| if ( o ) | |||
| { | |||
| if ( *o <= **r ) | |||
| { | |||
| if ( (*r)->x() >= o->x() && (*r)->x() + (*r)->w() <= o->x() + o->w() ) | |||
| /* completely inside */ | |||
| continue; | |||
| Rectangle b( (*r)->x(), o->y(), (o->x() + o->w()) - (*r)->x(), o->h() ); | |||
| /* draw overlapping waveforms in X-ray style. */ | |||
| Waveform::fill = false; | |||
| /* Fl_Color oc = o->color(); */ | |||
| /* Fl_Color rc = (*r)->color(); */ | |||
| /* /\* give each region a different color *\/ */ | |||
| /* o->color( FL_RED ); */ | |||
| /* (*r)->color( FL_GREEN ); */ | |||
| fl_push_clip( b.x, b.y, b.w, b.h ); | |||
| o->draw(); | |||
| (*r)->draw(); | |||
| fl_pop_clip(); | |||
| Waveform::fill = true; | |||
| /* o->color( oc ); */ | |||
| /* (*r)->color( rc ); */ | |||
| /* fl_color( FL_BLACK ); */ | |||
| /* fl_line_style( FL_DOT, 4 ); */ | |||
| /* b.x = (*r)->line_x(); */ | |||
| /* b.w = min( 32767, (*r)->abs_w() ); */ | |||
| /* fl_line( b.x, b.y, b.x + b.w, b.y + b.h ); */ | |||
| /* fl_line( b.x, b.y + b.h, b.x + b.w, b.y ); */ | |||
| /* fl_line_style( FL_SOLID, 0 ); */ | |||
| // fl_pop_clip(); | |||
| } | |||
| } | |||
| } | |||
| fl_pop_clip(); | |||
| } | |||
| void | |||
| Sequence::remove ( Sequence_Widget *r ) | |||
| { | |||
| // Logger _log( this ); | |||
| _widgets.remove( r ); | |||
| } | |||
| 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(); | |||
| } | |||
| Sequence_Widget * | |||
| Sequence::event_widget ( void ) | |||
| { | |||
| nframes_t ets = timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ); | |||
| for ( list <Sequence_Widget *>::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); r++ ) | |||
| if ( ets > (*r)->offset() && ets < (*r)->offset() + (*r)->length() ) | |||
| return (*r); | |||
| return NULL; | |||
| } | |||
| void | |||
| Sequence::select_range ( int X, int W ) | |||
| { | |||
| nframes_t sts = timeline->xoffset + timeline->x_to_ts( X - 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)->offset() > ets || (*r)->offset() + (*r)->length() < sts ) ) | |||
| (*r)->select(); | |||
| } | |||
| void | |||
| Sequence::add ( Sequence_Widget *r ) | |||
| { | |||
| // Logger _log( this ); | |||
| if ( r->track() ) | |||
| { | |||
| r->redraw(); | |||
| r->track()->remove( r ); | |||
| // r->track()->redraw(); | |||
| } | |||
| r->track( this ); | |||
| _widgets.push_back( r ); | |||
| sort(); | |||
| } | |||
| /* snap /r/ to nearest edge */ | |||
| void | |||
| Sequence::snap ( Sequence_Widget *r ) | |||
| { | |||
| const int snap_pixels = 10; | |||
| const int rx1 = r->x(); | |||
| const int rx2 = r->x() + r->w(); | |||
| for ( list <Sequence_Widget*>::iterator i = _widgets.begin(); i != _widgets.end(); i++ ) | |||
| { | |||
| const Sequence_Widget *w = (*i); | |||
| if ( w == r ) | |||
| continue; | |||
| const int wx1 = w->x(); | |||
| const int wx2 = w->x() + w->w(); | |||
| if ( abs( rx1 - wx2 ) < snap_pixels ) | |||
| { | |||
| r->offset( w->offset() + w->length() + 1 ); | |||
| // printf( "snap: %lu | %lu\n", w->offset() + w->length(), r->offset() ); | |||
| goto done; | |||
| } | |||
| if ( abs( rx2 - wx1 ) < snap_pixels ) | |||
| { | |||
| r->offset( ( w->offset() - r->length() ) - 1 ); | |||
| // printf( "snap: %lu | %lu\n", r->offset() + r->length(), w->offset() ); | |||
| goto done; | |||
| } | |||
| } | |||
| { | |||
| int nx = timeline->nearest_line( r->abs_x() ); | |||
| if ( nx >= 0 ) | |||
| { | |||
| r->offset( timeline->x_to_ts( nx ) ); | |||
| return; | |||
| } | |||
| } | |||
| // r->offset( timeline->x_to_ts( r->x() ) ); | |||
| done: | |||
| return; | |||
| // r->resize(); | |||
| // r->position( rx1, y() ); | |||
| } | |||
| int | |||
| Sequence::handle ( int m ) | |||
| { | |||
| switch ( m ) | |||
| { | |||
| case FL_FOCUS: | |||
| return 1; | |||
| case FL_UNFOCUS: | |||
| return 1; | |||
| case FL_DND_ENTER: | |||
| printf( "enter\n" ); | |||
| if ( Sequence_Widget::pushed() && Sequence_Widget::pushed()->track()->class_name() == class_name() ) | |||
| { | |||
| add( Sequence_Widget::pushed() ); | |||
| redraw(); | |||
| } | |||
| case FL_DND_LEAVE: | |||
| return 1; | |||
| case FL_MOVE: | |||
| { | |||
| Sequence_Widget *r = event_widget(); | |||
| if ( r != Sequence_Widget::belowmouse() ) | |||
| { | |||
| if ( Sequence_Widget::belowmouse() ) | |||
| Sequence_Widget::belowmouse()->handle( FL_LEAVE ); | |||
| Sequence_Widget::belowmouse( r ); | |||
| if ( r ) | |||
| r->handle( FL_ENTER ); | |||
| } | |||
| return 0; | |||
| } | |||
| default: | |||
| { | |||
| Sequence_Widget *r = Sequence_Widget::pushed() ? Sequence_Widget::pushed() : event_widget(); | |||
| if ( r ) | |||
| { | |||
| int retval = r->dispatch( m ); | |||
| if ( retval && m == FL_PUSH ) | |||
| { | |||
| take_focus(); | |||
| Sequence_Widget::pushed( r ); | |||
| } | |||
| if ( retval && m == FL_RELEASE ) | |||
| Sequence_Widget::pushed( NULL ); | |||
| Loggable::block_start(); | |||
| while ( _delete_queue.size() ) | |||
| { | |||
| Sequence_Widget *t = _delete_queue.front(); | |||
| _delete_queue.pop(); | |||
| if ( Sequence_Widget::pushed() == t ) | |||
| Sequence_Widget::pushed( NULL ); | |||
| if ( Sequence_Widget::belowmouse() == t ) | |||
| { | |||
| Sequence_Widget::belowmouse()->handle( FL_LEAVE ); | |||
| Sequence_Widget::belowmouse( NULL ); | |||
| } | |||
| delete t; | |||
| } | |||
| Loggable::block_end(); | |||
| return retval; | |||
| } | |||
| else | |||
| return Fl_Widget::handle( m ); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,131 @@ | |||
| /*******************************************************************************/ | |||
| /* 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 <FL/Fl_Widget.H> | |||
| #include <FL/Fl_Group.H> | |||
| #include <FL/Fl.H> | |||
| // #include "Region.H" | |||
| #include <stdio.h> | |||
| #include "Loggable.H" | |||
| #include <assert.h> | |||
| #include <list> | |||
| // using namespace std; | |||
| class Region; | |||
| class Sequence_Widget; | |||
| #include "types.h" | |||
| /* This is the base class for all track types. */ | |||
| class Sequence : public Fl_Widget, public Loggable | |||
| { | |||
| char *_name; | |||
| static queue <Sequence_Widget *> _delete_queue; | |||
| protected: | |||
| std::list <Sequence_Widget *> _widgets; | |||
| Sequence_Widget *event_widget ( void ); | |||
| virtual const char *class_name ( void ) { return "Sequence"; } | |||
| void set ( char ** ) { return; } | |||
| char ** get ( void ) | |||
| { | |||
| // char *r; | |||
| char **sa = (char**)malloc( sizeof( char* ) * 2); | |||
| sa[0] = (char*)malloc( (_widgets.size() * ((sizeof( int ) * 2) + 3)) + 1 ); | |||
| sa[1] = NULL; | |||
| sa[0][0] = '\0'; | |||
| /* char *s = sa[0]; */ | |||
| /* s += sprintf( s, ":items " ); */ | |||
| /* for ( list <Sequence_Widget *>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) */ | |||
| /* { */ | |||
| /* s += sprintf( s, "0x%X", ((Loggable*)(*i))->id() ); */ | |||
| /* list <Sequence_Widget *>::const_iterator e = i; */ | |||
| /* if ( ++e != _widgets.end() ) */ | |||
| /* s += sprintf( s, "," ); */ | |||
| /* } */ | |||
| return sa; | |||
| } | |||
| public: | |||
| Sequence ( int X, int Y, int W, int H ); | |||
| virtual ~Sequence ( ); | |||
| const char * name ( void ) const { return _name; } | |||
| void name ( char *s ) { if ( _name ) free( _name ); _name = s; label( _name ); } | |||
| void sort ( void ); | |||
| void remove ( Sequence_Widget *r ); | |||
| void add ( Sequence_Widget *r ); | |||
| void select_range ( int X, int W ); | |||
| void remove_selected ( void ); | |||
| const std::list <Sequence_Widget *> widgets ( void ) const { return _widgets; } | |||
| void queue_delete ( Sequence_Widget *r ) | |||
| { | |||
| _delete_queue.push( r ); | |||
| } | |||
| Sequence_Widget * overlaps ( Sequence_Widget *r ); | |||
| virtual Sequence * clone ( void ) | |||
| { | |||
| assert( 0 ); | |||
| } | |||
| virtual Sequence * clone_empty ( void ) | |||
| { | |||
| return NULL; | |||
| } | |||
| virtual void snap ( Sequence_Widget *r ); | |||
| virtual int handle ( int m ); | |||
| virtual void draw ( void ); | |||
| virtual nframes_t process ( nframes_t nframes ) { return 0; } | |||
| }; | |||
| @@ -19,9 +19,9 @@ | |||
| #pragma once | |||
| #include "Track_Widget.H" | |||
| #include "Sequence_Widget.H" | |||
| class Track_Point : public Track_Widget | |||
| class Sequence_Point : public Sequence_Widget | |||
| { | |||
| protected: | |||
| @@ -38,20 +38,20 @@ public: | |||
| int abs_w ( void ) const { return 10; } | |||
| nframes_t length ( void ) const { return timeline->x_to_ts( abs_w() ); } | |||
| Track_Point ( ) | |||
| Sequence_Point ( ) | |||
| { | |||
| _label = NULL; | |||
| } | |||
| virtual ~Track_Point ( ) | |||
| virtual ~Sequence_Point ( ) | |||
| { | |||
| } | |||
| virtual void | |||
| draw ( void ) | |||
| { | |||
| Track_Widget::draw(); | |||
| Sequence_Widget::draw(); | |||
| draw_label( _label, align() ); | |||
| } | |||
| @@ -25,15 +25,15 @@ | |||
| the original? | |||
| */ | |||
| #include "Track_Widget.H" | |||
| #include "Sequence_Widget.H" | |||
| list <Track_Widget *> Track_Widget::_selection; | |||
| Track_Widget * Track_Widget::_current = NULL; | |||
| Track_Widget * Track_Widget::_pushed = NULL; | |||
| Track_Widget * Track_Widget::_belowmouse = NULL; | |||
| list <Sequence_Widget *> Sequence_Widget::_selection; | |||
| Sequence_Widget * Sequence_Widget::_current = NULL; | |||
| Sequence_Widget * Sequence_Widget::_pushed = NULL; | |||
| Sequence_Widget * Sequence_Widget::_belowmouse = NULL; | |||
| void | |||
| Track_Widget::draw_label ( const char *label, Fl_Align align, Fl_Color color ) | |||
| Sequence_Widget::draw_label ( const char *label, Fl_Align align, Fl_Color color ) | |||
| { | |||
| int X, Y; | |||
| @@ -109,9 +109,9 @@ Track_Widget::draw_label ( const char *label, Fl_Align align, Fl_Color color ) | |||
| } | |||
| int | |||
| Track_Widget::dispatch ( int m ) | |||
| Sequence_Widget::dispatch ( int m ) | |||
| { | |||
| Track_Widget::_current = this; | |||
| Sequence_Widget::_current = this; | |||
| if ( selected() ) | |||
| { | |||
| @@ -120,7 +120,7 @@ Track_Widget::dispatch ( int m ) | |||
| int r = 0; | |||
| for ( list <Track_Widget *>::iterator i = _selection.begin(); i != _selection.end(); i++ ) | |||
| for ( list <Sequence_Widget *>::iterator i = _selection.begin(); i != _selection.end(); i++ ) | |||
| if ( *i != this ) | |||
| r |= (*i)->handle( m ); | |||
| @@ -136,7 +136,7 @@ Track_Widget::dispatch ( int m ) | |||
| /* base hanlde just does basic dragging */ | |||
| int | |||
| Track_Widget::handle ( int m ) | |||
| Sequence_Widget::handle ( int m ) | |||
| { | |||
| int X = Fl::event_x(); | |||
| int Y = Fl::event_y(); | |||
| @@ -199,7 +199,7 @@ Track_Widget::handle ( int m ) | |||
| // _r->offset = timeline->x_to_ts( nx ) + timeline->xoffset; | |||
| offset( timeline->x_to_ts( nx ) + timeline->xoffset ); | |||
| if ( Track_Widget::_current == this ) | |||
| if ( Sequence_Widget::_current == this ) | |||
| _track->snap( this ); | |||
| } | |||
| @@ -19,14 +19,14 @@ | |||
| #pragma once | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Loggable.H" | |||
| #include "Timeline.H" | |||
| #include <list> | |||
| #include <algorithm> | |||
| using namespace std; | |||
| class Track_Widget; | |||
| class Sequence_Widget; | |||
| struct Drag | |||
| { | |||
| @@ -35,7 +35,7 @@ struct Drag | |||
| int y; | |||
| int state; | |||
| Track_Widget *original; | |||
| Sequence_Widget *original; | |||
| Drag( int X, int Y ) : x( X ), y( Y ) { state = 0; } | |||
| }; | |||
| @@ -48,25 +48,25 @@ struct Range | |||
| }; | |||
| /* Base class for virtual widget on a track */ | |||
| class Track_Widget : public Loggable | |||
| class Sequence_Widget : public Loggable | |||
| { | |||
| static list <Track_Widget *> _selection; /* all the widgets making up the selection */ | |||
| static list <Sequence_Widget *> _selection; /* all the widgets making up the selection */ | |||
| /* FIXME: is this not the same as /pushed/? */ | |||
| static Track_Widget * _current; /* the widget initiating events that affect the selection */ | |||
| static Sequence_Widget * _current; /* the widget initiating events that affect the selection */ | |||
| /* these are actually managed in the Track classes */ | |||
| static Track_Widget * _pushed; /* the widget receiving drag events (a copy) */ | |||
| static Track_Widget * _original; /* the original of the /pushed/ widget */ | |||
| static Track_Widget * _belowmouse; /* the widget below the mouse cursor */ | |||
| /* these are actually managed in the Sequence classes */ | |||
| static Sequence_Widget * _pushed; /* the widget receiving drag events (a copy) */ | |||
| static Sequence_Widget * _original; /* the original of the /pushed/ widget */ | |||
| static Sequence_Widget * _belowmouse; /* the widget below the mouse cursor */ | |||
| /* can't have this */ | |||
| Track_Widget ( const Track_Widget &rhs ); | |||
| Sequence_Widget ( const Sequence_Widget &rhs ); | |||
| protected: | |||
| Track *_track; /* track this region belongs to */ | |||
| Sequence *_track; /* track this region belongs to */ | |||
| Range _range; /* range for playback */ | |||
| Range *_r; /* range for editing / display (points to the same thing as above, except for when dragging etc) */ | |||
| @@ -78,7 +78,7 @@ protected: | |||
| public: | |||
| Track_Widget ( ) | |||
| Sequence_Widget ( ) | |||
| { | |||
| _track = NULL; | |||
| @@ -89,7 +89,7 @@ public: | |||
| _drag = NULL; | |||
| } | |||
| virtual ~Track_Widget ( ) | |||
| virtual ~Sequence_Widget ( ) | |||
| { | |||
| redraw(); | |||
| @@ -98,8 +98,8 @@ public: | |||
| _selection.remove( this ); | |||
| } | |||
| const Track_Widget & | |||
| operator= ( const Track_Widget &rhs ) | |||
| const Sequence_Widget & | |||
| operator= ( const Sequence_Widget &rhs ) | |||
| { | |||
| if ( this == &rhs ) | |||
| return *this; | |||
| @@ -114,12 +114,12 @@ public: | |||
| } | |||
| /* Track_Widget ( const Track_Widget &rhs ) */ | |||
| /* Sequence_Widget ( const Sequence_Widget &rhs ) */ | |||
| /* { */ | |||
| /* *this = rhs; */ | |||
| /* } */ | |||
| virtual Track_Widget *clone ( const Track_Widget *r ) = 0; | |||
| virtual Sequence_Widget *clone ( const Sequence_Widget *r ) = 0; | |||
| bool selected ( void ) | |||
| { | |||
| @@ -151,15 +151,15 @@ public: | |||
| delete _selection.front(); | |||
| } | |||
| static Track_Widget *current ( void ) { return Track_Widget::_current; } | |||
| static Sequence_Widget *current ( void ) { return Sequence_Widget::_current; } | |||
| static Track_Widget *pushed ( void ) { return Track_Widget::_pushed; } | |||
| static Track_Widget *belowmouse ( void ) { return Track_Widget::_belowmouse; } | |||
| static Sequence_Widget *pushed ( void ) { return Sequence_Widget::_pushed; } | |||
| static Sequence_Widget *belowmouse ( void ) { return Sequence_Widget::_belowmouse; } | |||
| static void pushed ( Track_Widget *w ) { Track_Widget::_pushed = w; } | |||
| static void belowmouse ( Track_Widget *w ) { Track_Widget::_belowmouse = w; } | |||
| static void pushed ( Sequence_Widget *w ) { Sequence_Widget::_pushed = w; } | |||
| static void belowmouse ( Sequence_Widget *w ) { Sequence_Widget::_belowmouse = w; } | |||
| // static void pushed ( Track_Widget *w ) { Track_Widget::_pushed = w; } | |||
| // static void pushed ( Sequence_Widget *w ) { Sequence_Widget::_pushed = w; } | |||
| void begin_drag ( const Drag &d ) | |||
| { | |||
| @@ -190,7 +190,7 @@ public: | |||
| { | |||
| long d = where - _r->offset; | |||
| for ( list <Track_Widget *>::iterator i = _selection.begin(); i != _selection.end(); i++ ) | |||
| for ( list <Sequence_Widget *>::iterator i = _selection.begin(); i != _selection.end(); i++ ) | |||
| { | |||
| (*i)->redraw(); | |||
| @@ -243,8 +243,8 @@ public: | |||
| void color ( Fl_Color v ) { _color = v; } | |||
| Fl_Color box_color ( void ) { return _box_color; } | |||
| Track * track ( void ) const { return _track; } | |||
| void track ( Track *t ) { _track = t; } | |||
| Sequence * track ( void ) const { return _track; } | |||
| void track ( Sequence *t ) { _track = t; } | |||
| nframes_t offset ( void ) const { return _r->offset; } | |||
| // void offset ( nframes_t o ) { _r->offset = o; } | |||
| @@ -285,13 +285,13 @@ public: | |||
| } | |||
| bool | |||
| operator< ( const Track_Widget & rhs ) | |||
| operator< ( const Sequence_Widget & rhs ) | |||
| { | |||
| return _r->offset < rhs._r->offset; | |||
| } | |||
| bool | |||
| operator<=( const Track_Widget & rhs ) | |||
| operator<=( const Sequence_Widget & rhs ) | |||
| { | |||
| return _r->offset <= rhs._r->offset; | |||
| } | |||
| @@ -300,7 +300,7 @@ public: | |||
| virtual int handle ( int m ); | |||
| static bool | |||
| sort_func ( Track_Widget *lhs, Track_Widget *rhs ) | |||
| sort_func ( Sequence_Widget *lhs, Sequence_Widget *rhs ) | |||
| { | |||
| return *lhs < *rhs; | |||
| } | |||
| @@ -19,7 +19,7 @@ | |||
| #include "Tempo_Point.H" | |||
| #include "Tempo_Track.H" | |||
| #include "Tempo_Sequence.H" | |||
| #include "Timeline.H" // for timeline->tempo_track | |||
| char ** | |||
| @@ -101,7 +101,7 @@ Tempo_Point::~Tempo_Point ( ) | |||
| int | |||
| Tempo_Point::handle ( int m ) | |||
| { | |||
| int r = Track_Widget::handle( m ); | |||
| int r = Sequence_Widget::handle( m ); | |||
| if ( m == FL_RELEASE ) | |||
| { | |||
| @@ -19,10 +19,10 @@ | |||
| #pragma once | |||
| #include "Track_Point.H" | |||
| // #include "Tempo_Track.H" | |||
| #include "Sequence_Point.H" | |||
| // #include "Tempo_Sequence.H" | |||
| class Tempo_Point : public Track_Point | |||
| class Tempo_Point : public Sequence_Point | |||
| { | |||
| float _tempo; | |||
| @@ -60,7 +60,7 @@ public: | |||
| _tempo = rhs._tempo; | |||
| } | |||
| Track_Widget *clone ( const Track_Widget *r ) | |||
| Sequence_Widget *clone ( const Sequence_Widget *r ) | |||
| { | |||
| return new Tempo_Point( *(Tempo_Point*)r ); | |||
| } | |||
| @@ -19,17 +19,17 @@ | |||
| #pragma once | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Tempo_Point.H" | |||
| #include <list> | |||
| class Tempo_Track : public Track | |||
| class Tempo_Sequence : public Sequence | |||
| { | |||
| public: | |||
| Tempo_Track ( int X, int Y, int W, int H ) : Track ( X, Y, W, H ) | |||
| Tempo_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) | |||
| { | |||
| box( FL_UP_BOX ); | |||
| } | |||
| @@ -39,7 +39,7 @@ public: | |||
| { | |||
| // sort(); | |||
| for ( std::list <Track_Widget *>::const_reverse_iterator i = _widgets.rbegin(); | |||
| for ( std::list <Sequence_Widget *>::const_reverse_iterator i = _widgets.rbegin(); | |||
| i != _widgets.rend(); i++ ) | |||
| { | |||
| if ( (*i)->offset() < when ) | |||
| @@ -18,7 +18,7 @@ | |||
| /*******************************************************************************/ | |||
| #include "Time_Point.H" | |||
| #include "Time_Track.H" | |||
| #include "Time_Sequence.H" | |||
| #include "Timeline.H" // for timeline->time_track | |||
| char ** | |||
| @@ -19,7 +19,7 @@ | |||
| #pragma once | |||
| #include "Track_Point.H" | |||
| #include "Sequence_Point.H" | |||
| #include "Loggable.H" | |||
| struct time_sig | |||
| @@ -43,7 +43,7 @@ struct time_sig | |||
| #define __CLASS__ "Time_Point" | |||
| class Time_Point : public Track_Point | |||
| class Time_Point : public Sequence_Point | |||
| { | |||
| time_sig _time; | |||
| @@ -96,7 +96,7 @@ public: | |||
| _time = rhs._time; | |||
| } | |||
| Track_Widget *clone ( const Track_Widget *r ) | |||
| Sequence_Widget *clone ( const Sequence_Widget *r ) | |||
| { | |||
| return new Time_Point( *(Time_Point*)r ); | |||
| } | |||
| @@ -116,7 +116,7 @@ public: | |||
| int | |||
| handle ( int m ) | |||
| { | |||
| int r = Track_Widget::handle( m ); | |||
| int r = Sequence_Widget::handle( m ); | |||
| if ( m == FL_RELEASE ) | |||
| { | |||
| @@ -19,18 +19,18 @@ | |||
| #pragma once | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| #include "Time_Point.H" | |||
| #include <list> | |||
| using std::list; | |||
| class Time_Track : public Track | |||
| class Time_Sequence : public Sequence | |||
| { | |||
| public: | |||
| Time_Track ( int X, int Y, int W, int H ) : Track ( X, Y, W, H ) | |||
| Time_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H ) | |||
| { | |||
| box( FL_UP_BOX ); | |||
| } | |||
| @@ -38,7 +38,7 @@ public: | |||
| time_sig | |||
| time ( nframes_t when ) | |||
| { | |||
| for ( list <Track_Widget *>::const_reverse_iterator i = _widgets.rbegin(); | |||
| for ( list <Sequence_Widget *>::const_reverse_iterator i = _widgets.rbegin(); | |||
| i != _widgets.rend(); i++ ) | |||
| { | |||
| if ( (*i)->offset() < when ) | |||
| @@ -18,18 +18,18 @@ | |||
| /*******************************************************************************/ | |||
| #include "Timeline.H" | |||
| #include "Tempo_Track.H" | |||
| #include "Time_Track.H" | |||
| #include "Audio_Track.H" | |||
| #include "Control_Track.H" | |||
| #include "Tempo_Sequence.H" | |||
| #include "Time_Sequence.H" | |||
| #include "Audio_Sequence.H" | |||
| #include "Control_Sequence.H" | |||
| #include <FL/Fl_Scrollbar.H> | |||
| #include "Ruler_Track.H" | |||
| #include "Ruler_Sequence.H" | |||
| // #include <FL/Fl_Image.H> | |||
| // #include <FL/Fl_RGB_Image.H> // needed for alpha blending | |||
| #include "Track_Header.H" | |||
| #include "Track.H" | |||
| const float UPDATE_FREQ = 0.02f; | |||
| @@ -107,11 +107,11 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi | |||
| } | |||
| { | |||
| Fl_Pack *o = new Fl_Pack( X + Track_Header::width(), Y, (W - Track_Header::width()) - vscroll->w(), H - hscroll->h(), "rulers" ); | |||
| Fl_Pack *o = new Fl_Pack( X + Track::width(), Y, (W - Track::width()) - vscroll->w(), H - hscroll->h(), "rulers" ); | |||
| o->type( Fl_Pack::VERTICAL ); | |||
| { | |||
| Tempo_Track *o = new Tempo_Track( 0, 0, 800, 24 ); | |||
| Tempo_Sequence *o = new Tempo_Sequence( 0, 0, 800, 24 ); | |||
| o->color( FL_RED ); | |||
| @@ -127,7 +127,7 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi | |||
| } | |||
| { | |||
| Time_Track *o = new Time_Track( 0, 24, 800, 24 ); | |||
| Time_Sequence *o = new Time_Sequence( 0, 24, 800, 24 ); | |||
| o->color( fl_color_average( FL_RED, FL_WHITE, 0.50f ) ); | |||
| @@ -143,7 +143,7 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi | |||
| } | |||
| { | |||
| Ruler_Track *o = new Ruler_Track( 0, 24, 800, 24 ); | |||
| Ruler_Sequence *o = new Ruler_Sequence( 0, 24, 800, 24 ); | |||
| o->color( FL_GREEN ); | |||
| @@ -180,14 +180,14 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : Fl_Overlay_Wi | |||
| /* for ( int i = 1; i--; ) */ | |||
| /* { */ | |||
| /* // Track_Header *t = new Track_Header( 0, 0, W, 75 ); */ | |||
| /* Track_Header *t = new Track_Header( 0, 0, W, 30 ); */ | |||
| /* Track *o = new Audio_Track( 0, 0, 1, 100 ); */ | |||
| /* // Track *t = new Track( 0, 0, W, 75 ); */ | |||
| /* Track *t = new Track( 0, 0, W, 30 ); */ | |||
| /* Sequence *o = new Audio_Sequence( 0, 0, 1, 100 ); */ | |||
| /* t->track( o ); */ | |||
| /* t->add( new Audio_Track( 0, 0, 1, 100 ) ); */ | |||
| /* t->add( new Audio_Track( 0, 0, 1, 100 ) ); */ | |||
| /* t->add_control( new Control_Track( 0, 0, 1, 100 ) ); */ | |||
| /* t->add( new Audio_Sequence( 0, 0, 1, 100 ) ); */ | |||
| /* t->add( new Audio_Sequence( 0, 0, 1, 100 ) ); */ | |||
| /* t->add_control( new Control_Sequence( 0, 0, 1, 100 ) ); */ | |||
| /* t->color( (Fl_Color)rand() ); */ | |||
| /* } */ | |||
| @@ -250,11 +250,11 @@ struct BBT | |||
| BBT | |||
| Timeline::bbt ( nframes_t when ) | |||
| { | |||
| Tempo_Track *tempo = (Tempo_Track*)rulers->child( 0 ); | |||
| Tempo_Sequence *tempo = (Tempo_Sequence*)rulers->child( 0 ); | |||
| BBT bbt; | |||
| for ( list <Track_Widget *>::const_iterator i = tempo.widgets.begin(); | |||
| for ( list <Sequence_Widget *>::const_iterator i = tempo.widgets.begin(); | |||
| i != tempo.widgets.end(); ++i ) | |||
| { | |||
| Tempo_Point *p = *i; | |||
| @@ -272,7 +272,7 @@ Timeline::nearest_line ( int ix ) | |||
| { | |||
| for ( int x = ix - 10; x < ix + 10; ++x ) | |||
| { | |||
| const int measure = ts_to_x( (double)(_sample_rate * 60) / beats_per_minute( x_to_ts( x - Track_Header::width() ) + xoffset )); | |||
| const int measure = ts_to_x( (double)(_sample_rate * 60) / beats_per_minute( x_to_ts( x - Track::width() ) + xoffset )); | |||
| // const int abs_x = ts_to_x( xoffset ) + x; | |||
| @@ -304,13 +304,13 @@ Timeline::draw_measure ( int X, int Y, int W, int H, Fl_Color color, bool BBT ) | |||
| for ( int x = X; x < X + W; ++x ) | |||
| { | |||
| measure = ts_to_x( (double)(_sample_rate * 60) / beats_per_minute( x_to_ts( x - Track_Header::width() ) + xoffset ) ); | |||
| measure = ts_to_x( (double)(_sample_rate * 60) / beats_per_minute( x_to_ts( x - Track::width() ) + xoffset ) ); | |||
| const int abs_x = ts_to_x( xoffset ) + x - Track_Header::width(); | |||
| const int abs_x = ts_to_x( xoffset ) + x - Track::width(); | |||
| if ( 0 == abs_x % measure ) | |||
| { | |||
| int bpb = beats_per_bar( x_to_ts( x -Track_Header::width() ) + xoffset ); | |||
| int bpb = beats_per_bar( x_to_ts( x -Track::width() ) + xoffset ); | |||
| if ( 0 == (abs_x / measure) % bpb ) | |||
| { | |||
| @@ -419,12 +419,12 @@ Timeline::draw_clip ( void * v, int X, int Y, int W, int H ) | |||
| tl->draw_child( *tl->rulers ); | |||
| /* headers */ | |||
| fl_push_clip( tl->tracks->x(), tl->rulers->y() + tl->rulers->h(), Track_Header::width(), tl->h() - tl->rulers->h() - tl->hscroll->h() ); | |||
| fl_push_clip( tl->tracks->x(), tl->rulers->y() + tl->rulers->h(), Track::width(), tl->h() - tl->rulers->h() - tl->hscroll->h() ); | |||
| tl->draw_child( *tl->tracks ); | |||
| fl_pop_clip(); | |||
| /* track bodies */ | |||
| fl_push_clip( tl->tracks->x() + Track_Header::width(), tl->rulers->y() + tl->rulers->h(), tl->tracks->w() - Track_Header::width(), tl->h() - tl->rulers->h() - tl->hscroll->h() ); | |||
| fl_push_clip( tl->tracks->x() + Track::width(), tl->rulers->y() + tl->rulers->h(), tl->tracks->w() - Track::width(), tl->h() - tl->rulers->h() - tl->hscroll->h() ); | |||
| tl->draw_child( *tl->tracks ); | |||
| fl_pop_clip(); | |||
| @@ -541,13 +541,13 @@ Timeline::draw ( void ) | |||
| int dy = _old_yposition - _yposition; | |||
| if ( ! dy ) | |||
| fl_scroll( X + Track_Header::width(), rulers->y(), rulers->w() - Fl::box_dw( rulers->child(0)->box() ), rulers->h(), dx, 0, draw_clip, this ); | |||
| fl_scroll( X + Track::width(), rulers->y(), rulers->w() - Fl::box_dw( rulers->child(0)->box() ), rulers->h(), dx, 0, draw_clip, this ); | |||
| Y = rulers->y() + rulers->h(); | |||
| H = h() - rulers->h() - hscroll->h(); | |||
| if ( dy == 0 ) | |||
| fl_scroll( X + Track_Header::width(), Y, W - Track_Header::width(), H, dx, dy, draw_clip, this ); | |||
| fl_scroll( X + Track::width(), Y, W - Track::width(), H, dx, dy, draw_clip, this ); | |||
| else | |||
| fl_scroll( X, Y, W, H, dx, dy, draw_clip, this ); | |||
| @@ -561,9 +561,9 @@ Timeline::draw ( void ) | |||
| void | |||
| Timeline::draw_playhead ( void ) | |||
| { | |||
| int x = ( ts_to_x( transport.frame ) - ts_to_x( xoffset ) ) + tracks->x() + Track_Header::width(); | |||
| int x = ( ts_to_x( transport.frame ) - ts_to_x( xoffset ) ) + tracks->x() + Track::width(); | |||
| if ( x < tracks->x() + Track_Header::width() || x > tracks->x() + tracks->w() ) | |||
| if ( x < tracks->x() + Track::width() || x > tracks->x() + tracks->w() ) | |||
| return; | |||
| fl_color( FL_RED ); | |||
| @@ -609,7 +609,7 @@ Timeline::draw_overlay ( void ) | |||
| if ( ! ( _selection.w && _selection.h ) ) | |||
| return; | |||
| fl_push_clip( tracks->x() + Track_Header::width(), rulers->y() + rulers->h(), tracks->w() - Track_Header::width(), h() - rulers->h() - hscroll->h() ); | |||
| fl_push_clip( tracks->x() + Track::width(), rulers->y() + rulers->h(), tracks->w() - Track::width(), h() - rulers->h() - hscroll->h() ); | |||
| const Rectangle &r = _selection; | |||
| @@ -659,7 +659,7 @@ Timeline::draw_overlay ( void ) | |||
| } | |||
| // #include "Track_Widget.H" | |||
| // #include "Sequence_Widget.H" | |||
| /** select all widgets in inside rectangle /r/ */ | |||
| void | |||
| @@ -669,7 +669,7 @@ Timeline::select( const Rectangle &r ) | |||
| for ( int i = tracks->children(); i-- ; ) | |||
| { | |||
| Track_Header *t = (Track_Header*)tracks->child( i ); | |||
| Track *t = (Track*)tracks->child( i ); | |||
| if ( ! ( t->y() > Y + r.h || t->y() + t->h() < Y ) ) | |||
| t->track()->select_range( r.x, r.w ); | |||
| @@ -689,7 +689,7 @@ Timeline::handle ( int m ) | |||
| { | |||
| case FL_Delete: | |||
| { | |||
| Track_Widget::delete_selected(); | |||
| Sequence_Widget::delete_selected(); | |||
| return 1; | |||
| } | |||
| @@ -740,16 +740,16 @@ Timeline::handle ( int m ) | |||
| /* FIXME: prompt for I/O config? */ | |||
| /* add audio track */ | |||
| Track_Header *t = new Track_Header( 0, 0, tracks->w(), 30 ); | |||
| Track *t = new Track( 0, 0, tracks->w(), 30 ); | |||
| add_track( t ); | |||
| Track *o = new Audio_Track( 0, 0, 1, 100 ); | |||
| Sequence *o = new Audio_Sequence( 0, 0, 1, 100 ); | |||
| t->track( o ); | |||
| // t->add( new Audio_Track( 0, 0, 1, 100 ) ); | |||
| // t->add( new Audio_Track( 0, 0, 1, 100 ) ); | |||
| t->add_control( new Control_Track( 0, 0, 1, 100 ) ); | |||
| // t->add( new Audio_Sequence( 0, 0, 1, 100 ) ); | |||
| // t->add( new Audio_Sequence( 0, 0, 1, 100 ) ); | |||
| t->add_control( new Control_Sequence( 0, 0, 1, 100 ) ); | |||
| t->color( (Fl_Color)rand() ); | |||
| } | |||
| @@ -798,7 +798,7 @@ Timeline::handle ( int m ) | |||
| void | |||
| Timeline::add_track ( Track_Header *track ) | |||
| Timeline::add_track ( Track *track ) | |||
| { | |||
| printf( "added new track to the timeline\n" ); | |||
| /* FIXME: do locking */ | |||
| @@ -810,7 +810,7 @@ Timeline::add_track ( Track_Header *track ) | |||
| } | |||
| void | |||
| Timeline::remove_track ( Track_Header *track ) | |||
| Timeline::remove_track ( Track *track ) | |||
| { | |||
| printf( "removed track from the timeline\n" ); | |||
| @@ -833,7 +833,7 @@ Timeline::process ( nframes_t nframes ) | |||
| { | |||
| for ( int i = tracks->children(); i-- ; ) | |||
| { | |||
| Track_Header *t = (Track_Header*)tracks->child( i ); | |||
| Track *t = (Track*)tracks->child( i ); | |||
| t->process( nframes ); | |||
| } | |||
| @@ -848,7 +848,7 @@ Timeline::seek ( nframes_t frame ) | |||
| { | |||
| for ( int i = tracks->children(); i-- ; ) | |||
| { | |||
| Track_Header *t = (Track_Header*)tracks->child( i ); | |||
| Track *t = (Track*)tracks->child( i ); | |||
| t->seek( frame ); | |||
| } | |||
| @@ -862,7 +862,7 @@ Timeline::seek_pending ( void ) | |||
| for ( int i = tracks->children(); i-- ; ) | |||
| { | |||
| Track_Header *t = (Track_Header*)tracks->child( i ); | |||
| Track *t = (Track*)tracks->child( i ); | |||
| if ( t->playback_ds ) | |||
| r += t->playback_ds->buffer_percent() < 50; | |||
| @@ -40,12 +40,12 @@ | |||
| class Timeline; | |||
| extern Timeline *timeline; | |||
| #include "Track.H" | |||
| #include "Sequence.H" | |||
| class Tempo_Track; | |||
| class Time_Track; | |||
| class Ruler_Track; | |||
| class Track_Header; | |||
| class Tempo_Sequence; | |||
| class Time_Sequence; | |||
| class Ruler_Sequence; | |||
| class Track; | |||
| // disables double-buffering to make unnecessary redrawing more apparent | |||
| // #define DEBUG_TIMELINE_DRAWING | |||
| @@ -113,9 +113,9 @@ class Timeline : public Fl_Overlay_Window, public RWLock | |||
| public: | |||
| Tempo_Track *tempo_track; | |||
| Time_Track *time_track; | |||
| Ruler_Track *ruler_track; | |||
| Tempo_Sequence *tempo_track; | |||
| Time_Sequence *time_track; | |||
| Ruler_Sequence *ruler_track; | |||
| nframes_t xoffset; | |||
| @@ -150,8 +150,8 @@ public: | |||
| void select( const Rectangle &r ); | |||
| void add_track ( Track_Header *track ); | |||
| void remove_track ( Track_Header *track ); | |||
| void add_track ( Track *track ); | |||
| void remove_track ( Track *track ); | |||
| private: | |||
| @@ -18,400 +18,356 @@ | |||
| /*******************************************************************************/ | |||
| #include "Track.H" | |||
| #include "Timeline.H" | |||
| #include "Region.H" | |||
| #include <FL/fl_draw.H> | |||
| queue <Track_Widget *> Track::_delete_queue; | |||
| Track::Track ( int X, int Y, int W, int H ) : Fl_Widget( X, Y, W, H ) | |||
| { | |||
| _name = NULL; | |||
| #include "Transport.H" | |||
| #include "Playback_DS.H" | |||
| #include "Record_DS.H" | |||
| box( FL_DOWN_BOX ); | |||
| color( fl_darker( FL_GRAY ) ); | |||
| align( FL_ALIGN_LEFT ); | |||
| #include "Engine.H" | |||
| // log_create(); | |||
| } | |||
| Track::~Track ( ) | |||
| { | |||
| /* FIXME: what to do with regions? */ | |||
| parent()->redraw(); | |||
| parent()->remove( this ); | |||
| // log_destroy(); | |||
| } | |||
| #include "Port.H" | |||
| void | |||
| Track::sort ( void ) | |||
| Track::cb_input_field ( Fl_Widget *w, void *v ) | |||
| { | |||
| _widgets.sort( Track_Widget::sort_func ); | |||
| ((Track*)v)->cb_input_field(); | |||
| } | |||
| /** return a pointer to the widget that /r/ overlaps, or NULL if none. */ | |||
| Track_Widget * | |||
| Track::overlaps ( Track_Widget *r ) | |||
| void | |||
| Track::cb_button ( Fl_Widget *w, void *v ) | |||
| { | |||
| for ( list <Track_Widget *>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) | |||
| { | |||
| if ( *i == r ) continue; | |||
| if ( ! ( (*i)->offset() > r->offset() + r->length() || (*i)->offset() + (*i)->length() < r->offset() ) ) | |||
| return *i; | |||
| } | |||
| return NULL; | |||
| ((Track*)v)->cb_button( w ); | |||
| } | |||
| #include "Waveform.H" | |||
| void | |||
| Track::draw ( void ) | |||
| Track::cb_input_field ( void ) | |||
| { | |||
| log_start(); | |||
| if ( ! fl_not_clipped( x(), y(), w(), h() ) ) | |||
| return; | |||
| fl_push_clip( x(), y(), w(), h() ); | |||
| if ( _name ) | |||
| free( _name ); | |||
| draw_box(); | |||
| _name = strdup( name_field->value() ); | |||
| int X, Y, W, H; | |||
| fl_clip_box( x(), y(), w(), h(), X, Y, W, H ); | |||
| log_end(); | |||
| } | |||
| void | |||
| Track::cb_button ( Fl_Widget *w ) | |||
| { | |||
| if ( Track_Widget::pushed() && Track_Widget::pushed()->track() == this ) | |||
| printf( "FIXME: inform mixer here\n" ); | |||
| if ( w == record_button ) | |||
| { | |||
| /* make sure the Track_Widget::pushed widget is above all others */ | |||
| remove( Track_Widget::pushed() ); | |||
| add( Track_Widget::pushed() ); | |||
| /* FIXME: wrong place for this! */ | |||
| if ( record_button->value() ) | |||
| record_ds->start( transport.frame ); | |||
| else | |||
| record_ds->stop( transport.frame ); | |||
| } | |||
| int xfades = 0; | |||
| // printf( "track::draw %d,%d %dx%d\n", X,Y,W,H ); | |||
| timeline->draw_measure_lines( x(), y(), w(), h(), color() ); | |||
| for ( list <Track_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| (*r)->draw_box(); | |||
| for ( list <Track_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| (*r)->draw(); | |||
| /* draw crossfades */ | |||
| for ( list <Track_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| { | |||
| Track_Widget *o = overlaps( *r ); | |||
| if ( o ) | |||
| else | |||
| if ( w == take_menu ) | |||
| { | |||
| if ( *o <= **r ) | |||
| { | |||
| /* if ( o->x() == (*r)->x() && o->w() == (*r)->w() ) */ | |||
| /* printf( "complete superposition\n" ); */ | |||
| if ( (*r)->x() >= o->x() && (*r)->x() + (*r)->w() <= o->x() + o->w() ) | |||
| /* completely inside */ | |||
| continue; | |||
| ++xfades; | |||
| Rectangle b( (*r)->x(), | |||
| o->y(), | |||
| (o->x() + o->w()) - (*r)->x(), | |||
| o->h() ); | |||
| Fl_Color c = fl_color_average( o->box_color(), (*r)->box_color(), 0.50f ); | |||
| c = fl_color_average( c, FL_YELLOW, 0.30f ); | |||
| fl_push_clip( b.x, b.y, b.w, b.h ); | |||
| draw_box( FL_FLAT_BOX, b.x - 100, b.y, b.w + 200, b.h, c ); | |||
| draw_box( FL_UP_FRAME, b.x - 100, b.y, b.w + 200, b.h, c ); | |||
| int v = take_menu->value(); | |||
| switch ( v ) | |||
| { | |||
| case 0: /* show all takes */ | |||
| show_all_takes( take_menu->menu()[ v ].value() ); | |||
| return; | |||
| case 1: /* new */ | |||
| track( track()->clone_empty() ); | |||
| return; | |||
| } | |||
| fl_pop_clip(); | |||
| const char *s = take_menu->menu()[ v ].text; | |||
| for ( int i = takes->children(); i--; ) | |||
| { | |||
| Sequence *t = (Sequence*)takes->child( i ); | |||
| if ( ! strcmp( s, t->name() ) ) | |||
| { | |||
| track( t ); | |||
| redraw(); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| Track::Track ( int X, int Y, int W, int H, const char *L ) : | |||
| Fl_Group ( X, Y, W, H, L ) | |||
| { | |||
| // printf( "There are %d xfades\n", xfades ); | |||
| _track = NULL; | |||
| _name = NULL; | |||
| _selected = false; | |||
| _show_all_takes = false; | |||
| _size = 1; | |||
| for ( list <Track_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
| { | |||
| Track_Widget *o = overlaps( *r ); | |||
| if ( o ) | |||
| { | |||
| if ( *o <= **r ) | |||
| { | |||
| if ( (*r)->x() >= o->x() && (*r)->x() + (*r)->w() <= o->x() + o->w() ) | |||
| /* completely inside */ | |||
| continue; | |||
| Rectangle b( (*r)->x(), o->y(), (o->x() + o->w()) - (*r)->x(), o->h() ); | |||
| /* draw overlapping waveforms in X-ray style. */ | |||
| Waveform::fill = false; | |||
| char pname[40]; | |||
| static int no = 0, ni = 0; | |||
| /* Fl_Color oc = o->color(); */ | |||
| /* Fl_Color rc = (*r)->color(); */ | |||
| snprintf( pname, sizeof( pname ), "out-%d", no++ ); | |||
| /* /\* give each region a different color *\/ */ | |||
| /* o->color( FL_RED ); */ | |||
| /* (*r)->color( FL_GREEN ); */ | |||
| output.push_back( Port( strdup( pname ), Port::Output ) ); | |||
| fl_push_clip( b.x, b.y, b.w, b.h ); | |||
| snprintf( pname, sizeof( pname ), "in-%d", ni++ ); | |||
| o->draw(); | |||
| (*r)->draw(); | |||
| input.push_back( Port( strdup( pname ), Port::Input ) ); | |||
| fl_pop_clip(); | |||
| snprintf( pname, sizeof( pname ), "in-%d", ni++ ); | |||
| Waveform::fill = true; | |||
| input.push_back( Port( strdup( pname ), Port::Input ) ); | |||
| } | |||
| /* o->color( oc ); */ | |||
| /* (*r)->color( rc ); */ | |||
| playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), 1 ); | |||
| record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), 2 ); | |||
| /* fl_color( FL_BLACK ); */ | |||
| /* fl_line_style( FL_DOT, 4 ); */ | |||
| Fl_Group::size( w(), height() ); | |||
| /* b.x = (*r)->line_x(); */ | |||
| /* b.w = min( 32767, (*r)->abs_w() ); */ | |||
| Track *o = this; | |||
| o->box( FL_THIN_UP_BOX ); | |||
| { | |||
| Fl_Group *o = new Fl_Group( 2, 2, 149, 70 ); | |||
| o->color( ( Fl_Color ) 53 ); | |||
| { | |||
| Fl_Input *o = name_field = new Fl_Input( 2, 2, 144, 24 ); | |||
| o->color( ( Fl_Color ) 33 ); | |||
| o->labeltype( FL_NO_LABEL ); | |||
| o->labelcolor( FL_GRAY0 ); | |||
| o->textcolor( 32 ); | |||
| /* fl_line( b.x, b.y, b.x + b.w, b.y + b.h ); */ | |||
| o->callback( cb_input_field, (void*)this ); | |||
| } | |||
| /* fl_line( b.x, b.y + b.h, b.x + b.w, b.y ); */ | |||
| { | |||
| Fl_Group *o = controls = new Fl_Group( 2, 28, 149, 24 ); | |||
| /* fl_line_style( FL_SOLID, 0 ); */ | |||
| { | |||
| Fl_Button *o = record_button = | |||
| new Fl_Button( 6, 28, 26, 24, "@circle" ); | |||
| o->type( 1 ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->selection_color( FL_RED ); | |||
| o->labelsize( 8 ); | |||
| o->callback( cb_button, this ); | |||
| } | |||
| { | |||
| Fl_Button *o = mute_button = | |||
| new Fl_Button( 35, 28, 26, 24, "m" ); | |||
| o->type( 1 ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->labelsize( 11 ); | |||
| o->callback( cb_button, this ); | |||
| } | |||
| { | |||
| Fl_Button *o = solo_button = | |||
| new Fl_Button( 66, 28, 26, 24, "s" ); | |||
| o->type( 1 ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->labelsize( 11 ); | |||
| o->callback( cb_button, this ); | |||
| } | |||
| { | |||
| Fl_Menu_Button *o = take_menu = | |||
| new Fl_Menu_Button( 97, 28, 47, 24, "T" ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE ); | |||
| o->callback( cb_button, this ); | |||
| // fl_pop_clip(); | |||
| o->add( "Show all takes", 0, 0, 0, FL_MENU_TOGGLE ); | |||
| o->add( "New", 0, 0, 0, FL_MENU_DIVIDER ); | |||
| } | |||
| o->end(); | |||
| } | |||
| } | |||
| fl_pop_clip(); | |||
| } | |||
| void | |||
| Track::remove ( Track_Widget *r ) | |||
| { | |||
| // Logger _log( this ); | |||
| _widgets.remove( r ); | |||
| } | |||
| { | |||
| Fl_Box *o = new Fl_Box( 0, 76, 149, 38 ); | |||
| o->box( FL_FLAT_BOX ); | |||
| Fl_Group::current()->resizable( o ); | |||
| } | |||
| o->size( Track::width(), h() ); | |||
| o->end(); | |||
| } | |||
| { | |||
| Fl_Pack *o = pack = new Fl_Pack( width(), 0, 1006, 115 ); | |||
| o->labeltype( FL_NO_LABEL ); | |||
| o->resize( x() + width(), y(), w() - width(), h() ); | |||
| Fl_Group::current()->resizable( o ); | |||
| void | |||
| Track::remove_selected ( void ) | |||
| { | |||
| Loggable::block_start(); | |||
| { | |||
| Fl_Pack *o = control = new Fl_Pack( width(), 0, pack->w(), 115 ); | |||
| o->end(); | |||
| } | |||
| for ( list <Track_Widget *>::iterator r = _widgets.begin(); r != _widgets.end(); ) | |||
| if ( (*r)->selected() ) | |||
| { | |||
| Track_Widget *t = *r; | |||
| _widgets.erase( r++ ); | |||
| delete t; | |||
| Fl_Pack *o = takes = new Fl_Pack( width(), 0, pack->w(), 115 ); | |||
| o->end(); | |||
| o->hide(); | |||
| } | |||
| else | |||
| ++r; | |||
| Loggable::block_end(); | |||
| } | |||
| o->end(); | |||
| } | |||
| end(); | |||
| log_create(); | |||
| } | |||
| Track_Widget * | |||
| Track::event_widget ( void ) | |||
| Track::~Track ( ) | |||
| { | |||
| nframes_t ets = timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ); | |||
| for ( list <Track_Widget *>::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); r++ ) | |||
| if ( ets > (*r)->offset() && ets < (*r)->offset() + (*r)->length() ) | |||
| return (*r); | |||
| return NULL; | |||
| log_destroy(); | |||
| } | |||
| void | |||
| Track::select_range ( int X, int W ) | |||
| static int pack_visible( Fl_Pack *p ) | |||
| { | |||
| nframes_t sts = timeline->xoffset + timeline->x_to_ts( X - x() ); | |||
| nframes_t ets = sts + timeline->x_to_ts( W ); | |||
| int v = 0; | |||
| for ( int i = p->children(); i--; ) | |||
| if ( p->child( i )->visible() ) | |||
| v++; | |||
| for ( list <Track_Widget *>::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); r++ ) | |||
| if ( ! ( (*r)->offset() > ets || (*r)->offset() + (*r)->length() < sts ) ) | |||
| (*r)->select(); | |||
| return v; | |||
| } | |||
| /* adjust size of widget and children */ | |||
| void | |||
| Track::add ( Track_Widget *r ) | |||
| Track::resize ( void ) | |||
| { | |||
| // Logger _log( this ); | |||
| for ( int i = takes->children(); i--; ) | |||
| takes->child( i )->size( w(), height() ); | |||
| for ( int i = control->children(); i--; ) | |||
| control->child( i )->size( w(), height() ); | |||
| if ( r->track() ) | |||
| if ( _show_all_takes ) | |||
| { | |||
| takes->show(); | |||
| Fl_Group::size( w(), height() * ( 1 + takes->children() + pack_visible( control ) ) ); | |||
| } | |||
| else | |||
| { | |||
| r->redraw(); | |||
| r->track()->remove( r ); | |||
| // r->track()->redraw(); | |||
| takes->hide(); | |||
| Fl_Group::size( w(), height() * ( 1 + pack_visible( control ) ) ); | |||
| } | |||
| r->track( this ); | |||
| _widgets.push_back( r ); | |||
| if ( track() ) | |||
| track()->size( w(), height() ); | |||
| sort(); | |||
| if ( controls->y() + controls->h() > y() + h() ) | |||
| controls->hide(); | |||
| else | |||
| controls->show(); | |||
| parent()->redraw(); | |||
| } | |||
| /* snap /r/ to nearest edge */ | |||
| void | |||
| Track::snap ( Track_Widget *r ) | |||
| Track::size ( int v ) | |||
| { | |||
| const int snap_pixels = 10; | |||
| if ( v < 0 || v > 3 ) | |||
| return; | |||
| const int rx1 = r->x(); | |||
| const int rx2 = r->x() + r->w(); | |||
| _size = v; | |||
| resize(); | |||
| } | |||
| for ( list <Track_Widget*>::iterator i = _widgets.begin(); i != _widgets.end(); i++ ) | |||
| { | |||
| const Track_Widget *w = (*i); | |||
| if ( w == r ) | |||
| continue; | |||
| const int wx1 = w->x(); | |||
| const int wx2 = w->x() + w->w(); | |||
| void | |||
| Track::track( Sequence * t ) | |||
| { | |||
| // t->size( 1, h() ); | |||
| if ( track() ) | |||
| add( track() ); | |||
| if ( abs( rx1 - wx2 ) < snap_pixels ) | |||
| { | |||
| r->offset( w->offset() + w->length() + 1 ); | |||
| // takes->insert( *track(), 0 ); | |||
| // printf( "snap: %lu | %lu\n", w->offset() + w->length(), r->offset() ); | |||
| _track = t; | |||
| pack->insert( *t, 0 ); | |||
| goto done; | |||
| } | |||
| resize(); | |||
| } | |||
| if ( abs( rx2 - wx1 ) < snap_pixels ) | |||
| { | |||
| r->offset( ( w->offset() - r->length() ) - 1 ); | |||
| void | |||
| Track::add_control( Sequence *t ) | |||
| { | |||
| control->add( t ); | |||
| // printf( "snap: %lu | %lu\n", r->offset() + r->length(), w->offset() ); | |||
| resize(); | |||
| } | |||
| goto done; | |||
| } | |||
| } | |||
| { | |||
| int nx = timeline->nearest_line( r->abs_x() ); | |||
| /**********/ | |||
| /* Engine */ | |||
| /**********/ | |||
| if ( nx >= 0 ) | |||
| { | |||
| r->offset( timeline->x_to_ts( nx ) ); | |||
| return; | |||
| } | |||
| /* THREAD: RT */ | |||
| nframes_t | |||
| Track::process ( nframes_t nframes ) | |||
| { | |||
| if ( playback_ds ) | |||
| { | |||
| record_ds->process( nframes ); | |||
| return playback_ds->process( nframes ); | |||
| } | |||
| // r->offset( timeline->x_to_ts( r->x() ) ); | |||
| done: | |||
| return; | |||
| // r->resize(); | |||
| // r->position( rx1, y() ); | |||
| else | |||
| return 0; | |||
| } | |||
| int | |||
| Track::handle ( int m ) | |||
| /* THREAD: RT */ | |||
| void | |||
| Track::seek ( nframes_t frame ) | |||
| { | |||
| if ( playback_ds ) | |||
| return playback_ds->seek( frame ); | |||
| } | |||
| switch ( m ) | |||
| { | |||
| case FL_FOCUS: | |||
| return 1; | |||
| case FL_UNFOCUS: | |||
| return 1; | |||
| case FL_DND_ENTER: | |||
| printf( "enter\n" ); | |||
| if ( Track_Widget::pushed() && Track_Widget::pushed()->track()->class_name() == class_name() ) | |||
| { | |||
| add( Track_Widget::pushed() ); | |||
| redraw(); | |||
| } | |||
| case FL_DND_LEAVE: | |||
| return 1; | |||
| case FL_MOVE: | |||
| { | |||
| Track_Widget *r = event_widget(); | |||
| if ( r != Track_Widget::belowmouse() ) | |||
| { | |||
| if ( Track_Widget::belowmouse() ) | |||
| Track_Widget::belowmouse()->handle( FL_LEAVE ); | |||
| Track_Widget::belowmouse( r ); | |||
| if ( r ) | |||
| r->handle( FL_ENTER ); | |||
| } | |||
| return 0; | |||
| } | |||
| default: | |||
| { | |||
| Track_Widget *r = Track_Widget::pushed() ? Track_Widget::pushed() : event_widget(); | |||
| if ( r ) | |||
| { | |||
| int retval = r->dispatch( m ); | |||
| if ( retval && m == FL_PUSH ) | |||
| { | |||
| take_focus(); | |||
| Track_Widget::pushed( r ); | |||
| } | |||
| if ( retval && m == FL_RELEASE ) | |||
| Track_Widget::pushed( NULL ); | |||
| Loggable::block_start(); | |||
| /* FIXME: what about theading issues with this region/audiofile being | |||
| accessible from the UI thread? Need locking? */ | |||
| while ( _delete_queue.size() ) | |||
| { | |||
| #include "Region.H" | |||
| Track_Widget *t = _delete_queue.front(); | |||
| _delete_queue.pop(); | |||
| /* THREAD: IO */ | |||
| /** create capture region and prepare to record */ | |||
| void | |||
| Track::record ( nframes_t frame ) | |||
| { | |||
| assert( _capture == NULL ); | |||
| /* FIXME: hack */ | |||
| Audio_File *af = Audio_File_SF::create( "testing.wav", 48000, input.size(), "Wav/24" ); | |||
| if ( Track_Widget::pushed() == t ) | |||
| Track_Widget::pushed( NULL ); | |||
| if ( Track_Widget::belowmouse() == t ) | |||
| { | |||
| Track_Widget::belowmouse()->handle( FL_LEAVE ); | |||
| Track_Widget::belowmouse( NULL ); | |||
| } | |||
| _capture = new Region( af, track(), frame ); | |||
| delete t; | |||
| } | |||
| /* FIXME: wrong place for this */ | |||
| _capture->_r->end = 0; | |||
| } | |||
| Loggable::block_end(); | |||
| /* THREAD: IO */ | |||
| /** write a block to the (already opened) capture file */ | |||
| void | |||
| Track::write ( sample_t *buf, nframes_t nframes ) | |||
| { | |||
| _capture->write( buf, nframes ); | |||
| } | |||
| return retval; | |||
| } | |||
| else | |||
| return Fl_Widget::handle( m ); | |||
| } | |||
| } | |||
| /* THREAD: IO */ | |||
| void | |||
| Track::stop ( nframes_t nframes ) | |||
| { | |||
| _capture = NULL; | |||
| } | |||
| @@ -17,115 +17,269 @@ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #pragma once | |||
| #include <FL/Fl_Widget.H> | |||
| #include <FL/Fl_Group.H> | |||
| #ifndef Track_H | |||
| #define Track_H | |||
| #include <FL/Fl.H> | |||
| // #include "Region.H" | |||
| #include <stdio.h> | |||
| #include "Sequence.H" | |||
| #include <FL/Fl_Group.H> | |||
| #include <FL/Fl_Input.H> | |||
| #include <FL/Fl_Button.H> | |||
| #include <FL/Fl_Menu_Button.H> | |||
| #include <FL/Fl_Pack.H> | |||
| #include <FL/Fl_Box.H> | |||
| #include "Loggable.H" | |||
| #include <assert.h> | |||
| // #include "Port.H" | |||
| #include <list> | |||
| /* TODO: rename this to Audio_Sequence_Header or something since it's clearly audio specific. */ | |||
| // using namespace std; | |||
| #include <vector> | |||
| using std::vector; | |||
| class Region; | |||
| class Track_Widget; | |||
| class Playback_DS; | |||
| class Record_DS; | |||
| class Port; | |||
| #include "types.h" | |||
| class Track : public Fl_Group, public Loggable | |||
| { | |||
| public: | |||
| /* This is the base class for all track types. */ | |||
| Track ( int X, int Y, int W, int H, const char *L = 0 ); | |||
| ~Track ( ); | |||
| class Track : public Fl_Widget, public Loggable | |||
| { | |||
| private: | |||
| // Sequence * _track; | |||
| char *_name; | |||
| static queue <Track_Widget *> _delete_queue; | |||
| bool _selected; | |||
| protected: | |||
| bool _show_all_takes; | |||
| std::list <Track_Widget *> _widgets; | |||
| Track_Widget *event_widget ( void ); | |||
| int _size; | |||
| virtual const char *class_name ( void ) { return "Track"; } | |||
| enum { AUDIO } _type; | |||
| Sequence *_track; | |||
| void set ( char ** ) { return; } | |||
| Region *_capture; /* capture region */ | |||
| char ** get ( void ) | |||
| public: | |||
| Fl_Input * name_field; | |||
| Fl_Button *record_button; | |||
| Fl_Button *mute_button; | |||
| Fl_Button *solo_button; | |||
| Fl_Menu_Button *take_menu; | |||
| Fl_Group *controls; | |||
| Fl_Pack *pack; | |||
| Fl_Pack *control; | |||
| Fl_Pack *takes; | |||
| vector <Port> input; | |||
| vector <Port> output; /* output ports... */ | |||
| Playback_DS *playback_ds; | |||
| Record_DS *record_ds; | |||
| const char *class_name ( void ) { return "Track"; } | |||
| void set ( char **sa ) | |||
| { | |||
| // char *r; | |||
| for ( int i = 0; sa[i]; ++i ) | |||
| { | |||
| char *s = sa[i]; | |||
| strtok( s, " " ); | |||
| char *v = s + strlen( s ) + 1; | |||
| if ( *v == '"' ) | |||
| { | |||
| v++; | |||
| v[ strlen( v ) - 2 ] = '\0'; | |||
| } | |||
| if ( ! strcmp( s, ":h" ) ) | |||
| { | |||
| size( atoi( v ) ); | |||
| Fl_Widget::size( w(), height() ); | |||
| } | |||
| else if ( ! strcmp( s, ":selected" ) ) | |||
| _selected = atoi( v ); | |||
| // else if ( ! strcmp( s, ":armed" | |||
| else if ( ! strcmp( s, ":name" ) ) | |||
| { | |||
| _name = strdup( v ); | |||
| name_field->value( _name ); | |||
| } | |||
| else if ( ! strcmp( s, ":track" ) ) | |||
| { | |||
| int i; | |||
| sscanf( v, "%X", &i ); | |||
| Sequence *t = (Sequence*)Loggable::find( i ); | |||
| assert( t ); | |||
| char **sa = (char**)malloc( sizeof( char* ) * 2); | |||
| sa[0] = (char*)malloc( (_widgets.size() * ((sizeof( int ) * 2) + 3)) + 1 ); | |||
| sa[1] = NULL; | |||
| track( t ); | |||
| } | |||
| sa[0][0] = '\0'; | |||
| /* char *s = sa[0]; */ | |||
| free( s ); | |||
| } | |||
| free( sa ); | |||
| } | |||
| char ** get ( void ) | |||
| { | |||
| char **sa = (char**)malloc( sizeof( char* ) * (1 + 5) ); | |||
| int i = 0; | |||
| /* s += sprintf( s, ":items " ); */ | |||
| /* for ( list <Track_Widget *>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ ) */ | |||
| /* { */ | |||
| /* s += sprintf( s, "0x%X", ((Loggable*)(*i))->id() ); */ | |||
| asprintf( &sa[ i++ ], ":name \"%s\"", _name ? _name : "" ); | |||
| asprintf( &sa[ i++ ], ":track 0x%X", track() ? track()->id() : 0 ); | |||
| asprintf( &sa[ i++ ], ":selected %d", _selected ); | |||
| // asprintf( &sa[ i++ ], ":record %d", record_button->value() ); | |||
| /* list <Track_Widget *>::const_iterator e = i; */ | |||
| /* if ( ++e != _widgets.end() ) */ | |||
| /* s += sprintf( s, "," ); */ | |||
| /* } */ | |||
| /* asprintf( &sa[ i++ ], ":solo %d", solo_button->value() ); */ | |||
| /* asprintf( &sa[ i++ ], ":mute %d", mute_button->value() ); */ | |||
| asprintf( &sa[ i++ ], ":h %d", size() ); | |||
| // asprintf( &sa[ i++ ], ":gain %f", _scale ); | |||
| sa[ i ] = NULL; | |||
| return sa; | |||
| } | |||
| public: | |||
| Track ( int X, int Y, int W, int H ); | |||
| virtual ~Track ( ); | |||
| /* for loggable */ | |||
| static Loggable * | |||
| create ( char **sa ) | |||
| { | |||
| Track *r = new Track( 0, 0, 1, 1 ); | |||
| const char * name ( void ) const { return _name; } | |||
| void name ( char *s ) { if ( _name ) free( _name ); _name = s; label( _name ); } | |||
| r->set( sa ); | |||
| void sort ( void ); | |||
| return (Loggable *)r; | |||
| } | |||
| void | |||
| draw ( void ) | |||
| { | |||
| if ( _selected ) | |||
| { | |||
| Fl_Color c = color(); | |||
| void remove ( Track_Widget *r ); | |||
| void add ( Track_Widget *r ); | |||
| color( FL_RED ); | |||
| void select_range ( int X, int W ); | |||
| Fl_Group::draw(); | |||
| void remove_selected ( void ); | |||
| color( c ); | |||
| } | |||
| else | |||
| Fl_Group::draw(); | |||
| } | |||
| const std::list <Track_Widget *> widgets ( void ) const { return _widgets; } | |||
| void add_control( Sequence *t ); | |||
| void queue_delete ( Track_Widget *r ) | |||
| int size ( void ) const { return _size; } | |||
| void resize ( void ); | |||
| void size ( int v ); | |||
| int height ( void ) const | |||
| { | |||
| _delete_queue.push( r ); | |||
| static int table[] = { 30, 80, 150, 300 }; | |||
| return table[ _size ]; | |||
| } | |||
| Track_Widget * overlaps ( Track_Widget *r ); | |||
| void show_all_takes ( bool b ) | |||
| { | |||
| _show_all_takes = b; | |||
| resize(); | |||
| } | |||
| const char * name ( void ) const { return _name; } | |||
| bool mute ( void ) const { return mute_button->value(); } | |||
| bool solo ( void ) const { return solo_button->value(); } | |||
| bool armed ( void ) const { return record_button->value(); } | |||
| bool selected ( void ) const { return _selected; } | |||
| virtual Track * clone ( void ) | |||
| static void cb_input_field ( Fl_Widget *w, void *v ); | |||
| void cb_input_field ( void ); | |||
| static void cb_button ( Fl_Widget *w, void *v ); | |||
| void cb_button ( Fl_Widget *w ); | |||
| static int width ( void ) { return 150; } | |||
| void track( Sequence * t ); | |||
| Sequence * track ( void ) { return _track; } | |||
| void add ( Sequence * t ) | |||
| { | |||
| takes->insert( *t, 0 ); | |||
| if ( ! t->name() ) | |||
| { | |||
| char pat[20]; | |||
| snprintf( pat, sizeof( pat ), "%d", takes->children() ); | |||
| t->name( strdup( pat ) ); | |||
| take_menu->add( t->name() ); | |||
| } | |||
| } | |||
| void remote ( Sequence *t ) | |||
| { | |||
| assert( 0 ); | |||
| takes->remove( t ); | |||
| // take_menu->remove( t->name() ); | |||
| } | |||
| virtual Track * clone_empty ( void ) | |||
| int handle ( int m ) | |||
| { | |||
| return NULL; | |||
| switch ( m ) | |||
| { | |||
| case FL_MOUSEWHEEL: | |||
| { | |||
| if ( ! Fl::event_shift() ) | |||
| return 0; | |||
| int d = Fl::event_dy(); | |||
| printf( "%d\n", d ); | |||
| if ( d < 0 ) | |||
| size( size() - 1 ); | |||
| else | |||
| size( size() + 1 ); | |||
| return 1; | |||
| } | |||
| default: | |||
| return Fl_Group::handle( m ); | |||
| } | |||
| } | |||
| virtual void snap ( Track_Widget *r ); | |||
| virtual int handle ( int m ); | |||
| virtual void draw ( void ); | |||
| virtual nframes_t process ( nframes_t nframes ) { return 0; } | |||
| /* Engine */ | |||
| nframes_t process ( nframes_t nframes ); | |||
| void seek ( nframes_t frame ); | |||
| void record ( nframes_t nframes ); | |||
| void write ( sample_t *buf, nframes_t nframes ); | |||
| void stop ( nframes_t nframes ); | |||
| }; | |||
| #endif | |||
| @@ -1,373 +0,0 @@ | |||
| /*******************************************************************************/ | |||
| /* 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_Header.H" | |||
| #include "Transport.H" | |||
| #include "Playback_DS.H" | |||
| #include "Record_DS.H" | |||
| #include "Engine.H" | |||
| #include "Port.H" | |||
| void | |||
| Track_Header::cb_input_field ( Fl_Widget *w, void *v ) | |||
| { | |||
| ((Track_Header*)v)->cb_input_field(); | |||
| } | |||
| void | |||
| Track_Header::cb_button ( Fl_Widget *w, void *v ) | |||
| { | |||
| ((Track_Header*)v)->cb_button( w ); | |||
| } | |||
| void | |||
| Track_Header::cb_input_field ( void ) | |||
| { | |||
| log_start(); | |||
| if ( _name ) | |||
| free( _name ); | |||
| _name = strdup( name_field->value() ); | |||
| log_end(); | |||
| } | |||
| void | |||
| Track_Header::cb_button ( Fl_Widget *w ) | |||
| { | |||
| printf( "FIXME: inform mixer here\n" ); | |||
| if ( w == record_button ) | |||
| { | |||
| /* FIXME: wrong place for this! */ | |||
| if ( record_button->value() ) | |||
| record_ds->start( transport.frame ); | |||
| else | |||
| record_ds->stop( transport.frame ); | |||
| } | |||
| 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 */ | |||
| track( track()->clone_empty() ); | |||
| return; | |||
| } | |||
| const char *s = take_menu->menu()[ v ].text; | |||
| for ( int i = takes->children(); i--; ) | |||
| { | |||
| Track *t = (Track*)takes->child( i ); | |||
| if ( ! strcmp( s, t->name() ) ) | |||
| { | |||
| track( t ); | |||
| redraw(); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| Track_Header::Track_Header ( int X, int Y, int W, int H, const char *L ) : | |||
| Fl_Group ( X, Y, W, H, L ) | |||
| { | |||
| _track = NULL; | |||
| _name = NULL; | |||
| _selected = false; | |||
| _show_all_takes = false; | |||
| _size = 1; | |||
| { | |||
| char pname[40]; | |||
| static int no = 0, ni = 0; | |||
| snprintf( pname, sizeof( pname ), "out-%d", no++ ); | |||
| output.push_back( Port( strdup( pname ), Port::Output ) ); | |||
| snprintf( pname, sizeof( pname ), "in-%d", ni++ ); | |||
| input.push_back( Port( strdup( pname ), Port::Input ) ); | |||
| snprintf( pname, sizeof( pname ), "in-%d", ni++ ); | |||
| input.push_back( Port( strdup( pname ), Port::Input ) ); | |||
| } | |||
| playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), 1 ); | |||
| record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), 2 ); | |||
| Fl_Group::size( w(), height() ); | |||
| Track_Header *o = this; | |||
| o->box( FL_THIN_UP_BOX ); | |||
| { | |||
| Fl_Group *o = new Fl_Group( 2, 2, 149, 70 ); | |||
| o->color( ( Fl_Color ) 53 ); | |||
| { | |||
| Fl_Input *o = name_field = new Fl_Input( 2, 2, 144, 24 ); | |||
| o->color( ( Fl_Color ) 33 ); | |||
| o->labeltype( FL_NO_LABEL ); | |||
| o->labelcolor( FL_GRAY0 ); | |||
| o->textcolor( 32 ); | |||
| o->callback( cb_input_field, (void*)this ); | |||
| } | |||
| { | |||
| Fl_Group *o = controls = new Fl_Group( 2, 28, 149, 24 ); | |||
| { | |||
| Fl_Button *o = record_button = | |||
| new Fl_Button( 6, 28, 26, 24, "@circle" ); | |||
| o->type( 1 ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->selection_color( FL_RED ); | |||
| o->labelsize( 8 ); | |||
| o->callback( cb_button, this ); | |||
| } | |||
| { | |||
| Fl_Button *o = mute_button = | |||
| new Fl_Button( 35, 28, 26, 24, "m" ); | |||
| o->type( 1 ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->labelsize( 11 ); | |||
| o->callback( cb_button, this ); | |||
| } | |||
| { | |||
| Fl_Button *o = solo_button = | |||
| new Fl_Button( 66, 28, 26, 24, "s" ); | |||
| o->type( 1 ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->labelsize( 11 ); | |||
| o->callback( cb_button, this ); | |||
| } | |||
| { | |||
| Fl_Menu_Button *o = take_menu = | |||
| new Fl_Menu_Button( 97, 28, 47, 24, "T" ); | |||
| o->box( FL_THIN_UP_BOX ); | |||
| o->color( FL_LIGHT1 ); | |||
| o->align( FL_ALIGN_LEFT | FL_ALIGN_INSIDE ); | |||
| o->callback( cb_button, this ); | |||
| o->add( "Show all takes", 0, 0, 0, FL_MENU_TOGGLE ); | |||
| o->add( "New", 0, 0, 0, FL_MENU_DIVIDER ); | |||
| } | |||
| o->end(); | |||
| } | |||
| { | |||
| Fl_Box *o = new Fl_Box( 0, 76, 149, 38 ); | |||
| o->box( FL_FLAT_BOX ); | |||
| Fl_Group::current()->resizable( o ); | |||
| } | |||
| o->size( Track_Header::width(), h() ); | |||
| o->end(); | |||
| } | |||
| { | |||
| Fl_Pack *o = pack = new Fl_Pack( width(), 0, 1006, 115 ); | |||
| o->labeltype( FL_NO_LABEL ); | |||
| o->resize( x() + width(), y(), w() - width(), h() ); | |||
| Fl_Group::current()->resizable( o ); | |||
| { | |||
| Fl_Pack *o = control = new Fl_Pack( width(), 0, pack->w(), 115 ); | |||
| o->end(); | |||
| } | |||
| { | |||
| Fl_Pack *o = takes = new Fl_Pack( width(), 0, pack->w(), 115 ); | |||
| o->end(); | |||
| o->hide(); | |||
| } | |||
| o->end(); | |||
| } | |||
| end(); | |||
| log_create(); | |||
| } | |||
| Track_Header::~Track_Header ( ) | |||
| { | |||
| log_destroy(); | |||
| } | |||
| static int pack_visible( Fl_Pack *p ) | |||
| { | |||
| int v = 0; | |||
| for ( int i = p->children(); i--; ) | |||
| if ( p->child( i )->visible() ) | |||
| v++; | |||
| return v; | |||
| } | |||
| /* adjust size of widget and children */ | |||
| void | |||
| Track_Header::resize ( void ) | |||
| { | |||
| for ( int i = takes->children(); i--; ) | |||
| takes->child( i )->size( w(), height() ); | |||
| for ( int i = control->children(); i--; ) | |||
| control->child( i )->size( w(), height() ); | |||
| if ( _show_all_takes ) | |||
| { | |||
| takes->show(); | |||
| Fl_Group::size( w(), height() * ( 1 + takes->children() + pack_visible( control ) ) ); | |||
| } | |||
| else | |||
| { | |||
| takes->hide(); | |||
| Fl_Group::size( w(), height() * ( 1 + pack_visible( control ) ) ); | |||
| } | |||
| if ( track() ) | |||
| track()->size( w(), height() ); | |||
| if ( controls->y() + controls->h() > y() + h() ) | |||
| controls->hide(); | |||
| else | |||
| controls->show(); | |||
| parent()->redraw(); | |||
| } | |||
| void | |||
| Track_Header::size ( int v ) | |||
| { | |||
| if ( v < 0 || v > 3 ) | |||
| return; | |||
| _size = v; | |||
| resize(); | |||
| } | |||
| void | |||
| Track_Header::track( Track * t ) | |||
| { | |||
| // t->size( 1, h() ); | |||
| if ( track() ) | |||
| add( track() ); | |||
| // takes->insert( *track(), 0 ); | |||
| _track = t; | |||
| pack->insert( *t, 0 ); | |||
| resize(); | |||
| } | |||
| void | |||
| Track_Header::add_control( Track *t ) | |||
| { | |||
| control->add( t ); | |||
| resize(); | |||
| } | |||
| /**********/ | |||
| /* Engine */ | |||
| /**********/ | |||
| /* THREAD: RT */ | |||
| nframes_t | |||
| Track_Header::process ( nframes_t nframes ) | |||
| { | |||
| if ( playback_ds ) | |||
| { | |||
| record_ds->process( nframes ); | |||
| return playback_ds->process( nframes ); | |||
| } | |||
| else | |||
| return 0; | |||
| } | |||
| /* THREAD: RT */ | |||
| void | |||
| Track_Header::seek ( nframes_t frame ) | |||
| { | |||
| if ( playback_ds ) | |||
| return playback_ds->seek( frame ); | |||
| } | |||
| /* FIXME: what about theading issues with this region/audiofile being | |||
| accessible from the UI thread? Need locking? */ | |||
| #include "Region.H" | |||
| /* THREAD: IO */ | |||
| /** create capture region and prepare to record */ | |||
| void | |||
| Track_Header::record ( nframes_t frame ) | |||
| { | |||
| assert( _capture == NULL ); | |||
| /* FIXME: hack */ | |||
| Audio_File *af = Audio_File_SF::create( "testing.wav", 48000, input.size(), "Wav/24" ); | |||
| _capture = new Region( af, track(), frame ); | |||
| /* FIXME: wrong place for this */ | |||
| _capture->_r->end = 0; | |||
| } | |||
| /* THREAD: IO */ | |||
| /** write a block to the (already opened) capture file */ | |||
| void | |||
| Track_Header::write ( sample_t *buf, nframes_t nframes ) | |||
| { | |||
| _capture->write( buf, nframes ); | |||
| } | |||
| /* THREAD: IO */ | |||
| void | |||
| Track_Header::stop ( nframes_t nframes ) | |||
| { | |||
| _capture = NULL; | |||
| } | |||
| @@ -1,285 +0,0 @@ | |||
| /*******************************************************************************/ | |||
| /* 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. */ | |||
| /*******************************************************************************/ | |||
| #ifndef Track_Header_H | |||
| #define Track_Header_H | |||
| #include <FL/Fl.H> | |||
| #include "Track.H" | |||
| #include <FL/Fl_Group.H> | |||
| #include <FL/Fl_Input.H> | |||
| #include <FL/Fl_Button.H> | |||
| #include <FL/Fl_Menu_Button.H> | |||
| #include <FL/Fl_Pack.H> | |||
| #include <FL/Fl_Box.H> | |||
| #include "Loggable.H" | |||
| // #include "Port.H" | |||
| /* TODO: rename this to Audio_Track_Header or something since it's audio specific. */ | |||
| #include <vector> | |||
| using std::vector; | |||
| class Playback_DS; | |||
| class Record_DS; | |||
| class Port; | |||
| class Track_Header : public Fl_Group, public Loggable | |||
| { | |||
| public: | |||
| Track_Header ( int X, int Y, int W, int H, const char *L = 0 ); | |||
| ~Track_Header ( ); | |||
| private: | |||
| // Track * _track; | |||
| char *_name; | |||
| bool _selected; | |||
| bool _show_all_takes; | |||
| int _size; | |||
| enum { AUDIO } _type; | |||
| Track *_track; | |||
| Region *_capture; /* capture region */ | |||
| public: | |||
| Fl_Input * name_field; | |||
| Fl_Button *record_button; | |||
| Fl_Button *mute_button; | |||
| Fl_Button *solo_button; | |||
| Fl_Menu_Button *take_menu; | |||
| Fl_Group *controls; | |||
| Fl_Pack *pack; | |||
| Fl_Pack *control; | |||
| Fl_Pack *takes; | |||
| vector <Port> input; | |||
| vector <Port> output; /* output ports... */ | |||
| Playback_DS *playback_ds; | |||
| Record_DS *record_ds; | |||
| const char *class_name ( void ) { return "Track_Header"; } | |||
| void set ( char **sa ) | |||
| { | |||
| for ( int i = 0; sa[i]; ++i ) | |||
| { | |||
| char *s = sa[i]; | |||
| strtok( s, " " ); | |||
| char *v = s + strlen( s ) + 1; | |||
| if ( *v == '"' ) | |||
| { | |||
| v++; | |||
| v[ strlen( v ) - 2 ] = '\0'; | |||
| } | |||
| if ( ! strcmp( s, ":h" ) ) | |||
| { | |||
| size( atoi( v ) ); | |||
| Fl_Widget::size( w(), height() ); | |||
| } | |||
| else if ( ! strcmp( s, ":selected" ) ) | |||
| _selected = atoi( v ); | |||
| // else if ( ! strcmp( s, ":armed" | |||
| else if ( ! strcmp( s, ":name" ) ) | |||
| { | |||
| _name = strdup( v ); | |||
| name_field->value( _name ); | |||
| } | |||
| else if ( ! strcmp( s, ":track" ) ) | |||
| { | |||
| int i; | |||
| sscanf( v, "%X", &i ); | |||
| Track *t = (Track*)Loggable::find( i ); | |||
| assert( t ); | |||
| track( t ); | |||
| } | |||
| free( s ); | |||
| } | |||
| free( sa ); | |||
| } | |||
| char ** get ( void ) | |||
| { | |||
| char **sa = (char**)malloc( sizeof( char* ) * (1 + 5) ); | |||
| int i = 0; | |||
| asprintf( &sa[ i++ ], ":name \"%s\"", _name ? _name : "" ); | |||
| asprintf( &sa[ i++ ], ":track 0x%X", track() ? track()->id() : 0 ); | |||
| asprintf( &sa[ i++ ], ":selected %d", _selected ); | |||
| // asprintf( &sa[ i++ ], ":record %d", record_button->value() ); | |||
| /* asprintf( &sa[ i++ ], ":solo %d", solo_button->value() ); */ | |||
| /* asprintf( &sa[ i++ ], ":mute %d", mute_button->value() ); */ | |||
| asprintf( &sa[ i++ ], ":h %d", size() ); | |||
| // asprintf( &sa[ i++ ], ":gain %f", _scale ); | |||
| sa[ i ] = NULL; | |||
| return sa; | |||
| } | |||
| /* for loggable */ | |||
| static Loggable * | |||
| create ( char **sa ) | |||
| { | |||
| Track_Header *r = new Track_Header( 0, 0, 1, 1 ); | |||
| r->set( sa ); | |||
| return (Loggable *)r; | |||
| } | |||
| void | |||
| draw ( void ) | |||
| { | |||
| if ( _selected ) | |||
| { | |||
| Fl_Color c = color(); | |||
| color( FL_RED ); | |||
| Fl_Group::draw(); | |||
| color( c ); | |||
| } | |||
| else | |||
| Fl_Group::draw(); | |||
| } | |||
| void add_control( Track *t ); | |||
| int size ( void ) const { return _size; } | |||
| void resize ( void ); | |||
| void size ( int v ); | |||
| int height ( void ) const | |||
| { | |||
| static int table[] = { 30, 80, 150, 300 }; | |||
| return table[ _size ]; | |||
| } | |||
| void show_all_takes ( bool b ) | |||
| { | |||
| _show_all_takes = b; | |||
| resize(); | |||
| } | |||
| const char * name ( void ) const { return _name; } | |||
| bool mute ( void ) const { return mute_button->value(); } | |||
| bool solo ( void ) const { return solo_button->value(); } | |||
| bool armed ( void ) const { return record_button->value(); } | |||
| bool selected ( void ) const { return _selected; } | |||
| static void cb_input_field ( Fl_Widget *w, void *v ); | |||
| void cb_input_field ( void ); | |||
| static void cb_button ( Fl_Widget *w, void *v ); | |||
| void cb_button ( Fl_Widget *w ); | |||
| static int width ( void ) { return 150; } | |||
| void track( Track * t ); | |||
| Track * track ( void ) { return _track; } | |||
| void add ( Track * t ) | |||
| { | |||
| takes->insert( *t, 0 ); | |||
| if ( ! t->name() ) | |||
| { | |||
| char pat[20]; | |||
| snprintf( pat, sizeof( pat ), "%d", takes->children() ); | |||
| t->name( strdup( pat ) ); | |||
| take_menu->add( t->name() ); | |||
| } | |||
| } | |||
| void remote ( Track *t ) | |||
| { | |||
| takes->remove( t ); | |||
| // take_menu->remove( t->name() ); | |||
| } | |||
| int handle ( int m ) | |||
| { | |||
| switch ( m ) | |||
| { | |||
| case FL_MOUSEWHEEL: | |||
| { | |||
| if ( ! Fl::event_shift() ) | |||
| return 0; | |||
| int d = Fl::event_dy(); | |||
| printf( "%d\n", d ); | |||
| if ( d < 0 ) | |||
| size( size() - 1 ); | |||
| else | |||
| size( size() + 1 ); | |||
| return 1; | |||
| } | |||
| default: | |||
| return Fl_Group::handle( m ); | |||
| } | |||
| } | |||
| /* Engine */ | |||
| nframes_t process ( nframes_t nframes ); | |||
| void seek ( nframes_t frame ); | |||
| void record ( nframes_t nframes ); | |||
| void write ( sample_t *buf, nframes_t nframes ); | |||
| void stop ( nframes_t nframes ); | |||
| }; | |||
| #endif | |||
| @@ -40,15 +40,15 @@ | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "Track.H" | |||
| #include "Audio_Track.H" | |||
| #include "Sequence.H" | |||
| #include "Audio_Sequence.H" | |||
| #include "Timeline.H" | |||
| #include "Tempo_Track.H" | |||
| #include "Time_Track.H" | |||
| #include "Control_Track.H" | |||
| #include "Tempo_Sequence.H" | |||
| #include "Time_Sequence.H" | |||
| #include "Control_Sequence.H" | |||
| #include "Loggable.H" | |||
| #include "Track_Header.H" | |||
| #include "Track.H" | |||
| // #include "const.h" | |||
| #include "Engine.H" | |||
| @@ -77,7 +77,7 @@ main ( int argc, char **argv ) | |||
| Loggable::register_create( "Tempo_Point", &Tempo_Point::create ); | |||
| Loggable::register_create( "Time_Point", &Time_Point::create ); | |||
| Loggable::register_create( "Control_Point", &Control_Point::create ); | |||
| Loggable::register_create( "Track_Header", &Track_Header::create ); | |||
| Loggable::register_create( "Track", &Track::create ); | |||
| /* TODO: change to seesion dir */ | |||