@@ -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 */ | |||