Assists music production by grouping standalone programs into sessions. Community version of "Non Session Manager".
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
5.8KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2007,2008 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. #include "phrase.H"
  19. #include "gui/draw.H"
  20. #include "pattern.H"
  21. #include "smf.H"
  22. #include "common.h"
  23. vector <phrase*> phrase::_phrases;
  24. signal <void> phrase::signal_create_destroy;
  25. phrase::phrase ( void )
  26. {
  27. viewport.h = 32;
  28. viewport.w = 32;
  29. _add();
  30. char *s;
  31. asprintf( &s, "Phrase %d", number() );
  32. name( s );
  33. }
  34. phrase::~phrase ( void )
  35. {
  36. DMESSAGE( "deleting phrase %d", number() );
  37. signal_create_destroy();
  38. }
  39. void
  40. phrase::_add ( void )
  41. {
  42. // keep track of all the phrases
  43. phrase::_phrases.push_back( this );
  44. _number = phrases();
  45. signal_create_destroy();
  46. }
  47. /* copy constructor */
  48. phrase::phrase ( const phrase &rhs ) : Grid( rhs )
  49. {
  50. _add();
  51. }
  52. phrase *
  53. phrase::clone ( void )
  54. {
  55. return new phrase( *this );
  56. }
  57. /******************/
  58. /* Static methods */
  59. /******************/
  60. int
  61. phrase::phrases ( void )
  62. {
  63. return phrase::_phrases.size();
  64. }
  65. phrase *
  66. phrase::phrase_by_number ( int n )
  67. {
  68. if ( n <= phrases() && n > 0 )
  69. {
  70. return phrase::_phrases[ n - 1 ];
  71. }
  72. return NULL;
  73. }
  74. void
  75. phrase::reset ( void )
  76. {
  77. for ( int n = phrase::phrases(); n-- ; )
  78. {
  79. delete phrase::_phrases.back();
  80. phrase::_phrases.pop_back();
  81. }
  82. }
  83. /*******************/
  84. /* Virtual Methods */
  85. /*******************/
  86. phrase *
  87. phrase::create ( void )
  88. {
  89. if ( phrase::phrases() < 128 )
  90. {
  91. return new phrase;
  92. }
  93. else
  94. return NULL;
  95. }
  96. phrase *
  97. phrase::by_number ( int n ) const
  98. {
  99. return phrase::phrase_by_number( n );
  100. }
  101. void
  102. phrase::put ( int x, int y, tick_t l )
  103. {
  104. // FIXME: fix insertion length to the length of the pattern
  105. // referred to by this row.
  106. l = 4;
  107. // FIXME: use translation here.
  108. pattern *p = pattern::pattern_by_number( y + 1 );
  109. if ( ! p )
  110. return;
  111. l = p->length();
  112. Grid::put( x, y, l );
  113. }
  114. const char *
  115. phrase::row_name ( int r ) const
  116. {
  117. pattern *p = pattern::pattern_by_number( r + 1 );
  118. return p ? p->name() : NULL;
  119. }
  120. void
  121. phrase::draw_row_names ( Canvas *c ) const
  122. {
  123. for ( int y = viewport.h; y--; )
  124. {
  125. pattern *p = pattern::pattern_by_number( y + 1 );
  126. if ( p && p->name() )
  127. c->draw_row_name( y, p->name(), 0 );
  128. }
  129. }
  130. void
  131. phrase::trigger ( tick_t start, tick_t end )
  132. {
  133. _start = start;
  134. _end = end;
  135. }
  136. // FIXME: so much of this is copied from pattern.C, there has
  137. // to be a way to share more of this code.
  138. void
  139. phrase::play ( tick_t start, tick_t end )
  140. {
  141. /* get our own copy of this pointer so UI thread can change it. */
  142. const data *d = const_cast< const data * >(_rd);
  143. if ( start > _end )
  144. {
  145. _playing = false;
  146. return;
  147. }
  148. if ( start < _start )
  149. start = _start;
  150. if ( end > _end )
  151. end = _end;
  152. _playing = true;
  153. // where we are in the absolute time
  154. tick_t tick = start - _start;
  155. int num_played = tick / d->length;
  156. tick_t offset = _start + (d->length * num_played);
  157. _index = tick % d->length;
  158. if ( _index < end - start )
  159. DMESSAGE( "Triggered phrase %d at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), start, _start, _end, offset );
  160. try_again:
  161. // pattern is empty
  162. if ( d->events.empty() )
  163. goto done;
  164. for ( const event *e = d->events.first(); e; e = e->next() )
  165. {
  166. // MESSAGE( "s[%ld] -> t[%ld] : %ld, len %ld", start, end, e->timestamp(), _length ); // (*e).print();
  167. const tick_t ts = e->timestamp() + offset;
  168. if ( ts >= end )
  169. goto done;
  170. if ( e->is_note_on() )
  171. {
  172. const tick_t tse = offset + e->link()->timestamp();
  173. if ( tse > start )
  174. {
  175. pattern *p = pattern::pattern_by_number( 1 + note_to_y( e->note() ) );
  176. if ( ! p->playing() )
  177. p->trigger( ts, tse );
  178. p->play( start, end );
  179. }
  180. }
  181. }
  182. // ran out of events, but there's still some loop left to play.
  183. offset += d->length;
  184. goto try_again;
  185. MESSAGE( "out of events, resetting to satisfy loop" );
  186. done: ;
  187. }
  188. void
  189. phrase::load ( smf *f )
  190. {
  191. lock();
  192. f->read_phrase_info( this );
  193. tick_t len;
  194. list <midievent> *me = f->read_track_events( &len );
  195. _rw->events = *me;
  196. delete me;
  197. if ( len )
  198. _rw->length = len;
  199. unlock();
  200. }
  201. void
  202. phrase::dump ( smf *f )
  203. {
  204. f->open_track( _name, -1 );
  205. f->write_phrase_info( this );
  206. f->cue( true );
  207. Grid::dump( f, 0 );
  208. f->close_track( length() );
  209. }