2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles */
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. */
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 */
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 /*******************************************************************************/
29 /* #include <string> */
31 /* using std::string; */
33 sequence::sequence ( void )
36 _name = _notes = NULL;
44 sequence::lock ( void )
46 // create a copy of the lock-free data.
49 data *d = const_cast< data *> (_rd);
51 _rw->phrases = d->phrases;
56 sequence::unlock ( void )
58 _history.push_back( const_cast<data *>( _rd ) );
60 if ( _history.size() > MAX_UNDO + 1 )
62 data *d = _history.front();
64 if ( d == _rw || d == _rd )
65 ASSERTION( "something bad has happend." );
72 // swap the copy back in (atomically).
81 sequence::insert ( unsigned int n, int pn )
85 /* if ( n > _rw->phrases.size() ) */
86 /* _rw->phrases.resize( n + 10 ); */
88 // MESSAGE( "inserting %d at %d", pn, n );
90 _rw->phrases.insert( _find( n ), pn );
96 vector <int>::iterator
97 sequence::_find ( int n )
99 // boy I hate C++/STL.. So lame.
101 for ( vector <int>::iterator e = _rw->phrases.begin(); e != _rw->phrases.end(); e++ )
108 return _rw->phrases.end();
112 sequence::remove ( int n )
116 _rw->phrases.erase( _find( n ) );
122 /** return the number of phrases in this sequence */
124 sequence::phrases ( void ) const
130 sequence::_swap ( int n1, int n2 )
132 int x = _rw->phrases[ n1 ];
133 _rw->phrases[ n1 ] = _rw->phrases[ n2 ];
134 _rw->phrases[ n2 ] = x;
138 sequence::move ( int n, int dir )
152 if ( n + 1 < _rw->num )
162 /* Render sequence to a string.. suitable for display in the UI */
164 sequence::dump ( void )
166 char *s = (char *)malloc( 256 );
171 for ( int i = 0; i < _rd->num; i++ )
177 int x = _rd->phrases[ i ];
179 phrase *p = phrase::phrase_by_number( x );
184 snprintf( line, len, "%d\t%d\t%s\n", start, p->number(), p->name() );
188 s = (char *)realloc( s, siz += strlen( line ) + 1 );
197 sequence::play ( tick_t start, tick_t end ) const
199 // keep our own copy.
203 for ( int i = 0; i < d->num; i++ )
205 phrase *p = phrase::phrase_by_number( d->phrases[ i ] );
208 tick_t pstart = offset;
209 tick_t pend = offset + p->length();
211 // this phrase seems to be current.
212 if ( pend > start && pstart <= end )
214 p->trigger( pstart, pend );
216 _playing = p->number();
220 p->play( start, end );
226 WARNING( "programming error: no such phrase." );
230 /** return the number of the currently playing phrase, or 0 if none. */
232 sequence::playing ( void ) const
237 /** return the location of the playhead for this sequence */
239 sequence::index ( void ) const
244 /** return the total length of the sequence in ticks */
246 sequence::length ( void ) const
250 for ( int i = 0; i < _rd->num; i++ )
252 phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] );
263 /** return to a blank slate */
265 sequence::reset ( void )
267 // MESSAGE( "reseting" );
279 /** load entire sequence from file, replacing everything */
281 sequence::load ( const char *name )
285 if ( ! f.open( name, smf::READ ) )
287 WARNING( "error opening file: %s", strerror( errno ) );
293 if ( f.format() != 2 )
295 WARNING( "not a Non song file" );
301 DMESSAGE( "reading song info" );
310 if ( ! f.read_song_info( &mode, &phrases, &patterns, &sname, ¬es ) )
312 WARNING( "not a Non song file" );
316 song.play_mode = (play_mode_e)mode;
322 this->notes( notes );
327 DMESSAGE( "reading playlist" );
329 // f.read_playlist( this );
334 while ( (s = f.read_cue_point() ) )
338 sscanf( s, "%d:", &n );
340 _rw->phrases.insert( _find( _rw->num++ ), n );
345 DMESSAGE( "reading phrases" );
347 while ( phrases-- && f.next_track() )
349 phrase *p = new phrase;
354 DMESSAGE( "reading patterns" );
356 while ( patterns-- && f.next_track() )
358 pattern *p = new pattern;
370 /** save entire sequence to file */
372 sequence::save ( const char *name ) const
376 /* open for writing */
377 f.open( name, smf::WRITE );
381 DMESSAGE( "saving playlist" );
383 f.open_track( NULL, -1 );
385 DMESSAGE( "saving song info" );
387 f.write_song_info( song.play_mode, phrase::phrases(), pattern::patterns(), this->name(), notes() );
389 for ( int i = 0; i < _rd->num; ++i )
393 phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] );
395 snprintf( pat, 256, "%d: %s", p->number(), p->name() );
397 f.write_meta_event( smf::CUEPOINT, pat );
402 DMESSAGE( "saving phrases" );
404 for ( int i = 0; i < phrase::phrases(); i++ )
406 phrase *p = phrase::phrase_by_number( i + 1 );
411 DMESSAGE( "saving patterns" );
413 for ( int i = 0; i < pattern::patterns(); i++ )
415 pattern *p = pattern::pattern_by_number( i + 1 );
427 sequence::name ( void ) const
433 sequence::name ( const char *s )
435 if ( _name ) free( _name );
443 sequence::notes ( void ) const
449 sequence::notes ( const char *s )
451 if ( _notes ) free( _notes );
453 _notes = strdup( s );