Timeline: Fix waveform drawing during record and cumulative error in looped region...
[nondaw.git] / timeline / src / Sequence_Widget.H
blob8da354e9bce9bdb3c9461e27c1f314507758241f
2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles                                     */
4 /*                                                                             */
5 /* This program is free software; you can redistribute it and/or modify it     */
6 /* under the terms of the GNU General Public License as published by the       */
7 /* Free Software Foundation; either version 2 of the License, or (at your      */
8 /* option) any later version.                                                  */
9 /*                                                                             */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       */
12 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   */
13 /* more details.                                                               */
14 /*                                                                             */
15 /* You should have received a copy of the GNU General Public License along     */
16 /* with This program; see the file COPYING.  If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18 /*******************************************************************************/
21 #pragma once
23 #include "Sequence.H"
24 #include "Loggable.H"
25 #include "Timeline.H"
26 #include <list>
27 #include <algorithm>
28 using std::min;
29 using std::max;
31 class Sequence_Widget;
33 struct Drag
35     /* mouse coords at offset of drag */
36     int x;
37     int y;
38     int state;
40     nframes_t start;
42     Drag( int X, int Y, nframes_t start=0 ) : x( X ), y( Y ), start( start ) { state = 0; }
45 /* most common position description. /offset/ is only used by Regions,
46    but it's more convenient to have it here  */
47 struct Range
49     nframes_t start;                       /* where on the timeline */
50     nframes_t offset;                      /* first sample from clip */
51     nframes_t length;                      /* total number of samples */
53     void
54     trim_left ( long n )
55         {
56             start -= n;
57             offset -= n;
58             length += n;
59         }
61     void
62     trim_right ( long n )
63         {
64             length += n;
65         }
67     void
68     set_left ( nframes_t f )
69         {
70             offset += f - start;
71             length -= f - start;
72             start = f;
73         }
75     void
76     set_right ( nframes_t f )
77         {
78             length = f - start;
79         }
81     Range ( ) : start( 0 ), offset( 0 ), length( 0 )
82         {
83         }
86 /* Used by time/tempo points or any other child of Sequence_Widget
87    which must be locked to a point in musical time rather than wallclock
88    time. Bar and beat start at 1. */
89 struct BBT
91     unsigned short bar;
92     unsigned char beat;
93     unsigned short tick;
95     BBT ( ) : bar( 0 ), beat( 0 ), tick( 0 )
96         {
97         }
101 /* FIXME: wrong place for this */
102 struct position_info
104     nframes_t frame;
106     float tempo;
107     int beats_per_bar;
108     int beat_type;
110     BBT bbt;
113 #define SEQUENCE_WIDGET_CLONE_FUNC(class)               \
114     virtual Sequence_Widget *clone ( void ) const       \
115     {                                                   \
116         return new class ( *this );                     \
117     }
120 /* Base class for virtual widget on a track */
121 class Sequence_Widget : public Loggable
124     static std::list <Sequence_Widget *> _selection;                    /* all the widgets making up the selection */
126     /* FIXME: is this not the same as /pushed/? */
127     static Sequence_Widget * _current;                             /* the widget initiating events that affect the selection */
129     /* these are actually managed in the Sequence classes */
130     static Sequence_Widget * _pushed;                              /* the widget receiving drag events (a copy) */
131     static Sequence_Widget * _original;                            /* the original of the /pushed/ widget */
132     static Sequence_Widget * _belowmouse;                          /* the widget below the mouse cursor */
135     static Fl_Color _selection_color;
138 protected:
140     Sequence *_sequence;                                              /* track this region belongs to */
142     Range _range;                                               /* range for playback */
143     Range *_r;                                                  /* range for editing / display (points to the same thing as above, except for when dragging etc) */
145     Fl_Color _color;                                            /* color of waveform */
146     Fl_Color _box_color;                                        /* color of background (box) */
148     Drag *_drag;
150     virtual void get ( Log_Entry &e ) const;
151     virtual void set ( Log_Entry &e );
153     Sequence_Widget ( const Sequence_Widget &rhs );
154     Sequence_Widget ( );
156     const Sequence_Widget &
157     operator= ( const Sequence_Widget &rhs );
159 public:
161     virtual ~Sequence_Widget ( );
163     virtual Sequence_Widget *clone ( void ) const = 0;
165     bool selected ( void ) const;
166     static int nselected ( void )
167         { return _selection.size(); }
168     void select ( void );
169     void deselect ( void );
170     void remove ( void );
172     static void delete_selected ( void );
173     static void select_none ( void );
175     static Sequence_Widget *current    ( void ) { return Sequence_Widget::_current; }
176     static Sequence_Widget *pushed     ( void ) { return Sequence_Widget::_pushed; }
177     static Sequence_Widget *belowmouse ( void ) { return Sequence_Widget::_belowmouse; }
179     static void pushed     ( Sequence_Widget *w ) { Sequence_Widget::_pushed     = w; }
180     static void belowmouse ( Sequence_Widget *w ) { Sequence_Widget::_belowmouse = w; }
182     void begin_drag ( const Drag &d );
183     void end_drag ( void );
185     int dispatch ( int m );
187     Fl_Widget * parent ( void ) const { return _sequence; }
189     int scroll_x ( void ) const { return timeline->ts_to_x( timeline->xoffset ); }
190     nframes_t scroll_ts ( void ) const { return timeline->xoffset; }
192     virtual int y ( void ) const { return _sequence->y(); }
193     virtual int h ( void ) const { return _sequence->h(); }
195     /* used by regions */
196     
197     int get_x( nframes_t frame ) const
198         {
199             return  frame < timeline->xoffset ? _sequence->x() : min( _sequence->x() + _sequence->w(), _sequence->x() + timeline->ts_to_x( frame - timeline->xoffset ) );
201         }
203     virtual int x ( void ) const
204         {
205             return get_x( _r->start );
206         }
208     /* use this as x() when you need to draw lines between widgets */
209     int line_x ( void ) const
210         {
211             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 ) );
212         }
214     virtual int w ( void ) const
215         {
216             int tx = timeline->ts_to_x( _r->start );
218             int rw;
219             if ( tx < scroll_x() )
220                 rw = abs_w() - (scroll_x() - tx);
221             else
222                 rw = abs_w();
224             return min( rw, _sequence->w() );
225         }
227     int abs_x ( void ) const { return timeline->ts_to_x( _r->start ); }
228     virtual int abs_w ( void ) const { return timeline->ts_to_x( _r->length ); }
230     Fl_Color color ( void ) const { return _color; }
231     void color ( Fl_Color v ) { _color = v; }
232     Fl_Color box_color ( void ) const { return _box_color; }
233     void box_color ( Fl_Color v ) { _box_color = v; }
234     virtual Fl_Color selection_color ( void ) const { return _selection_color; }
235     virtual void selection_color ( Fl_Color v ) { _selection_color = v; }
237     Sequence * sequence ( void ) const { return _sequence; }
238     void sequence ( Sequence *t ) { _sequence = t; }
240     nframes_t start ( void ) const { return _r->start; }
242 /*     void start ( nframes_t o ) { _r->start = o; } */
244     void start ( nframes_t where );
246     void length ( nframes_t v ) { _r->length = v; }
247     virtual nframes_t length ( void ) const { return _r->length; }
248     void offset ( nframes_t v ) { _r->offset = v; }
249     nframes_t offset ( void ) const { return _r->offset; }
251     /** convert a screen x coord into an start into the region */
252     nframes_t x_to_offset ( int X )
253         {
254             return timeline->x_to_ts( scroll_x() + ( X - _sequence->x() ) ) - _r->start;
255         }
257     int active_r ( void ) const { return _sequence->active_r(); }
259 /** returns true if widget /w/ begins and ends completely within the range of this widget */
260     bool contains ( const Sequence_Widget *w ) const
261         {
262             return w->start() >= start() && w->start() + w->length() <= start() + length();
263         }
265 /** returns true of widget /w/ overlaps this widget in any place */
266     bool overlaps ( const Sequence_Widget *w ) const
267         {
268             return ! ( w->start() > start() + length() || w->start() + w->length() < start() );
269         }
271     virtual Fl_Boxtype box ( void ) const { return FL_UP_BOX; }
272     virtual Fl_Align align ( void ) const { return (Fl_Align)0; }
274     virtual void
275     redraw ( void )
276         {
277             if ( ! _sequence )
278                 return;
280             if ( ! (align() & FL_ALIGN_INSIDE) )
281             {
282                 // FIXME: to better..
283                 _sequence->redraw();
284             }
285             else
286                 _sequence->damage( FL_DAMAGE_ALL, x(), y(), w(), h() );
287         }
289     virtual void draw_box ( void );
290     virtual void draw ( void );
291     virtual void draw_label ( void );
293     bool
294     operator< ( const Sequence_Widget & rhs ) const
295         {
296             return _r->start < rhs._r->start;
297         }
299     bool
300     operator<=( const Sequence_Widget & rhs ) const
301         {
302             return _r->start <= rhs._r->start;
303         }
305     virtual void draw_label ( const char *label, Fl_Align align, Fl_Color color=(Fl_Color)0, int xo=0, int yo=0 );
306     virtual int handle ( int m );
308     static bool
309     sort_func ( const Sequence_Widget *lhs, const Sequence_Widget *rhs )
310         {
311             return *lhs < *rhs;
312         }