2 /*******************************************************************************/
3 /* Copyright (C) 2007,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 /*******************************************************************************/
27 vector <phrase*> phrase::_phrases;
28 signal <void> phrase::signal_create_destroy;
30 phrase::phrase ( void )
38 asprintf( &s, "Phrase %d", number() );
45 phrase::~phrase ( void )
47 DMESSAGE( "deleting phrase %d", number() );
48 signal_create_destroy();
54 // keep track of all the phrases
55 phrase::_phrases.push_back( this );
58 signal_create_destroy();
61 /* copy constructor */
62 phrase::phrase ( const phrase &rhs ) : Grid( rhs )
68 phrase::clone ( void )
70 return new phrase( *this );
78 phrase::phrases ( void )
80 return phrase::_phrases.size();
84 phrase::phrase_by_number ( int n )
86 if ( n <= phrases() && n > 0 )
88 return phrase::_phrases[ n - 1 ];
94 phrase::reset ( void )
96 for ( int n = phrase::phrases(); n-- ; )
98 delete phrase::_phrases.back();
99 phrase::_phrases.pop_back();
106 /*******************/
107 /* Virtual Methods */
108 /*******************/
111 phrase::create ( void )
113 if ( phrase::phrases() < 128 )
122 phrase::by_number ( int n ) const
124 return phrase::phrase_by_number( n );
128 phrase::put ( int x, int y, tick_t l )
130 // FIXME: fix insertion length to the length of the pattern
131 // referred to by this row.
135 // FIXME: use translation here.
136 pattern *p = pattern::pattern_by_number( y + 1 );
143 Grid::put( x, y, l );
147 phrase::row_name ( int r ) const
149 pattern *p = pattern::pattern_by_number( r + 1 );
151 return p ? p->name() : NULL;
155 phrase::draw_row_names ( Canvas *c ) const
157 for ( int y = viewport.h; y--; )
159 pattern *p = pattern::pattern_by_number( y + 1 );
161 if ( p && p->name() )
162 c->draw_row_name( y, p->name(), 0 );
168 phrase::trigger ( tick_t start, tick_t end )
174 // FIXME: so much of this is copied from pattern.C, there has
175 // to be a way to share more of this code.
177 phrase::play ( tick_t start, tick_t end )
179 /* get our own copy of this pointer so UI thread can change it. */
180 const data *d = const_cast< const data * >(_rd);
188 if ( start < _start )
196 // where we are in the absolute time
197 tick_t tick = start - _start;
198 int num_played = tick / d->length;
199 tick_t offset = _start + (d->length * num_played);
201 _index = fmod( tick, d->length );
203 if ( _index < end - start )
204 DMESSAGE( "Triggered phrase %d at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), start, _start, _end, offset );
209 if ( d->events.empty() )
212 for ( const event *e = d->events.first(); e; e = e->next() )
214 // MESSAGE( "s[%ld] -> t[%ld] : %ld, len %ld", start, end, e->timestamp(), _length ); // (*e).print();
216 const tick_t ts = e->timestamp() + offset;
221 if ( e->is_note_on() )
223 const tick_t tse = offset + e->link()->timestamp();
227 pattern *p = pattern::pattern_by_number( 1 + note_to_y( e->note() ) );
229 p->trigger( ts, tse );
231 p->play( start, end );
236 // ran out of events, but there's still some loop left to play.
240 MESSAGE( "out of events, resetting to satisfy loop" );
247 phrase::load ( smf *f )
251 f->read_phrase_info( this );
255 list <midievent> *me = f->read_track_events( &len );
267 phrase::dump ( smf *f )
269 f->open_track( _name, -1 );
271 f->write_phrase_info( this );
277 f->close_track( length() );