Update NTK.
[nondaw.git] / timeline / src / Audio_Sequence.C
blob15316f20cdce77b0a14b06248ffa17a1036838ba
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 /*******************************************************************************/
20 /* An Audio_Sequence is a sequence of Audio_Regions. Takes and 'track
21  * contents' consist of these objects */
23 #include "debug.h"
25 #include <sys/time.h>
26 #include <FL/fl_ask.H>
27 #include <FL/Fl.H>
28 #include "Audio_Sequence.H"
29 #include "Waveform.H"
31 #include <list>
32 using namespace std;
34 #include "Track.H"
36 #include "Engine/Audio_File.H" // for ::from_file()
37 #include "Transport.H" // for locate()
39 #include <errno.h>
41 #include <unistd.h> // for symlink()
43 #include "string_util.h"
47 Audio_Sequence::Audio_Sequence ( Track *track, const char *name ) : Sequence( track )
49     _track = track;
51     if ( name )
52         Audio_Sequence::name( name );
53     else
54     {
55         struct timeval tv;
57         gettimeofday( &tv, NULL );
59         time_t t = tv.tv_sec;
61         char s[40];
63         ctime_r( &t, s );
65         s[ strlen( s ) - 1 ] = 0;
67         Audio_Sequence::name( s );
68     }
70     if ( track )
71         track->add( this );
73     log_create();
75     /* FIXME: temporary  */
76     labeltype( FL_NO_LABEL );
81 Audio_Sequence::~Audio_Sequence ( )
83     Loggable::block_start();
85     clear();
87     log_destroy();
89     track()->remove( this );
91     Loggable::block_end();
96 /** return a pointer to the current capture region for this sequence */
97 const Audio_Region *
98 Audio_Sequence::capture_region ( void ) const
100     return track()->capture_region();
103 void
104 Audio_Sequence::get ( Log_Entry &e ) const
106     e.add( ":track", _track );
107     e.add( ":name", name() );
110 void
111 Audio_Sequence::set ( Log_Entry &e )
113     for ( int i = 0; i < e.size(); ++i )
114     {
115         const char *s, *v;
117         e.get( i, &s, &v );
119         if ( ! strcmp( ":track", s ) )
120         {
121             int i;
122             sscanf( v, "%X", &i );
123             Track *t = (Track*)Loggable::find( i );
125             assert( t );
127             t->sequence( this );
128         }
129         else if ( ! strcmp( ":name", s ) )
130             name( v );
131     }
135 void
136 Audio_Sequence::handle_widget_change ( nframes_t start, nframes_t length )
138     Sequence::handle_widget_change( start, length );
140     /* a region has changed. we may need to rebuffer... */
142     /* trigger rebuffer */
143     /* FIXME: we really only need to rebuffer *this* sequence! */
144     /* FIXME: how does this fit into the selection? */
146     if ( transport->rolling && ( start > transport->frame || start + length > transport->frame ) )
147         transport->locate( transport->frame );
150 void
151 Audio_Sequence::draw ( void )
154     Sequence::draw();
156     int xfades = 0;
158     fl_push_clip( x(), y(), w(), h() );
160     /* draw crossfades */
161     for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin();  r != _widgets.end(); r++ )
162     {
163         Sequence_Widget *o = overlaps( *r );
165         if ( o )
166         {
167             if ( *o <= **r )
168             {
169 /*                 if ( o->x() == (*r)->x() && o->w() == (*r)->w() ) */
170 /*                     printf( "complete superposition\n" ); */
172                 if ( o->contains( *r ) )
173                     /* completely inside */
174                     continue;
176                 ++xfades;
178                 Rectangle b( (*r)->x(),
179                              o->y(),
180                              (o->x() + o->w()) - (*r)->x(),
181                              o->h() );
183                 Fl_Color c = fl_color_add_alpha( FL_YELLOW, 127 );
185                 fl_color( c );
186                 fl_rectf( b.x, b.y, b.w, b.h );
187             }
188         }
190     }
192     fl_pop_clip();
195 /** event handler that supports DND of audio clips */
197 Audio_Sequence::handle ( int m )
199     switch ( m )
200     {
201         case FL_PASTE:
202         {
203             const char *text = Fl::event_text();
205             if ( ! strcmp( text, "Audio_Region" ) )
206                 return 1;
208             char *file;
210             if ( ! sscanf( text, "file://%a[^\r\n]\n", &file ) )
211             {
212                 printf( "invalid drop \"%s\"\n", text );
213                 return 0;
214             }
216             unescape_url( file );
218             printf( "pasted file \"%s\"\n", file );
220             fl_cursor( FL_CURSOR_WAIT );
221             Fl::check();
223             char *t = strdup( file );
225             char *filebase = strdup( basename( t ) );
227             free( t );
229             char *s = 0;
231             int i = 0;
233             for ( ; ; i++ )
234             {
235                 if ( i ) 
236                 {
237                     free( s );
238                     asprintf( &s, "sources/%s-%i", filebase, i );
239                 }
240                 else
241                     asprintf( &s, "sources/%s", filebase );
243                 DMESSAGE( "Symlink %s -> %s", file, s );
244                 if ( symlink( file, s ) == 0 )
245                     break;
246                 
247                 if ( errno != EEXIST )
248                 {
249                     WARNING( "Failed to create symlink: %s", strerror( errno ) );
250                     break;
251                 }
252             }
253             
254             Audio_File *c = Audio_File::from_file( basename( s ) );
256             free( s );
257             free( filebase );
259             fl_cursor( FL_CURSOR_DEFAULT );
260             Fl::check();
262             if ( ! c || c->dummy() )
263             {
264                 fl_alert( "Could not import file \"%s\"", file );
265                 free( file );
267                 if ( c )
268                 {
269                     delete c;
270                     c = NULL;
271                 }
273                 return 0;
274             }
276             free( file );
278 //            Audio_Region *r =
279             new Audio_Region( c, this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ) );
281             redraw();
282             
283             return 1;
284         }
285         default:
286             return Sequence::handle( m );
287     }