/*******************************************************************************/ /* Copyright (C) 2008 Jonathan Moore Liles */ /* */ /* This program is free software; you can redistribute it and/or modify it */ /* under the terms of the GNU General Public License as published by the */ /* Free Software Foundation; either version 2 of the License, or (at your */ /* option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ /* more details. */ /* */ /* You should have received a copy of the GNU General Public License along */ /* with This program; see the file COPYING. If not,write to the Free Software */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************************/ /* An Audio_Sequence is a sequence of Audio_Regions. Takes and 'track * contents' consist of these objects */ #include "debug.h" #include #include #include #include "Audio_Sequence.H" #include "Waveform.H" #include using namespace std; #include "Track.H" #include "Engine/Audio_File.H" // for ::from_file() #include "Transport.H" // for locate() #include #include // for symlink() #include "string_util.h" Audio_Sequence::Audio_Sequence ( Track *track, const char *name ) : Sequence( track ) { _track = track; if ( name ) Audio_Sequence::name( name ); else { struct timeval tv; gettimeofday( &tv, NULL ); time_t t = tv.tv_sec; char s[40]; ctime_r( &t, s ); s[ strlen( s ) - 1 ] = 0; Audio_Sequence::name( s ); } if ( track ) track->add( this ); log_create(); /* FIXME: temporary */ labeltype( FL_NO_LABEL ); } Audio_Sequence::~Audio_Sequence ( ) { Loggable::block_start(); clear(); log_destroy(); track()->remove( this ); Loggable::block_end(); } /** return a pointer to the current capture region for this sequence */ const Audio_Region * Audio_Sequence::capture_region ( void ) const { return track()->capture_region(); } void Audio_Sequence::get ( Log_Entry &e ) const { e.add( ":track", _track ); e.add( ":name", name() ); } void Audio_Sequence::set ( Log_Entry &e ) { for ( int i = 0; i < e.size(); ++i ) { const char *s, *v; e.get( i, &s, &v ); if ( ! strcmp( ":track", s ) ) { int i; sscanf( v, "%X", &i ); Track *t = (Track*)Loggable::find( i ); assert( t ); t->sequence( this ); } else if ( ! strcmp( ":name", s ) ) name( v ); } } void Audio_Sequence::handle_widget_change ( nframes_t start, nframes_t length ) { Sequence::handle_widget_change( start, length ); /* a region has changed. we may need to rebuffer... */ /* trigger rebuffer */ /* FIXME: we really only need to rebuffer *this* sequence! */ /* FIXME: how does this fit into the selection? */ if ( transport->rolling && ( start > transport->frame || start + length > transport->frame ) ) transport->locate( transport->frame ); } void Audio_Sequence::draw ( void ) { Sequence::draw(); int xfades = 0; fl_push_clip( x(), y(), w(), h() ); /* draw crossfades */ for ( list ::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) { Sequence_Widget *o = overlaps( *r ); if ( o ) { if ( *o <= **r ) { /* if ( o->x() == (*r)->x() && o->w() == (*r)->w() ) */ /* printf( "complete superposition\n" ); */ if ( o->contains( *r ) ) /* completely inside */ continue; ++xfades; Rectangle b( (*r)->x(), o->y(), (o->x() + o->w()) - (*r)->x(), o->h() ); Fl_Color c = fl_color_add_alpha( FL_YELLOW, 127 ); fl_color( c ); fl_rectf( b.x, b.y, b.w, b.h ); } } } fl_pop_clip(); } /** event handler that supports DND of audio clips */ int Audio_Sequence::handle ( int m ) { switch ( m ) { case FL_PASTE: { const char *text = Fl::event_text(); if ( ! strcmp( text, "Audio_Region" ) ) return 1; char *file; if ( ! sscanf( text, "file://%a[^\r\n]\n", &file ) ) { printf( "invalid drop \"%s\"\n", text ); return 0; } unescape_url( file ); printf( "pasted file \"%s\"\n", file ); fl_cursor( FL_CURSOR_WAIT ); Fl::check(); char *t = strdup( file ); char *filebase = strdup( basename( t ) ); free( t ); char *s = 0; int i = 0; for ( ; ; i++ ) { if ( i ) { free( s ); asprintf( &s, "sources/%s-%i", filebase, i ); } else asprintf( &s, "sources/%s", filebase ); DMESSAGE( "Symlink %s -> %s", file, s ); if ( symlink( file, s ) == 0 ) break; if ( errno != EEXIST ) { WARNING( "Failed to create symlink: %s", strerror( errno ) ); break; } } Audio_File *c = Audio_File::from_file( basename( s ) ); free( s ); free( filebase ); fl_cursor( FL_CURSOR_DEFAULT ); Fl::check(); if ( ! c || c->dummy() ) { fl_alert( "Could not import file \"%s\"", file ); free( file ); if ( c ) { delete c; c = NULL; } return 0; } free( file ); // Audio_Region *r = new Audio_Region( c, this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ) ); redraw(); return 1; } default: return Sequence::handle( m ); } }