Timeline: Implement new cursor system.
This adds new cursor rulers for edit, punch and playback. P1/P2 are now known as the Edit Cursor. Multiple Punch Cursors may be defined. The playback cursor affects Home and End controls. New options are available for looping over the playback cursor (even while recording) and automatically creating new takes at start of recording (or loop). The new cursor objects bump the project file version. Older versions of non-daw will be unable to load new/edited projects.
This commit is contained in:
parent
bcfa3953b1
commit
2f06f509d7
|
@ -30,7 +30,7 @@ class Annotation_Point : public Sequence_Point
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// const char *class_name ( void ) { return "Annotation_Point"; }
|
// const char *class_label ( void ) { return "Annotation_Point"; }
|
||||||
|
|
||||||
virtual void get ( Log_Entry &e ) const
|
virtual void get ( Log_Entry &e ) const
|
||||||
{
|
{
|
||||||
|
@ -51,7 +51,7 @@ protected:
|
||||||
e.get( i, &s, &v );
|
e.get( i, &s, &v );
|
||||||
|
|
||||||
if ( ! strcmp( s, ":label" ) )
|
if ( ! strcmp( s, ":label" ) )
|
||||||
name( v );
|
label( v );
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeline->redraw();
|
// timeline->redraw();
|
||||||
|
@ -67,13 +67,13 @@ public:
|
||||||
LOG_CREATE_FUNC( Annotation_Point );
|
LOG_CREATE_FUNC( Annotation_Point );
|
||||||
SEQUENCE_WIDGET_CLONE_FUNC( Annotation_Point );
|
SEQUENCE_WIDGET_CLONE_FUNC( Annotation_Point );
|
||||||
|
|
||||||
Annotation_Point ( Sequence *sequence, nframes_t when, const char *name )
|
Annotation_Point ( Sequence *sequence, nframes_t when, const char *label )
|
||||||
{
|
{
|
||||||
_sequence = sequence;
|
_sequence = sequence;
|
||||||
|
|
||||||
_r->start = when;
|
_r->start = when;
|
||||||
|
|
||||||
_label = strdup( name );
|
_label = strdup( label );
|
||||||
|
|
||||||
log_create();
|
log_create();
|
||||||
}
|
}
|
||||||
|
@ -96,10 +96,10 @@ public:
|
||||||
|
|
||||||
if ( m == FL_PUSH && Fl::test_shortcut( FL_BUTTON3 ) && ! Fl::event_shift() )
|
if ( m == FL_PUSH && Fl::test_shortcut( FL_BUTTON3 ) && ! Fl::event_shift() )
|
||||||
{
|
{
|
||||||
const char *s = fl_input( "New name for mark:", name() );
|
const char *s = fl_input( "New label for mark:", label() );
|
||||||
|
|
||||||
if ( s )
|
if ( s )
|
||||||
name( s );
|
label( s );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,13 +45,13 @@ Annotation_Region::set ( Log_Entry &e )
|
||||||
e.get( i, &s, &v );
|
e.get( i, &s, &v );
|
||||||
|
|
||||||
if ( ! strcmp( s, ":label" ) )
|
if ( ! strcmp( s, ":label" ) )
|
||||||
name( v );
|
label( v );
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeline->redraw();
|
// timeline->redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
Annotation_Region::Annotation_Region ( Sequence *sequence, nframes_t when, const char *name )
|
Annotation_Region::Annotation_Region ( Sequence *sequence, nframes_t when, const char *label )
|
||||||
{
|
{
|
||||||
_sequence = sequence;
|
_sequence = sequence;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ Annotation_Region::Annotation_Region ( Sequence *sequence, nframes_t when, const
|
||||||
/* FIXME: hack */
|
/* FIXME: hack */
|
||||||
_r->length = 400;
|
_r->length = 400;
|
||||||
|
|
||||||
_label = strdup( name );
|
_label = strdup( label );
|
||||||
|
|
||||||
log_create();
|
log_create();
|
||||||
}
|
}
|
||||||
|
@ -103,10 +103,10 @@ Annotation_Region::handle ( int m )
|
||||||
{
|
{
|
||||||
if ( test_press( FL_BUTTON3 ) )
|
if ( test_press( FL_BUTTON3 ) )
|
||||||
{
|
{
|
||||||
char *s = fl_text_edit( "Annotation text:", "&Save", name() );
|
char *s = fl_text_edit( "Annotation text:", "&Save", label() );
|
||||||
|
|
||||||
if ( s )
|
if ( s )
|
||||||
name( s );
|
label( s );
|
||||||
|
|
||||||
free( s );
|
free( s );
|
||||||
|
|
||||||
|
|
|
@ -30,19 +30,6 @@ class Annotation_Region : public Sequence_Region
|
||||||
/* not permitted */
|
/* not permitted */
|
||||||
Annotation_Region & operator = ( const Annotation_Region &rhs );
|
Annotation_Region & operator = ( const Annotation_Region &rhs );
|
||||||
|
|
||||||
char *_label;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
const char *name ( void ) const { return _label; }
|
|
||||||
void name ( const char *s )
|
|
||||||
{
|
|
||||||
if ( _label )
|
|
||||||
free( _label );
|
|
||||||
_label = strdup( s );
|
|
||||||
redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void get ( Log_Entry &e ) const;
|
virtual void get ( Log_Entry &e ) const;
|
||||||
|
@ -50,7 +37,6 @@ protected:
|
||||||
|
|
||||||
Annotation_Region ( )
|
Annotation_Region ( )
|
||||||
{
|
{
|
||||||
_label = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Annotation_Region ( const Annotation_Region &rhs );
|
Annotation_Region ( const Annotation_Region &rhs );
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2012 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 "Cursor_Point.H"
|
||||||
|
#include "Cursor_Sequence.H"
|
||||||
|
#include "Timeline.H" // for timeline->time_track
|
||||||
|
|
||||||
|
Cursor_Point::Cursor_Point ( )
|
||||||
|
{
|
||||||
|
// timeline->->add( this );
|
||||||
|
_label = NULL;
|
||||||
|
_type = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor_Point::Cursor_Point ( nframes_t when, const char *type, const char *label )
|
||||||
|
{
|
||||||
|
// _make_label();
|
||||||
|
|
||||||
|
_label = NULL;
|
||||||
|
_type = NULL;
|
||||||
|
|
||||||
|
this->label( label );
|
||||||
|
this->type( type );
|
||||||
|
|
||||||
|
timeline->add_cursor( this );
|
||||||
|
|
||||||
|
start( when );
|
||||||
|
|
||||||
|
log_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor_Point::Cursor_Point ( const Cursor_Point &rhs ) : Sequence_Point( rhs )
|
||||||
|
{
|
||||||
|
label( rhs.label() );
|
||||||
|
type( rhs.type() );
|
||||||
|
|
||||||
|
log_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor_Point::~Cursor_Point ( )
|
||||||
|
{
|
||||||
|
// sequence()->remove( this );
|
||||||
|
|
||||||
|
log_destroy();
|
||||||
|
|
||||||
|
label(NULL);
|
||||||
|
type(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Point::get ( Log_Entry &e ) const
|
||||||
|
{
|
||||||
|
// Sequence_Point::get( e );
|
||||||
|
|
||||||
|
e.add( ":start", start() );
|
||||||
|
e.add( ":label", label() );
|
||||||
|
e.add( ":type", type() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Point::set ( Log_Entry &e )
|
||||||
|
{
|
||||||
|
|
||||||
|
Sequence_Point::set( e );
|
||||||
|
|
||||||
|
for ( int i = 0; i < e.size(); ++i )
|
||||||
|
{
|
||||||
|
const char *s, *v;
|
||||||
|
|
||||||
|
e.get( i, &s, &v );
|
||||||
|
|
||||||
|
if ( ! strcmp( s, ":label" ) )
|
||||||
|
label( v );
|
||||||
|
else if ( ! strcmp( s, ":type" ))
|
||||||
|
{
|
||||||
|
type( v );
|
||||||
|
|
||||||
|
timeline->add_cursor( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* /\* FIXME: we need to add this to the time track on creation!!! *\/ */
|
||||||
|
/* timeline->time_track->add( this ); */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence()->handle_widget_change( start(), length() );
|
||||||
|
|
||||||
|
// _make_label();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Point::log_children ( void ) const
|
||||||
|
{
|
||||||
|
log_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Cursor_Point::handle ( int m )
|
||||||
|
{
|
||||||
|
Logger log( this );
|
||||||
|
|
||||||
|
/* if ( m == FL_PUSH && Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_CTRL | FL_SHIFT ) ) ) */
|
||||||
|
/* { */
|
||||||
|
|
||||||
|
/* time_sig t = _time; */
|
||||||
|
|
||||||
|
/* edit( &t ); */
|
||||||
|
|
||||||
|
/* time( t.beats_per_bar, t.beat_type ); */
|
||||||
|
|
||||||
|
/* return 0; */
|
||||||
|
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
return Sequence_Point::handle( m );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2012 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 "Sequence_Point.H"
|
||||||
|
|
||||||
|
|
||||||
|
class Cursor_Point : public Sequence_Point
|
||||||
|
{
|
||||||
|
char *_type;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// const char *class_name ( void ) { return "Time_Point"; }
|
||||||
|
|
||||||
|
virtual void get ( Log_Entry &e ) const;
|
||||||
|
void set ( Log_Entry &e );
|
||||||
|
void log_children ( void ) const;
|
||||||
|
|
||||||
|
Cursor_Point ( );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
LOG_CREATE_FUNC( Cursor_Point );
|
||||||
|
SEQUENCE_WIDGET_CLONE_FUNC( Cursor_Point );
|
||||||
|
|
||||||
|
// static bool edit ( time_sig *sig );
|
||||||
|
|
||||||
|
Cursor_Point ( nframes_t when, const char *type, const char *label );
|
||||||
|
Cursor_Point ( const Cursor_Point &rhs );
|
||||||
|
|
||||||
|
~Cursor_Point ( );
|
||||||
|
|
||||||
|
const char * type ( void ) const { return _type; }
|
||||||
|
void type ( const char *v )
|
||||||
|
{
|
||||||
|
if ( _type )
|
||||||
|
free( _type );
|
||||||
|
|
||||||
|
_type = NULL;
|
||||||
|
|
||||||
|
if ( v )
|
||||||
|
_type = strdup( v );
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle ( int m );
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,154 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2012 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 <FL/Fl_Tooltip.H>
|
||||||
|
#include <FL/fl_ask.H>
|
||||||
|
#include <FL/fl_draw.H>
|
||||||
|
|
||||||
|
#include "Cursor_Region.H"
|
||||||
|
#include "Cursor_Sequence.H"
|
||||||
|
#include "Timeline.H"
|
||||||
|
|
||||||
|
Fl_Color Cursor_Region::box_color ( void ) const
|
||||||
|
{
|
||||||
|
return ((Cursor_Sequence*)sequence())->cursor_color();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Cursor_Region::box_color ( Fl_Color c )
|
||||||
|
{
|
||||||
|
((Cursor_Sequence*)sequence())->cursor_color( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Region::get ( Log_Entry &e ) const
|
||||||
|
{
|
||||||
|
// Sequence_Region::get( e );
|
||||||
|
e.add( ":start", start() );
|
||||||
|
e.add( ":length", length() );
|
||||||
|
e.add( ":label", label() );
|
||||||
|
e.add( ":type", type() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Region::set ( Log_Entry &e )
|
||||||
|
{
|
||||||
|
Sequence_Region::set( e );
|
||||||
|
|
||||||
|
for ( int i = 0; i < e.size(); ++i )
|
||||||
|
{
|
||||||
|
const char *s, *v;
|
||||||
|
|
||||||
|
e.get( i, &s, &v );
|
||||||
|
|
||||||
|
if ( ! strcmp( s, ":label" ) )
|
||||||
|
label( v );
|
||||||
|
if ( ! strcmp( s, ":type" ) )
|
||||||
|
{
|
||||||
|
type( v );
|
||||||
|
timeline->add_cursor( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeline->redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor_Region::Cursor_Region ( nframes_t when, nframes_t length, const char *type, const char *label )
|
||||||
|
{
|
||||||
|
_label = NULL;
|
||||||
|
_type = NULL;
|
||||||
|
|
||||||
|
this->label( label );
|
||||||
|
this->type( type );
|
||||||
|
|
||||||
|
timeline->add_cursor( this );
|
||||||
|
|
||||||
|
start( when );
|
||||||
|
|
||||||
|
this->length( length );
|
||||||
|
|
||||||
|
log_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor_Region::Cursor_Region ( const Cursor_Region &rhs ) : Sequence_Region( rhs )
|
||||||
|
{
|
||||||
|
_label = strdup( rhs._label );
|
||||||
|
_type = strdup( rhs._type );
|
||||||
|
|
||||||
|
log_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Cursor_Region::~Cursor_Region ( )
|
||||||
|
{
|
||||||
|
// timeline->cursor_track->remove( this );
|
||||||
|
|
||||||
|
log_destroy();
|
||||||
|
|
||||||
|
label(NULL);
|
||||||
|
type(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Region::draw_box ( void )
|
||||||
|
{
|
||||||
|
Sequence_Region::draw_box();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Region::draw ( void )
|
||||||
|
{
|
||||||
|
draw_label( _label, (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_TOP | FL_ALIGN_CLIP ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "FL/Fl_Text_Edit_Window.H"
|
||||||
|
#include "FL/test_press.H"
|
||||||
|
|
||||||
|
int
|
||||||
|
Cursor_Region::handle ( int m )
|
||||||
|
{
|
||||||
|
Logger _log( this );
|
||||||
|
|
||||||
|
if ( m == FL_PUSH )
|
||||||
|
{
|
||||||
|
if ( test_press( FL_BUTTON3 ) )
|
||||||
|
{
|
||||||
|
char *s = fl_text_edit( "Cursor text:", "&Save", label() );
|
||||||
|
|
||||||
|
if ( s )
|
||||||
|
label( s );
|
||||||
|
|
||||||
|
free( s );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = Sequence_Region::handle( m );
|
||||||
|
|
||||||
|
if ( m == FL_RELEASE )
|
||||||
|
{
|
||||||
|
sequence()->sort();
|
||||||
|
timeline->redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2012 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 "Sequence_Region.H"
|
||||||
|
#include "Cursor_Sequence.H"
|
||||||
|
|
||||||
|
class Cursor_Region : public Sequence_Region
|
||||||
|
{
|
||||||
|
/* not permitted */
|
||||||
|
Cursor_Region & operator = ( const Cursor_Region &rhs );
|
||||||
|
|
||||||
|
char *_type;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void get ( Log_Entry &e ) const;
|
||||||
|
virtual void set ( Log_Entry &e );
|
||||||
|
|
||||||
|
Cursor_Region ( )
|
||||||
|
{
|
||||||
|
_label = NULL;
|
||||||
|
_type = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor_Region ( const Cursor_Region &rhs );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual Fl_Color box_color ( void ) const;
|
||||||
|
virtual void box_color ( Fl_Color c );
|
||||||
|
|
||||||
|
/* for loggable */
|
||||||
|
LOG_CREATE_FUNC( Cursor_Region );
|
||||||
|
SEQUENCE_WIDGET_CLONE_FUNC( Cursor_Region );
|
||||||
|
|
||||||
|
Cursor_Region ( nframes_t when, nframes_t length, const char *type, const char *label );
|
||||||
|
virtual ~Cursor_Region ( );
|
||||||
|
|
||||||
|
void draw_box ( void );
|
||||||
|
void draw ( void );
|
||||||
|
int handle ( int m );
|
||||||
|
|
||||||
|
|
||||||
|
const char * type ( void ) const { return _type; }
|
||||||
|
void type ( const char *v )
|
||||||
|
{
|
||||||
|
if ( _type )
|
||||||
|
free( _type );
|
||||||
|
|
||||||
|
_type = NULL;
|
||||||
|
|
||||||
|
if ( v )
|
||||||
|
_type = strdup( v );
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2012 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 "Cursor_Sequence.H"
|
||||||
|
#include "Cursor_Point.H"
|
||||||
|
#include "Timeline.H"
|
||||||
|
|
||||||
|
void
|
||||||
|
Cursor_Sequence::handle_widget_change ( nframes_t start, nframes_t length )
|
||||||
|
{
|
||||||
|
sort();
|
||||||
|
timeline->redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequence_Widget *
|
||||||
|
Cursor_Sequence::active_cursor ( void )
|
||||||
|
{
|
||||||
|
if ( _widgets.size() )
|
||||||
|
return _widgets.front();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Cursor_Sequence::handle ( int m )
|
||||||
|
{
|
||||||
|
int r = Sequence::handle( m );
|
||||||
|
|
||||||
|
if ( r )
|
||||||
|
return r;
|
||||||
|
|
||||||
|
switch ( m )
|
||||||
|
{
|
||||||
|
case FL_PUSH:
|
||||||
|
/* if ( Fl::event_button1() ) */
|
||||||
|
/* { */
|
||||||
|
/* add( new Cursor_Point( timeline->x_to_offset( Fl::event_x() ), "NONE" ) ); */
|
||||||
|
/* timeline->redraw(); */
|
||||||
|
/* return 0; */
|
||||||
|
/* } */
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/* Copyright (C) 2012 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 "Sequence.H"
|
||||||
|
#include "Cursor_Point.H"
|
||||||
|
#include "Cursor_Region.H"
|
||||||
|
|
||||||
|
class Cursor_Sequence : public Sequence
|
||||||
|
{
|
||||||
|
|
||||||
|
Fl_Color _cursor_color;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/* not used */
|
||||||
|
void get ( Log_Entry & ) const { }
|
||||||
|
void set ( Log_Entry & ) { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Sequence_Widget *active_cursor ( void );
|
||||||
|
|
||||||
|
Fl_Color cursor_color ( void ) const { return _cursor_color; }
|
||||||
|
void cursor_color ( Fl_Color c ) { _cursor_color = c; }
|
||||||
|
|
||||||
|
Fl_Cursor cursor ( void ) const { return FL_CURSOR_DEFAULT; }
|
||||||
|
|
||||||
|
Cursor_Sequence ( int X, int Y, int W, int H ) : Sequence ( X, Y, W, H )
|
||||||
|
{
|
||||||
|
_cursor_color = FL_CYAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handle_widget_change ( nframes_t start, nframes_t length );
|
||||||
|
int handle ( int m );
|
||||||
|
};
|
|
@ -26,6 +26,7 @@
|
||||||
#include "Playback_DS.H"
|
#include "Playback_DS.H"
|
||||||
|
|
||||||
#include "Thread.H"
|
#include "Thread.H"
|
||||||
|
#include "../Cursor_Sequence.H"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -34,14 +35,48 @@ bool
|
||||||
Timeline::record ( void )
|
Timeline::record ( void )
|
||||||
{
|
{
|
||||||
/* FIXME: right place for this? */
|
/* FIXME: right place for this? */
|
||||||
|
|
||||||
|
if ( Timeline::automatically_create_takes &&
|
||||||
|
! _created_new_takes )
|
||||||
|
{
|
||||||
|
add_take_for_armed_tracks();
|
||||||
|
_created_new_takes = true;
|
||||||
|
}
|
||||||
|
|
||||||
transport->recording = true;
|
transport->recording = true;
|
||||||
|
|
||||||
|
deactivate();
|
||||||
|
|
||||||
Loggable::block_start();
|
Loggable::block_start();
|
||||||
|
|
||||||
nframes_t frame = transport->frame;
|
nframes_t frame = transport->frame;
|
||||||
|
|
||||||
if ( transport->punch_enabled() && range_start() != range_end() && frame < range_start() )
|
if ( transport->punch_enabled() )
|
||||||
frame = range_start();
|
{
|
||||||
|
const Sequence_Widget *w = punch_cursor_track->next( frame );
|
||||||
|
|
||||||
|
if ( w && w->start() >= frame )
|
||||||
|
{
|
||||||
|
frame = w->start();
|
||||||
|
_punch_out_frame = w->start() + w->length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_punch_in_frame = frame;
|
||||||
|
|
||||||
|
punch_in( frame );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeline::punch_in ( nframes_t frame )
|
||||||
|
{
|
||||||
|
if ( _punched_in )
|
||||||
|
{
|
||||||
|
WARNING( "Programming error. Attempt to punch in twice" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DMESSAGE( "Going to record starting at frame %lu", (unsigned long)frame );
|
DMESSAGE( "Going to record starting at frame %lu", (unsigned long)frame );
|
||||||
|
|
||||||
|
@ -53,20 +88,12 @@ Timeline::record ( void )
|
||||||
t->record_ds->start( frame );
|
t->record_ds->start( frame );
|
||||||
}
|
}
|
||||||
|
|
||||||
deactivate();
|
_punched_in = true;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** stop recording for all armed tracks */
|
|
||||||
void
|
void
|
||||||
Timeline::stop ( void )
|
Timeline::punch_out ( nframes_t frame )
|
||||||
{
|
{
|
||||||
nframes_t frame = transport->frame;
|
|
||||||
|
|
||||||
if ( transport->punch_enabled() && range_start() != range_end() && frame > range_end() )
|
|
||||||
frame = range_end();
|
|
||||||
|
|
||||||
for ( int i = tracks->children(); i-- ; )
|
for ( int i = tracks->children(); i-- ; )
|
||||||
{
|
{
|
||||||
Track *t = (Track*)tracks->child( i );
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
@ -86,6 +113,27 @@ Timeline::stop ( void )
|
||||||
t->record_ds->shutdown();
|
t->record_ds->shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_punched_in = false;
|
||||||
|
_punch_in_frame = 0;
|
||||||
|
_punch_out_frame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** stop recording for all armed tracks. Does not affect transport. */
|
||||||
|
void
|
||||||
|
Timeline::stop ( void )
|
||||||
|
{
|
||||||
|
nframes_t frame = transport->frame;
|
||||||
|
|
||||||
|
if ( transport->punch_enabled() )
|
||||||
|
{
|
||||||
|
const Sequence_Widget *w = punch_cursor_track->prev( frame );
|
||||||
|
|
||||||
|
if ( w && w->start() + w->length() < frame )
|
||||||
|
frame = w->start() + w->length();
|
||||||
|
}
|
||||||
|
|
||||||
|
punch_out( frame );
|
||||||
|
|
||||||
Loggable::block_end();
|
Loggable::block_end();
|
||||||
|
|
||||||
activate();
|
activate();
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
extern Transport *transport;
|
extern Transport *transport;
|
||||||
extern TLE *tle;
|
extern TLE *tle;
|
||||||
|
|
||||||
const int PROJECT_VERSION = 1;
|
const int PROJECT_VERSION = 2;
|
||||||
|
|
||||||
extern char *instance_name;
|
extern char *instance_name;
|
||||||
|
|
||||||
|
@ -287,9 +287,14 @@ Project::open ( const char *name )
|
||||||
strncmp( created_by, APP_NAME, strlen( APP_NAME ) ) )
|
strncmp( created_by, APP_NAME, strlen( APP_NAME ) ) )
|
||||||
return E_INVALID;
|
return E_INVALID;
|
||||||
|
|
||||||
if ( version != PROJECT_VERSION )
|
if ( version > PROJECT_VERSION )
|
||||||
return E_VERSION;
|
return E_VERSION;
|
||||||
|
|
||||||
|
if ( version < 2 )
|
||||||
|
{
|
||||||
|
/* FIXME: Version 1->2 adds Cursor_Sequence and Cursor_Point to default project... */
|
||||||
|
}
|
||||||
|
|
||||||
/* normally, engine will be NULL after a close or on an initial open,
|
/* normally, engine will be NULL after a close or on an initial open,
|
||||||
but 'new' will have already created it to get the sample rate. */
|
but 'new' will have already created it to get the sample rate. */
|
||||||
if ( ! engine )
|
if ( ! engine )
|
||||||
|
|
|
@ -303,12 +303,20 @@ Sequence::handle ( int m )
|
||||||
case FL_SHORTCUT:
|
case FL_SHORTCUT:
|
||||||
if ( Fl::test_shortcut( FL_CTRL + FL_Right ) )
|
if ( Fl::test_shortcut( FL_CTRL + FL_Right ) )
|
||||||
{
|
{
|
||||||
transport->locate( next( transport->frame ) );
|
const Sequence_Widget *w = next( transport->frame );
|
||||||
|
|
||||||
|
if ( w )
|
||||||
|
transport->locate( w->start() );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if ( Fl::test_shortcut( FL_CTRL + FL_Left ) )
|
else if ( Fl::test_shortcut( FL_CTRL + FL_Left ) )
|
||||||
{
|
{
|
||||||
transport->locate( prev( transport->frame ) );
|
const Sequence_Widget *w = prev( transport->frame );
|
||||||
|
|
||||||
|
if ( w )
|
||||||
|
transport->locate( w->start() );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if ( Fl::test_shortcut( FL_CTRL + ' ' ) )
|
else if ( Fl::test_shortcut( FL_CTRL + ' ' ) )
|
||||||
|
@ -496,29 +504,29 @@ Sequence::handle ( int m )
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return the location of the next widget from frame /from/ */
|
/** return the location of the next widget from frame /from/ */
|
||||||
nframes_t
|
const Sequence_Widget *
|
||||||
Sequence::next ( nframes_t from ) const
|
Sequence::next ( nframes_t from ) const
|
||||||
{
|
{
|
||||||
for ( list <Sequence_Widget*>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ )
|
for ( list <Sequence_Widget*>::const_iterator i = _widgets.begin(); i != _widgets.end(); i++ )
|
||||||
if ( (*i)->start() > from )
|
if ( (*i)->start() > from )
|
||||||
return (*i)->start();
|
return *i;
|
||||||
|
|
||||||
if ( _widgets.size() )
|
if ( _widgets.size() )
|
||||||
return _widgets.back()->start();
|
return _widgets.back();
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return the location of the next widget from frame /from/ */
|
/** return the location of the next widget from frame /from/ */
|
||||||
nframes_t
|
const Sequence_Widget *
|
||||||
Sequence::prev ( nframes_t from ) const
|
Sequence::prev ( nframes_t from ) const
|
||||||
{
|
{
|
||||||
for ( list <Sequence_Widget*>::const_reverse_iterator i = _widgets.rbegin(); i != _widgets.rend(); i++ )
|
for ( list <Sequence_Widget*>::const_reverse_iterator i = _widgets.rbegin(); i != _widgets.rend(); i++ )
|
||||||
if ( (*i)->start() < from )
|
if ( (*i)->start() < from )
|
||||||
return (*i)->start();
|
return *i;
|
||||||
|
|
||||||
if ( _widgets.size() )
|
if ( _widgets.size() )
|
||||||
return _widgets.front()->start();
|
return _widgets.front();
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,8 +96,8 @@ public:
|
||||||
void sort ( void );
|
void sort ( void );
|
||||||
void clear ( void );
|
void clear ( void );
|
||||||
|
|
||||||
nframes_t next ( nframes_t from ) const;
|
const Sequence_Widget *next ( nframes_t from ) const;
|
||||||
nframes_t prev ( nframes_t from ) const;
|
const Sequence_Widget *prev ( nframes_t from ) const;
|
||||||
|
|
||||||
Track *track ( void ) const { return _track; }
|
Track *track ( void ) const { return _track; }
|
||||||
void track ( Track *t ) { _track = t; }
|
void track ( Track *t ) { _track = t; }
|
||||||
|
|
|
@ -28,8 +28,6 @@ class Sequence_Point : public Sequence_Widget
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
char *_label;
|
|
||||||
|
|
||||||
void get ( Log_Entry &e ) const;
|
void get ( Log_Entry &e ) const;
|
||||||
void set ( Log_Entry &e );
|
void set ( Log_Entry &e );
|
||||||
|
|
||||||
|
@ -43,8 +41,8 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
const char *name ( void ) const { return _label; }
|
const char *label ( void ) const { return _label; }
|
||||||
void name ( const char *s )
|
void label ( const char *s )
|
||||||
{
|
{
|
||||||
if ( _label )
|
if ( _label )
|
||||||
free( _label );
|
free( _label );
|
||||||
|
|
|
@ -248,6 +248,7 @@ void
|
||||||
Sequence_Region::draw_box ( void )
|
Sequence_Region::draw_box ( void )
|
||||||
{
|
{
|
||||||
Fl_Color c = selected() ? selection_color() : box_color();
|
Fl_Color c = selected() ? selection_color() : box_color();
|
||||||
|
|
||||||
fl_draw_box( box(), line_x(), y(), abs_w(), h(), fl_color_add_alpha( c, 127 ) );
|
fl_draw_box( box(), line_x(), y(), abs_w(), h(), fl_color_add_alpha( c, 127 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ Fl_Color Sequence_Widget::_selection_color = FL_MAGENTA;
|
||||||
|
|
||||||
Sequence_Widget::Sequence_Widget ( )
|
Sequence_Widget::Sequence_Widget ( )
|
||||||
{
|
{
|
||||||
|
_label = 0;
|
||||||
_sequence = NULL;
|
_sequence = NULL;
|
||||||
|
|
||||||
_r = &_range;
|
_r = &_range;
|
||||||
|
@ -56,6 +57,9 @@ Sequence_Widget::Sequence_Widget ( const Sequence_Widget &rhs ) : Loggable( rhs
|
||||||
{
|
{
|
||||||
_drag = NULL;
|
_drag = NULL;
|
||||||
|
|
||||||
|
if ( rhs._label )
|
||||||
|
_label = strdup( rhs._label );
|
||||||
|
|
||||||
_sequence = rhs._sequence;
|
_sequence = rhs._sequence;
|
||||||
|
|
||||||
_range = rhs._range;
|
_range = rhs._range;
|
||||||
|
@ -77,6 +81,9 @@ Sequence_Widget::operator= ( const Sequence_Widget &rhs )
|
||||||
_box_color = rhs._box_color;
|
_box_color = rhs._box_color;
|
||||||
_color = rhs._color;
|
_color = rhs._color;
|
||||||
|
|
||||||
|
if ( rhs._label )
|
||||||
|
_label = strdup( rhs._label );
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +97,8 @@ Sequence_Widget::~Sequence_Widget ( )
|
||||||
if ( this == _belowmouse )
|
if ( this == _belowmouse )
|
||||||
_belowmouse = NULL;
|
_belowmouse = NULL;
|
||||||
|
|
||||||
|
label( NULL );
|
||||||
|
|
||||||
_sequence->remove( this );
|
_sequence->remove( this );
|
||||||
|
|
||||||
_selection.remove( this );
|
_selection.remove( this );
|
||||||
|
|
|
@ -137,6 +137,8 @@ class Sequence_Widget : public Loggable
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
char *_label;
|
||||||
|
|
||||||
Sequence *_sequence; /* track this region belongs to */
|
Sequence *_sequence; /* track this region belongs to */
|
||||||
|
|
||||||
Range _range; /* range for playback */
|
Range _range; /* range for playback */
|
||||||
|
@ -208,7 +210,7 @@ public:
|
||||||
/* use this as x() when you need to draw lines between widgets */
|
/* use this as x() when you need to draw lines between widgets */
|
||||||
int line_x ( void ) const
|
int line_x ( void ) const
|
||||||
{
|
{
|
||||||
return _r->start < timeline->xoffset ? max( -32768, _sequence->x() - timeline->ts_to_x( timeline->xoffset - _r->start )) : min( 32767, _sequence->x() + timeline->ts_to_x( _r->start - timeline->xoffset ) );
|
return _r->start < timeline->xoffset ? max( -32767, _sequence->x() - timeline->ts_to_x( timeline->xoffset - _r->start )) : min( 32767, _sequence->x() + timeline->ts_to_x( _r->start - timeline->xoffset ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int w ( void ) const
|
virtual int w ( void ) const
|
||||||
|
@ -229,8 +231,8 @@ public:
|
||||||
|
|
||||||
Fl_Color color ( void ) const { return _color; }
|
Fl_Color color ( void ) const { return _color; }
|
||||||
void color ( Fl_Color v ) { _color = v; }
|
void color ( Fl_Color v ) { _color = v; }
|
||||||
Fl_Color box_color ( void ) const { return _box_color; }
|
virtual Fl_Color box_color ( void ) const { return _box_color; }
|
||||||
void box_color ( Fl_Color v ) { _box_color = v; }
|
virtual void box_color ( Fl_Color v ) { _box_color = v; }
|
||||||
virtual Fl_Color selection_color ( void ) const { return _selection_color; }
|
virtual Fl_Color selection_color ( void ) const { return _selection_color; }
|
||||||
virtual void selection_color ( Fl_Color v ) { _selection_color = v; }
|
virtual void selection_color ( Fl_Color v ) { _selection_color = v; }
|
||||||
|
|
||||||
|
@ -242,12 +244,28 @@ public:
|
||||||
/* void start ( nframes_t o ) { _r->start = o; } */
|
/* void start ( nframes_t o ) { _r->start = o; } */
|
||||||
|
|
||||||
void start ( nframes_t where );
|
void start ( nframes_t where );
|
||||||
|
|
||||||
void length ( nframes_t v ) { _r->length = v; }
|
void length ( nframes_t v ) { _r->length = v; }
|
||||||
virtual nframes_t length ( void ) const { return _r->length; }
|
virtual nframes_t length ( void ) const { return _r->length; }
|
||||||
void offset ( nframes_t v ) { _r->offset = v; }
|
void offset ( nframes_t v ) { _r->offset = v; }
|
||||||
nframes_t offset ( void ) const { return _r->offset; }
|
nframes_t offset ( void ) const { return _r->offset; }
|
||||||
|
|
||||||
|
void set_left ( nframes_t v ) { _r->set_left( v ); }
|
||||||
|
void set_right ( nframes_t v ) { _r->set_right( v ); }
|
||||||
|
|
||||||
|
const char *label ( void ) const { return _label; }
|
||||||
|
void label ( const char *s )
|
||||||
|
{
|
||||||
|
if ( _label )
|
||||||
|
free( _label );
|
||||||
|
|
||||||
|
_label = NULL;
|
||||||
|
|
||||||
|
if ( s )
|
||||||
|
_label = strdup( s );
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
/** convert a screen x coord into an start into the region */
|
/** convert a screen x coord into an start into the region */
|
||||||
nframes_t x_to_offset ( int X )
|
nframes_t x_to_offset ( int X )
|
||||||
{
|
{
|
||||||
|
|
|
@ -504,6 +504,13 @@ Project::compact();}
|
||||||
timeline->redraw();}
|
timeline->redraw();}
|
||||||
xywh {15 15 40 25} type Toggle value 1
|
xywh {15 15 40 25} type Toggle value 1
|
||||||
}
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Cursor Overlay}
|
||||||
|
callback {Timeline::draw_with_cursor_overlay = menu_picked_value( o );
|
||||||
|
|
||||||
|
timeline->redraw();}
|
||||||
|
xywh {15 14 40 25} type Toggle value 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Submenu {} {
|
Submenu {} {
|
||||||
label {&Waveform} open
|
label {&Waveform} open
|
||||||
|
@ -594,6 +601,16 @@ timeline->redraw();}
|
||||||
callback {transport->stop_disables_record( ((Fl_Menu_*)o)->mvalue()->flags & FL_MENU_VALUE );}
|
callback {transport->stop_disables_record( ((Fl_Menu_*)o)->mvalue()->flags & FL_MENU_VALUE );}
|
||||||
xywh {10 10 40 25} type Toggle value 1
|
xywh {10 10 40 25} type Toggle value 1
|
||||||
}
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {Loop Playback}
|
||||||
|
callback {timeline->loop_playback = ( ((Fl_Menu_*)o)->mvalue()->flags & FL_MENU_VALUE );}
|
||||||
|
xywh {10 10 40 25} type Toggle value 0
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {Automatically Create Takes}
|
||||||
|
callback {timeline->automatically_create_takes = ( ((Fl_Menu_*)o)->mvalue()->flags & FL_MENU_VALUE );}
|
||||||
|
xywh {10 10 40 25} type Toggle value 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "Timeline.H"
|
#include "Timeline.H"
|
||||||
#include "Tempo_Sequence.H"
|
#include "Tempo_Sequence.H"
|
||||||
#include "Time_Sequence.H"
|
#include "Time_Sequence.H"
|
||||||
|
#include "Cursor_Sequence.H"
|
||||||
#include "Audio_Sequence.H"
|
#include "Audio_Sequence.H"
|
||||||
#include "Control_Sequence.H"
|
#include "Control_Sequence.H"
|
||||||
#include "Scalebar.H"
|
#include "Scalebar.H"
|
||||||
|
@ -55,6 +56,8 @@
|
||||||
#include "OSC_Thread.H"
|
#include "OSC_Thread.H"
|
||||||
#include "OSC/Endpoint.H"
|
#include "OSC/Endpoint.H"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <nsm.h>
|
#include <nsm.h>
|
||||||
extern nsm_client_t *nsm;
|
extern nsm_client_t *nsm;
|
||||||
|
|
||||||
|
@ -78,11 +81,14 @@ extern nsm_client_t *nsm;
|
||||||
|
|
||||||
|
|
||||||
bool Timeline::draw_with_measure_lines = true;
|
bool Timeline::draw_with_measure_lines = true;
|
||||||
|
bool Timeline::draw_with_cursor_overlay = true;
|
||||||
Timeline::snap_e Timeline::snap_to = Bars;
|
Timeline::snap_e Timeline::snap_to = Bars;
|
||||||
bool Timeline::snapping_on_hold = false;
|
bool Timeline::snapping_on_hold = false;
|
||||||
bool Timeline::snap_magnetic = true;
|
bool Timeline::snap_magnetic = true;
|
||||||
bool Timeline::follow_playhead = true;
|
bool Timeline::follow_playhead = true;
|
||||||
bool Timeline::center_playhead = true;
|
bool Timeline::center_playhead = true;
|
||||||
|
bool Timeline::loop_playback = false;
|
||||||
|
bool Timeline::automatically_create_takes = false;
|
||||||
|
|
||||||
const float UPDATE_FREQ = 1.0 / 18.0f;
|
const float UPDATE_FREQ = 1.0 / 18.0f;
|
||||||
|
|
||||||
|
@ -138,6 +144,72 @@ draw_full_arrow_symbol ( Fl_Color color )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
nframes_t
|
||||||
|
Timeline::range_start ( void ) const
|
||||||
|
{
|
||||||
|
if ( edit_cursor_track->active_cursor() )
|
||||||
|
return edit_cursor_track->active_cursor()->start();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nframes_t
|
||||||
|
Timeline::range_end ( void ) const
|
||||||
|
{
|
||||||
|
if ( edit_cursor_track->active_cursor() )
|
||||||
|
return edit_cursor_track->active_cursor()->start() + edit_cursor_track->active_cursor()->length();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeline::range_start ( nframes_t n )
|
||||||
|
{
|
||||||
|
if ( ! edit_cursor_track->active_cursor() )
|
||||||
|
new Cursor_Region( 0, 0, "Edit", NULL );
|
||||||
|
|
||||||
|
Logger log( edit_cursor_track->active_cursor() );
|
||||||
|
|
||||||
|
edit_cursor_track->active_cursor()->set_left( n );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeline::range_end ( nframes_t n )
|
||||||
|
{
|
||||||
|
if ( ! edit_cursor_track->active_cursor() )
|
||||||
|
new Cursor_Region( 0, 0, "Edit", NULL );
|
||||||
|
|
||||||
|
Logger log( edit_cursor_track->active_cursor() );
|
||||||
|
|
||||||
|
edit_cursor_track->active_cursor()->set_right( n );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** return first frame of playback (might not be 0) */
|
||||||
|
nframes_t
|
||||||
|
Timeline::playback_home ( void ) const
|
||||||
|
{
|
||||||
|
if ( play_cursor_track->active_cursor() )
|
||||||
|
return play_cursor_track->active_cursor()->start();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** return last frame of playback */
|
||||||
|
nframes_t
|
||||||
|
Timeline::playback_end ( void ) const
|
||||||
|
{
|
||||||
|
if ( play_cursor_track->active_cursor() )
|
||||||
|
return play_cursor_track->active_cursor()->start() + play_cursor_track->active_cursor()->length();
|
||||||
|
else
|
||||||
|
return length();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeline::reset_range ( void )
|
||||||
|
{
|
||||||
|
delete edit_cursor_track->active_cursor();
|
||||||
|
}
|
||||||
|
|
||||||
/** callback used by Loggable class to create a snapshot of system
|
/** callback used by Loggable class to create a snapshot of system
|
||||||
* state. */
|
* state. */
|
||||||
void
|
void
|
||||||
|
@ -145,6 +217,9 @@ Timeline::snapshot ( void )
|
||||||
{
|
{
|
||||||
tempo_track->log_children();
|
tempo_track->log_children();
|
||||||
time_track->log_children();
|
time_track->log_children();
|
||||||
|
edit_cursor_track->log_children();
|
||||||
|
punch_cursor_track->log_children();
|
||||||
|
play_cursor_track->log_children();
|
||||||
|
|
||||||
for ( int i = 0; i < tracks->children(); ++i )
|
for ( int i = 0; i < tracks->children(); ++i )
|
||||||
{
|
{
|
||||||
|
@ -211,15 +286,15 @@ Timeline::menu_cb ( Fl_Widget *w, void *v )
|
||||||
((Timeline*)v)->menu_cb( (Fl_Menu_*)w );
|
((Timeline*)v)->menu_cb( (Fl_Menu_*)w );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ensure that p1 is less than p2 */
|
/** ensure that p1 is less than range_end() */
|
||||||
void
|
void
|
||||||
Timeline::fix_range ( void )
|
Timeline::fix_range ( void )
|
||||||
{
|
{
|
||||||
if ( p1 > p2 )
|
if ( range_start() > range_end() )
|
||||||
{
|
{
|
||||||
nframes_t t = p2;
|
nframes_t t = range_end();
|
||||||
p2 = p1;
|
range_end( range_start() );
|
||||||
p1 = t;
|
range_start( t );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,12 +302,25 @@ Timeline::fix_range ( void )
|
||||||
void
|
void
|
||||||
Timeline::range ( nframes_t start, nframes_t length )
|
Timeline::range ( nframes_t start, nframes_t length )
|
||||||
{
|
{
|
||||||
p1 = start;
|
range_start( start );
|
||||||
p2 = start + length;
|
range_end( start + length );
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** create a new take for every armed track */
|
||||||
|
void
|
||||||
|
Timeline::add_take_for_armed_tracks ( void )
|
||||||
|
{
|
||||||
|
for ( int i = tracks->children(); i-- ; )
|
||||||
|
{
|
||||||
|
Track *t = (Track*)tracks->child( i );
|
||||||
|
|
||||||
|
if ( t->armed() && t->sequence()->_widgets.size() )
|
||||||
|
t->sequence( new Audio_Sequence( t ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Timeline::menu_cb ( Fl_Menu_ *m )
|
Timeline::menu_cb ( Fl_Menu_ *m )
|
||||||
{
|
{
|
||||||
|
@ -245,7 +333,7 @@ Timeline::menu_cb ( Fl_Menu_ *m )
|
||||||
|
|
||||||
DMESSAGE( "%s", picked );
|
DMESSAGE( "%s", picked );
|
||||||
|
|
||||||
if ( ! strcmp( picked, "Add Audio Track" ) )
|
if ( ! strcmp( picked, "Add audio track" ) )
|
||||||
{
|
{
|
||||||
/* FIXME: prompt for I/O config? */
|
/* FIXME: prompt for I/O config? */
|
||||||
|
|
||||||
|
@ -266,28 +354,28 @@ Timeline::menu_cb ( Fl_Menu_ *m )
|
||||||
|
|
||||||
Loggable::block_end();
|
Loggable::block_end();
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "Tempo from range (beat)" ) )
|
else if ( ! strcmp( picked, "Tempo from edit (beat)" ) )
|
||||||
{
|
{
|
||||||
if ( p1 != p2 )
|
if ( range_start() != range_end() )
|
||||||
{
|
{
|
||||||
fix_range();
|
fix_range();
|
||||||
|
|
||||||
beats_per_minute( p1, sample_rate() * 60 / (float)( p2 - p1 ) );
|
beats_per_minute( range_start(), sample_rate() * 60 / (float)( range_end() - range_start() ) );
|
||||||
|
|
||||||
p2 = p1;
|
range_end( range_start() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "Tempo from range (bar)" ) )
|
else if ( ! strcmp( picked, "Tempo from edit (bar)" ) )
|
||||||
{
|
{
|
||||||
if ( p1 != p2 )
|
if ( range_start() != range_end() )
|
||||||
{
|
{
|
||||||
fix_range();
|
fix_range();
|
||||||
|
|
||||||
position_info pi = solve_tempomap( p1 );
|
position_info pi = solve_tempomap( range_start() );
|
||||||
|
|
||||||
beats_per_minute( p1, sample_rate() * 60 / (float)( ( p2 - p1 ) / pi.beats_per_bar ) );
|
beats_per_minute( range_start(), sample_rate() * 60 / (float)( ( range_end() - range_start() ) / pi.beats_per_bar ) );
|
||||||
|
|
||||||
p2 = p1;
|
range_end( range_start() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "Playhead to mouse" ) )
|
else if ( ! strcmp( picked, "Playhead to mouse" ) )
|
||||||
|
@ -299,13 +387,13 @@ Timeline::menu_cb ( Fl_Menu_ *m )
|
||||||
transport->locate( xoffset + x_to_ts( X ) );
|
transport->locate( xoffset + x_to_ts( X ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "P1 to mouse" ) )
|
else if ( ! strcmp( picked, "Edit start to mouse" ) )
|
||||||
{
|
{
|
||||||
int X = Fl::event_x() - Track::width();
|
int X = Fl::event_x() - Track::width();
|
||||||
|
|
||||||
if ( X > 0 )
|
if ( X > 0 )
|
||||||
{
|
{
|
||||||
p1 = xoffset + x_to_ts( X );
|
range_start( xoffset + x_to_ts( X ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
fix_range();
|
fix_range();
|
||||||
|
@ -313,13 +401,13 @@ Timeline::menu_cb ( Fl_Menu_ *m )
|
||||||
/* FIXME: only needs to damage the location of the old cursor! */
|
/* FIXME: only needs to damage the location of the old cursor! */
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "P2 to mouse" ) )
|
else if ( ! strcmp( picked, "Edit end to mouse" ) )
|
||||||
{
|
{
|
||||||
int X = Fl::event_x() - Track::width();
|
int X = Fl::event_x() - Track::width();
|
||||||
|
|
||||||
if ( X > 0 )
|
if ( X > 0 )
|
||||||
{
|
{
|
||||||
p2 = xoffset + x_to_ts( X );
|
range_end( xoffset + x_to_ts( X ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
fix_range();
|
fix_range();
|
||||||
|
@ -355,35 +443,72 @@ Timeline::menu_cb ( Fl_Menu_ *m )
|
||||||
if ( next_line( &f, true ) )
|
if ( next_line( &f, true ) )
|
||||||
transport->locate( f );
|
transport->locate( f );
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "Swap P1 and playhead" ) )
|
else if ( ! strcmp( picked, "Swap edit start and playhead" ) )
|
||||||
{
|
{
|
||||||
nframes_t t = transport->frame;
|
nframes_t t = transport->frame;
|
||||||
|
|
||||||
transport->locate( p1 );
|
transport->locate( range_start() );
|
||||||
|
|
||||||
p1 = t;
|
range_start( t );
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "Swap P2 and playhead" ) )
|
else if ( ! strcmp( picked, "Swap edit end and playhead" ) )
|
||||||
{
|
{
|
||||||
nframes_t t = transport->frame;
|
nframes_t t = transport->frame;
|
||||||
|
|
||||||
transport->locate( p2 );
|
transport->locate( range_end() );
|
||||||
|
|
||||||
p2 = t;
|
range_end( t );
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "P1 to playhead" ) )
|
else if ( ! strcmp( picked, "Edit start to playhead" ) )
|
||||||
{
|
{
|
||||||
p1 = transport->frame;
|
range_start( transport->frame );
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( picked, "P2 to playhead" ) )
|
else if ( ! strcmp( picked, "Edit end to playhead" ) )
|
||||||
{
|
{
|
||||||
p2 = transport->frame;
|
range_end( transport->frame );
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
else if ( ! strcmp( picked, "Punch from edit" ) )
|
||||||
|
{
|
||||||
|
if ( range_start() != range_end() )
|
||||||
|
{
|
||||||
|
Loggable::block_start();
|
||||||
|
|
||||||
|
Cursor_Region *o = new Cursor_Region( range_start(), range_end() - range_start(), "Punch", NULL );
|
||||||
|
reset_range();
|
||||||
|
|
||||||
|
Loggable::block_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
else if ( ! strcmp( picked, "Playback from edit" ) )
|
||||||
|
{
|
||||||
|
if ( range_start() != range_end() )
|
||||||
|
{
|
||||||
|
Loggable::block_start();
|
||||||
|
|
||||||
|
if ( play_cursor_track->active_cursor() )
|
||||||
|
{
|
||||||
|
play_cursor_track->active_cursor()->start( range_start() );
|
||||||
|
play_cursor_track->active_cursor()->set_right( range_end() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Cursor_Region *o = new Cursor_Region( range_start(), range_end() - range_start(), "Playback", NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_range();
|
||||||
|
|
||||||
|
Loggable::block_end();
|
||||||
|
}
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
@ -412,6 +537,14 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
|
||||||
{
|
{
|
||||||
Loggable::snapshot_callback( &Timeline::snapshot, this );
|
Loggable::snapshot_callback( &Timeline::snapshot, this );
|
||||||
|
|
||||||
|
edit_cursor_track = NULL;
|
||||||
|
punch_cursor_track = NULL;
|
||||||
|
play_cursor_track = NULL;
|
||||||
|
|
||||||
|
_created_new_takes = 0;
|
||||||
|
_punched_in = 0;
|
||||||
|
_punch_in_frame = 0;
|
||||||
|
_punch_out_frame = 0;
|
||||||
osc_thread = 0;
|
osc_thread = 0;
|
||||||
_sample_rate = 44100;
|
_sample_rate = 44100;
|
||||||
|
|
||||||
|
@ -425,26 +558,28 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
|
||||||
X = Y = 0;
|
X = Y = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
p1 = p2 = 0;
|
// range_start( range_end( 0 ) );
|
||||||
|
|
||||||
menu = new Fl_Menu_Button( 0, 0, 0, 0, "Timeline" );
|
menu = new Fl_Menu_Button( 0, 0, 0, 0, "Timeline" );
|
||||||
|
|
||||||
/* menu->add( "Add Track", 0, 0, 0 ); */
|
/* menu->add( "Add Track", 0, 0, 0 ); */
|
||||||
|
|
||||||
menu->add( "Add Audio Track", 'a', 0, 0 );
|
menu->add( "Add audio track", 'a', 0, 0 );
|
||||||
menu->add( "Tempo from range (beat)", 't', 0, 0 );
|
menu->add( "Tempo from edit (beat)", 't', 0, 0 );
|
||||||
menu->add( "Tempo from range (bar)", FL_CTRL + 't', 0, 0 );
|
menu->add( "Tempo from edit (bar)", FL_CTRL + 't', 0, 0 );
|
||||||
menu->add( "Playhead to mouse", 'p', 0, 0 );
|
menu->add( "Playhead to mouse", 'p', 0, 0 );
|
||||||
menu->add( "P1 to mouse", '[', 0, 0 );
|
menu->add( "Edit start to mouse", '[', 0, 0 );
|
||||||
menu->add( "P2 to mouse", ']', 0, 0 );
|
menu->add( "Edit end to mouse", ']', 0, 0 );
|
||||||
menu->add( "Playhead left beat", FL_SHIFT + FL_Left, 0, 0 );
|
menu->add( "Playhead left beat", FL_SHIFT + FL_Left, 0, 0 );
|
||||||
menu->add( "Playhead right beat", FL_SHIFT + FL_Right, 0, 0 );
|
menu->add( "Playhead right beat", FL_SHIFT + FL_Right, 0, 0 );
|
||||||
menu->add( "Playhead left bar", FL_CTRL + FL_SHIFT + FL_Left, 0, 0 );
|
menu->add( "Playhead left bar", FL_CTRL + FL_SHIFT + FL_Left, 0, 0 );
|
||||||
menu->add( "Playhead right bar", FL_CTRL + FL_SHIFT + FL_Right, 0, 0 );
|
menu->add( "Playhead right bar", FL_CTRL + FL_SHIFT + FL_Right, 0, 0 );
|
||||||
menu->add( "Swap P1 and playhead", FL_CTRL + FL_SHIFT + '[', 0, 0 );
|
menu->add( "Swap edit start and playhead", FL_CTRL + FL_SHIFT + '[', 0, 0 );
|
||||||
menu->add( "Swap P2 and playhead", FL_CTRL + FL_SHIFT + ']', 0, 0 );
|
menu->add( "Swap edit end and playhead", FL_CTRL + FL_SHIFT + ']', 0, 0 );
|
||||||
menu->add( "P1 to playhead", FL_CTRL + '[', 0, 0 );
|
menu->add( "Edit start to playhead", FL_CTRL + '[', 0, 0 );
|
||||||
menu->add( "P2 to playhead", FL_CTRL + ']', 0, 0 );
|
menu->add( "Edit end to playhead", FL_CTRL + ']', 0, 0 );
|
||||||
|
menu->add( "Punch from edit", FL_CTRL + FL_SHIFT + 'p', 0, 0 );
|
||||||
|
menu->add( "Playback from edit", FL_CTRL + FL_SHIFT + 'l', 0, 0 );
|
||||||
menu->add( "Redraw", FL_CTRL + 'l', 0, 0 );
|
menu->add( "Redraw", FL_CTRL + 'l', 0, 0 );
|
||||||
|
|
||||||
menu_set_callback( const_cast<Fl_Menu_Item*>(menu->menu()), &Timeline::menu_cb, (void*)this );
|
menu_set_callback( const_cast<Fl_Menu_Item*>(menu->menu()), &Timeline::menu_cb, (void*)this );
|
||||||
|
@ -478,10 +613,11 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
|
||||||
o->type( Fl_Pack::VERTICAL );
|
o->type( Fl_Pack::VERTICAL );
|
||||||
|
|
||||||
{
|
{
|
||||||
Tempo_Sequence *o = new Tempo_Sequence( 0, 0, 800, 24 );
|
Tempo_Sequence *o = new Tempo_Sequence( 0, 0, 800, 18 );
|
||||||
|
|
||||||
o->color( fl_gray_ramp( 18 ) );
|
o->color( FL_GRAY );
|
||||||
|
|
||||||
|
o->labelsize( 12 );
|
||||||
o->label( "Tempo" );
|
o->label( "Tempo" );
|
||||||
o->align( FL_ALIGN_LEFT );
|
o->align( FL_ALIGN_LEFT );
|
||||||
|
|
||||||
|
@ -489,16 +625,55 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Time_Sequence *o = new Time_Sequence( 0, 24, 800, 24 );
|
Time_Sequence *o = new Time_Sequence( 0, 24, 800, 18 );
|
||||||
|
|
||||||
o->color( fl_gray_ramp( 16 ) );
|
o->color( fl_lighter( FL_GRAY ) );
|
||||||
|
|
||||||
|
o->labelsize( 12 );
|
||||||
o->label( "Time" );
|
o->label( "Time" );
|
||||||
o->align( FL_ALIGN_LEFT );
|
o->align( FL_ALIGN_LEFT );
|
||||||
|
|
||||||
time_track = o;
|
time_track = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 );
|
||||||
|
|
||||||
|
o->color( FL_GRAY );
|
||||||
|
|
||||||
|
o->labelsize( 12 );
|
||||||
|
o->label( "Edit" );
|
||||||
|
o->align( FL_ALIGN_LEFT );
|
||||||
|
o->cursor_color( FL_YELLOW );
|
||||||
|
|
||||||
|
edit_cursor_track = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 );
|
||||||
|
|
||||||
|
o->color( fl_lighter( FL_GRAY ) );
|
||||||
|
|
||||||
|
o->labelsize( 12 );
|
||||||
|
o->label( "Punch" );
|
||||||
|
o->align( FL_ALIGN_LEFT );
|
||||||
|
o->cursor_color( FL_RED );
|
||||||
|
|
||||||
|
punch_cursor_track = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Cursor_Sequence *o = new Cursor_Sequence( 0, 24, 800, 18 );
|
||||||
|
|
||||||
|
o->color( FL_GRAY );
|
||||||
|
|
||||||
|
o->labelsize( 12 );
|
||||||
|
o->label( "Playback" );
|
||||||
|
o->align( FL_ALIGN_LEFT );
|
||||||
|
o->cursor_color( FL_GREEN );
|
||||||
|
|
||||||
|
play_cursor_track = o;
|
||||||
|
}
|
||||||
|
|
||||||
/* { */
|
/* { */
|
||||||
/* Annotation_Sequence *o = new Annotation_Sequence( 0, 24, 800, 24 ); */
|
/* Annotation_Sequence *o = new Annotation_Sequence( 0, 24, 800, 24 ); */
|
||||||
|
@ -511,8 +686,8 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
|
||||||
/* ruler_track = o; */
|
/* ruler_track = o; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
o->size( o->w(), o->child( 0 )->h() * o->children() );
|
|
||||||
rulers = o;
|
rulers = o;
|
||||||
|
o->size( o->w(), o->child( 0 )->h() * o->children() );
|
||||||
o->end();
|
o->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,6 +1068,8 @@ Timeline::draw_clip ( void * v, int X, int Y, int W, int H )
|
||||||
fl_push_clip( tl->tracks->x(), tl->rulers->y() + tl->rulers->h(), tl->tracks->w(), tl->h() - tl->rulers->h() - tl->hscroll->h() );
|
fl_push_clip( tl->tracks->x(), tl->rulers->y() + tl->rulers->h(), tl->tracks->w(), tl->h() - tl->rulers->h() - tl->hscroll->h() );
|
||||||
tl->draw_child( *tl->tracks );
|
tl->draw_child( *tl->tracks );
|
||||||
|
|
||||||
|
tl->draw_cursors();
|
||||||
|
|
||||||
fl_pop_clip();
|
fl_pop_clip();
|
||||||
|
|
||||||
fl_pop_clip();
|
fl_pop_clip();
|
||||||
|
@ -914,20 +1091,83 @@ Timeline::resize ( int X, int Y, int W, int H )
|
||||||
tracks->resize( BX, BY + rulers->h(), W - vscroll->w(), H - vscroll->h() );
|
tracks->resize( BX, BY + rulers->h(), W - vscroll->w(), H - vscroll->h() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeline::add_cursor ( Cursor_Region *o )
|
||||||
|
{
|
||||||
|
if ( !strcmp( o->type(), "Edit" ) )
|
||||||
|
{
|
||||||
|
DMESSAGE( "Adding cursor to edit track" );
|
||||||
|
edit_cursor_track->add( o );
|
||||||
|
}
|
||||||
|
else if ( !strcmp( o->type(), "Punch" ) )
|
||||||
|
{
|
||||||
|
DMESSAGE( "Adding cursor to punch track" );
|
||||||
|
punch_cursor_track->add( o );
|
||||||
|
}
|
||||||
|
else if ( !strcmp( o->type(), "Playback" ) )
|
||||||
|
{
|
||||||
|
DMESSAGE( "Adding cursor to punch track" );
|
||||||
|
play_cursor_track->add( o );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeline::add_cursor ( Cursor_Point *o )
|
||||||
|
{
|
||||||
|
if ( !strcmp( o->type(), "Edit" ) )
|
||||||
|
edit_cursor_track->add( o );
|
||||||
|
else if ( !strcmp( o->type(), "Punch" ) )
|
||||||
|
punch_cursor_track->add( o );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeline::draw_cursors ( Cursor_Sequence *o ) const
|
||||||
|
{
|
||||||
|
fl_push_clip( tracks->x() + Track::width(), rulers->y() + rulers->h(), tracks->w() - Track::width(), h() - rulers->h() - hscroll->h() );
|
||||||
|
|
||||||
|
if ( o && o->_widgets.size() > 0 )
|
||||||
|
{
|
||||||
|
for ( std::list<Sequence_Widget*>::const_iterator i = o->_widgets.begin();
|
||||||
|
i != o->_widgets.end();
|
||||||
|
i++ )
|
||||||
|
{
|
||||||
|
if ( Timeline::draw_with_cursor_overlay )
|
||||||
|
{
|
||||||
|
fl_color( fl_color_add_alpha( (*i)->box_color(), 50 ) );
|
||||||
|
|
||||||
|
fl_rectf( (*i)->line_x(), tracks->y(), (*i)->abs_w(), tracks->h() );
|
||||||
|
}
|
||||||
|
|
||||||
|
fl_color( fl_color_add_alpha( (*i)->box_color(), 127 ));
|
||||||
|
|
||||||
|
fl_line( (*i)->line_x(), tracks->y(), (*i)->line_x(), 9000 );
|
||||||
|
|
||||||
|
fl_line( (*i)->line_x() + (*i)->abs_w(), tracks->y(), (*i)->line_x() + (*i)->abs_w(), tracks->h() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fl_pop_clip();
|
||||||
|
}
|
||||||
|
|
||||||
/** draw ancillary cursors (not necessarily in the overlay plane) */
|
/** draw ancillary cursors (not necessarily in the overlay plane) */
|
||||||
void
|
void
|
||||||
Timeline::draw_cursors ( void ) const
|
Timeline::draw_cursors ( void ) const
|
||||||
{
|
{
|
||||||
if ( p1 != p2 )
|
draw_cursors( edit_cursor_track );
|
||||||
{
|
|
||||||
draw_cursor( p1, FL_BLUE, draw_full_arrow_symbol );
|
if ( transport->punch_enabled() )
|
||||||
draw_cursor( p2, FL_GREEN, draw_full_arrow_symbol );
|
draw_cursors( punch_cursor_track );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Timeline::draw ( void )
|
Timeline::draw ( void )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// resize_rulers();
|
||||||
|
|
||||||
int X, Y, W, H;
|
int X, Y, W, H;
|
||||||
|
|
||||||
int bdx = 0;
|
int bdx = 0;
|
||||||
|
@ -943,7 +1183,7 @@ Timeline::draw ( void )
|
||||||
#ifndef USE_UNOPTIMIZED_DRAWING
|
#ifndef USE_UNOPTIMIZED_DRAWING
|
||||||
if ( ( damage() & FL_DAMAGE_ALL ) )
|
if ( ( damage() & FL_DAMAGE_ALL ) )
|
||||||
#else
|
#else
|
||||||
#warning Optimized drawing of timeline disabled. This will waste your CPU.
|
#warning Optimized drawing of timeline disabled. This will waste your CPU.
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
DMESSAGE( "complete redraw" );
|
DMESSAGE( "complete redraw" );
|
||||||
|
@ -957,12 +1197,13 @@ Timeline::draw ( void )
|
||||||
fl_push_clip( tracks->x(), rulers->y() + rulers->h(), tracks->w(), hscroll->y() - (rulers->y() + rulers->h()) );
|
fl_push_clip( tracks->x(), rulers->y() + rulers->h(), tracks->w(), hscroll->y() - (rulers->y() + rulers->h()) );
|
||||||
draw_child( *tracks );
|
draw_child( *tracks );
|
||||||
|
|
||||||
|
draw_cursors();
|
||||||
|
|
||||||
fl_pop_clip();
|
fl_pop_clip();
|
||||||
|
|
||||||
draw_child( *hscroll );
|
draw_child( *hscroll );
|
||||||
draw_child( *vscroll );
|
draw_child( *vscroll );
|
||||||
|
|
||||||
draw_cursors();
|
|
||||||
|
|
||||||
redraw_overlay();
|
redraw_overlay();
|
||||||
|
|
||||||
|
@ -998,13 +1239,14 @@ Timeline::draw ( void )
|
||||||
{
|
{
|
||||||
fl_push_clip( tracks->x(), rulers->y() + rulers->h(), tracks->w(), h() - rulers->h() - hscroll->h() );
|
fl_push_clip( tracks->x(), rulers->y() + rulers->h(), tracks->w(), h() - rulers->h() - hscroll->h() );
|
||||||
update_child( *tracks );
|
update_child( *tracks );
|
||||||
|
|
||||||
|
draw_cursors();
|
||||||
|
|
||||||
fl_pop_clip();
|
fl_pop_clip();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_child( *hscroll );
|
update_child( *hscroll );
|
||||||
update_child( *vscroll );
|
update_child( *vscroll );
|
||||||
|
|
||||||
draw_cursors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -1063,13 +1305,63 @@ Timeline::redraw_playhead ( void )
|
||||||
static nframes_t last_playhead = -1;
|
static nframes_t last_playhead = -1;
|
||||||
static int last_playhead_x = -1;
|
static int last_playhead_x = -1;
|
||||||
|
|
||||||
|
/* FIXME: kind of a hackish way to invoke punch / looping stuff from the UI thread... */
|
||||||
/* FIXME: kind of a hackish way to invoke punch stop from the UI thread... */
|
|
||||||
|
|
||||||
if ( transport->rolling &&
|
if ( transport->rolling &&
|
||||||
transport->rec_enabled() &&
|
transport->rec_enabled() &&
|
||||||
( ( transport->punch_enabled() && range_start() != range_end() ) && transport->frame > range_end() ) )
|
transport->punch_enabled() )
|
||||||
|
{
|
||||||
|
if ( _punched_in &&
|
||||||
|
transport->frame > _punch_in_frame &&
|
||||||
|
transport->frame > _punch_out_frame )
|
||||||
|
{
|
||||||
|
punch_out( _punch_out_frame );
|
||||||
|
}
|
||||||
|
else if ( ! _punched_in )
|
||||||
|
{
|
||||||
|
/* we've passed one or more punch regions... punch in for the next, if available. */
|
||||||
|
const Sequence_Widget *w = punch_cursor_track->next( transport->frame );
|
||||||
|
|
||||||
|
if ( w &&
|
||||||
|
w->start() > transport->frame )
|
||||||
|
{
|
||||||
|
_punch_in_frame = w->start();
|
||||||
|
_punch_out_frame = w->start() + w->length();
|
||||||
|
|
||||||
|
punch_in( w->start() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( transport->rolling )
|
||||||
|
{
|
||||||
|
if ( play_cursor_track->active_cursor() )
|
||||||
|
{
|
||||||
|
if ( Timeline::loop_playback )
|
||||||
|
{
|
||||||
|
if ( transport->frame > playback_end() )
|
||||||
|
{
|
||||||
|
if ( ! seek_pending() )
|
||||||
|
{
|
||||||
|
if ( transport->recording )
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
transport->locate( playback_home() );
|
||||||
|
record();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transport->locate( playback_home() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ( transport->frame > playback_end() )
|
||||||
transport->stop();
|
transport->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int playhead_x = ts_to_x( transport->frame );
|
int playhead_x = ts_to_x( transport->frame );
|
||||||
|
|
||||||
|
@ -1314,8 +1606,8 @@ Timeline::handle ( int m )
|
||||||
|
|
||||||
if ( range )
|
if ( range )
|
||||||
{
|
{
|
||||||
p1 = x_to_offset( _selection.x );
|
range_start( x_to_offset( _selection.x ) );
|
||||||
p2 = x_to_offset( _selection.x + _selection.w );
|
range_end( x_to_offset( _selection.x + _selection.w ) );
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1331,8 +1623,8 @@ Timeline::handle ( int m )
|
||||||
|
|
||||||
if ( range )
|
if ( range )
|
||||||
{
|
{
|
||||||
p1 = x_to_offset( _selection.x );
|
range_start( x_to_offset( _selection.x ) );
|
||||||
p2 = x_to_offset( _selection.x + _selection.w );
|
range_end( x_to_offset( _selection.x + _selection.w ) );
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -48,10 +48,13 @@ struct BBT;
|
||||||
class Tempo_Sequence;
|
class Tempo_Sequence;
|
||||||
class Time_Sequence;
|
class Time_Sequence;
|
||||||
class Annotation_Sequence;
|
class Annotation_Sequence;
|
||||||
|
class Cursor_Sequence;
|
||||||
class Track;
|
class Track;
|
||||||
class Scalebar;
|
class Scalebar;
|
||||||
class Sequence;
|
class Sequence;
|
||||||
class Sequence_Widget;
|
class Sequence_Widget;
|
||||||
|
class Cursor_Region;
|
||||||
|
class Cursor_Point;
|
||||||
|
|
||||||
namespace OSC { class Endpoint; }
|
namespace OSC { class Endpoint; }
|
||||||
|
|
||||||
|
@ -116,7 +119,7 @@ class Timeline : public Fl_Single_Window, public RWLock
|
||||||
|
|
||||||
int _fpp; /* frames per pixel, power of two */
|
int _fpp; /* frames per pixel, power of two */
|
||||||
|
|
||||||
nframes_t p1, p2; /* cursors */
|
// nframes_t p1, p2; /* cursors */
|
||||||
nframes_t _playhead;
|
nframes_t _playhead;
|
||||||
|
|
||||||
/* not permitted */
|
/* not permitted */
|
||||||
|
@ -147,19 +150,34 @@ public:
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* configuration values */
|
||||||
static bool draw_with_measure_lines;
|
static bool draw_with_measure_lines;
|
||||||
|
static bool draw_with_cursor_overlay;
|
||||||
static snap_e snap_to;
|
static snap_e snap_to;
|
||||||
static bool snapping_on_hold;
|
static bool snapping_on_hold;
|
||||||
static bool snap_magnetic;
|
static bool snap_magnetic;
|
||||||
static bool follow_playhead;
|
static bool follow_playhead;
|
||||||
static bool center_playhead;
|
static bool center_playhead;
|
||||||
|
static bool loop_playback;
|
||||||
|
static bool automatically_create_takes;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Tempo_Sequence *tempo_track;
|
Tempo_Sequence *tempo_track;
|
||||||
Time_Sequence *time_track;
|
Time_Sequence *time_track;
|
||||||
Annotation_Sequence *ruler_track;
|
Annotation_Sequence *ruler_track;
|
||||||
|
Cursor_Sequence *edit_cursor_track;
|
||||||
|
Cursor_Sequence *punch_cursor_track;
|
||||||
|
Cursor_Sequence *play_cursor_track;
|
||||||
|
|
||||||
Fl_Menu_Button *menu;
|
Fl_Menu_Button *menu;
|
||||||
|
|
||||||
|
int _punched_in;
|
||||||
|
nframes_t _punch_out_frame;
|
||||||
|
nframes_t _punch_in_frame;
|
||||||
|
bool _created_new_takes;
|
||||||
|
|
||||||
nframes_t xoffset;
|
nframes_t xoffset;
|
||||||
|
|
||||||
int _yposition;
|
int _yposition;
|
||||||
|
@ -177,8 +195,15 @@ public:
|
||||||
|
|
||||||
nframes_t fpp ( void ) const { return 1 << _fpp; }
|
nframes_t fpp ( void ) const { return 1 << _fpp; }
|
||||||
void range ( nframes_t start, nframes_t length );
|
void range ( nframes_t start, nframes_t length );
|
||||||
nframes_t range_start ( void ) const { return p1; }
|
|
||||||
nframes_t range_end ( void ) const { return p2; }
|
nframes_t range_start ( void ) const;
|
||||||
|
nframes_t range_end ( void ) const;
|
||||||
|
void range_start ( nframes_t n );
|
||||||
|
void range_end ( nframes_t n );
|
||||||
|
void reset_range ( void );
|
||||||
|
nframes_t playback_home ( void ) const;
|
||||||
|
nframes_t playback_end ( void ) const;
|
||||||
|
|
||||||
// nframes_t playhead ( void ) const { return transport->frame; }
|
// nframes_t playhead ( void ) const { return transport->frame; }
|
||||||
nframes_t length ( void ) const;
|
nframes_t length ( void ) const;
|
||||||
void sample_rate ( nframes_t r ) { _sample_rate = r; }
|
void sample_rate ( nframes_t r ) { _sample_rate = r; }
|
||||||
|
@ -205,6 +230,7 @@ public:
|
||||||
void xposition ( int X );
|
void xposition ( int X );
|
||||||
void yposition ( int Y );
|
void yposition ( int Y );
|
||||||
void draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const;
|
void draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const;
|
||||||
|
void draw_cursors ( Cursor_Sequence *o ) const;
|
||||||
void draw_cursors ( void ) const;
|
void draw_cursors ( void ) const;
|
||||||
void draw_playhead ( void );
|
void draw_playhead ( void );
|
||||||
void redraw_playhead ( void );
|
void redraw_playhead ( void );
|
||||||
|
@ -249,6 +275,8 @@ public:
|
||||||
|
|
||||||
bool record ( void );
|
bool record ( void );
|
||||||
void stop ( void );
|
void stop ( void );
|
||||||
|
void punch_in ( nframes_t frame );
|
||||||
|
void punch_out ( nframes_t frame );
|
||||||
|
|
||||||
void wait_for_buffers ( void );
|
void wait_for_buffers ( void );
|
||||||
bool seek_pending ( void );
|
bool seek_pending ( void );
|
||||||
|
@ -274,8 +302,13 @@ public:
|
||||||
|
|
||||||
void reply_to_finger ( lo_message msg );
|
void reply_to_finger ( lo_message msg );
|
||||||
|
|
||||||
|
void add_cursor ( Cursor_Region *o );
|
||||||
|
void add_cursor ( Cursor_Point *o );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void add_take_for_armed_tracks();
|
||||||
|
void resize_rulers ( void );
|
||||||
|
|
||||||
static void snapshot ( void *v ) { ((Timeline*)v)->snapshot(); }
|
static void snapshot ( void *v ) { ((Timeline*)v)->snapshot(); }
|
||||||
void snapshot ( void );
|
void snapshot ( void );
|
||||||
|
|
|
@ -84,7 +84,7 @@ Transport::Transport ( int X, int Y, int W, int H, const char *L )
|
||||||
o->shortcut( 'P' );
|
o->shortcut( 'P' );
|
||||||
o->callback( cb_button, this );
|
o->callback( cb_button, this );
|
||||||
o->when( FL_WHEN_CHANGED );
|
o->when( FL_WHEN_CHANGED );
|
||||||
o->color2( FL_GREEN );
|
o->color2( FL_RED );
|
||||||
o->box( FL_UP_BOX );
|
o->box( FL_UP_BOX );
|
||||||
|
|
||||||
end();
|
end();
|
||||||
|
@ -135,13 +135,15 @@ void
|
||||||
Transport::cb_button ( Fl_Widget *w )
|
Transport::cb_button ( Fl_Widget *w )
|
||||||
{
|
{
|
||||||
if ( w == _home_button )
|
if ( w == _home_button )
|
||||||
locate( 0 );
|
locate( timeline->playback_home() );
|
||||||
else if ( w == _end_button )
|
else if ( w == _end_button )
|
||||||
locate( timeline->length() );
|
locate( timeline->playback_end() );
|
||||||
else if ( w == _play_button )
|
else if ( w == _play_button )
|
||||||
toggle();
|
toggle();
|
||||||
else if ( w == _record_button )
|
else if ( w == _record_button )
|
||||||
update_record_state();
|
update_record_state();
|
||||||
|
else if ( w == _punch_button )
|
||||||
|
timeline->redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -196,8 +198,15 @@ Transport::locate ( nframes_t frame )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( ! recording )
|
if ( ! recording )
|
||||||
|
{
|
||||||
// don't allow seeking while record is in progress
|
// don't allow seeking while record is in progress
|
||||||
engine->transport_locate( frame );
|
engine->transport_locate( frame );
|
||||||
|
|
||||||
|
/* so there isn't a race waiting for the transport to sync */
|
||||||
|
this->frame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline->_created_new_takes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,6 +233,8 @@ Transport::stop ( void )
|
||||||
if ( _stop_disables_record )
|
if ( _stop_disables_record )
|
||||||
_record_button->value( 0 );
|
_record_button->value( 0 );
|
||||||
|
|
||||||
|
timeline->_created_new_takes = false;
|
||||||
|
|
||||||
update_record_state();
|
update_record_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "Time_Sequence.H"
|
#include "Time_Sequence.H"
|
||||||
#include "Annotation_Sequence.H"
|
#include "Annotation_Sequence.H"
|
||||||
#include "Control_Sequence.H"
|
#include "Control_Sequence.H"
|
||||||
|
#include "Cursor_Sequence.H"
|
||||||
#include "Track.H"
|
#include "Track.H"
|
||||||
|
|
||||||
#include "TLE.H"
|
#include "TLE.H"
|
||||||
|
@ -184,6 +185,8 @@ main ( int argc, char **argv )
|
||||||
LOG_REGISTER_CREATE( Control_Sequence );
|
LOG_REGISTER_CREATE( Control_Sequence );
|
||||||
LOG_REGISTER_CREATE( Tempo_Point );
|
LOG_REGISTER_CREATE( Tempo_Point );
|
||||||
LOG_REGISTER_CREATE( Time_Point );
|
LOG_REGISTER_CREATE( Time_Point );
|
||||||
|
LOG_REGISTER_CREATE( Cursor_Point );
|
||||||
|
LOG_REGISTER_CREATE( Cursor_Region );
|
||||||
LOG_REGISTER_CREATE( Track );
|
LOG_REGISTER_CREATE( Track );
|
||||||
|
|
||||||
signal( SIGPIPE, SIG_IGN );
|
signal( SIGPIPE, SIG_IGN );
|
||||||
|
|
Loading…
Reference in New Issue