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.

280 lines
5.9KB

  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. #include <math.h>
  24. vector <phrase*> phrase::_phrases;
  25. signal <void> phrase::signal_create_destroy;
  26. phrase::phrase ( void )
  27. {
  28. viewport.h = 32;
  29. viewport.w = 32;
  30. _add();
  31. char *s;
  32. asprintf( &s, "Phrase %d", number() );
  33. name( s );
  34. }
  35. phrase::~phrase ( void )
  36. {
  37. DMESSAGE( "deleting phrase %d", number() );
  38. signal_create_destroy();
  39. }
  40. void
  41. phrase::_add ( void )
  42. {
  43. // keep track of all the phrases
  44. phrase::_phrases.push_back( this );
  45. _number = phrases();
  46. signal_create_destroy();
  47. }
  48. /* copy constructor */
  49. phrase::phrase ( const phrase &rhs ) : Grid( rhs )
  50. {
  51. _add();
  52. }
  53. phrase *
  54. phrase::clone ( void )
  55. {
  56. return new phrase( *this );
  57. }
  58. /******************/
  59. /* Static methods */
  60. /******************/
  61. int
  62. phrase::phrases ( void )
  63. {
  64. return phrase::_phrases.size();
  65. }
  66. phrase *
  67. phrase::phrase_by_number ( int n )
  68. {
  69. if ( n <= phrases() && n > 0 )
  70. {
  71. return phrase::_phrases[ n - 1 ];
  72. }
  73. return NULL;
  74. }
  75. void
  76. phrase::reset ( void )
  77. {
  78. for ( int n = phrase::phrases(); n-- ; )
  79. {
  80. delete phrase::_phrases.back();
  81. phrase::_phrases.pop_back();
  82. }
  83. }
  84. /*******************/
  85. /* Virtual Methods */
  86. /*******************/
  87. phrase *
  88. phrase::create ( void )
  89. {
  90. if ( phrase::phrases() < 128 )
  91. {
  92. return new phrase;
  93. }
  94. else
  95. return NULL;
  96. }
  97. phrase *
  98. phrase::by_number ( int n ) const
  99. {
  100. return phrase::phrase_by_number( n );
  101. }
  102. void
  103. phrase::put ( int x, int y, tick_t l )
  104. {
  105. // FIXME: fix insertion length to the length of the pattern
  106. // referred to by this row.
  107. l = 4;
  108. // FIXME: use translation here.
  109. pattern *p = pattern::pattern_by_number( y + 1 );
  110. if ( ! p )
  111. return;
  112. l = p->length();
  113. Grid::put( x, y, l );
  114. }
  115. const char *
  116. phrase::row_name ( int r ) const
  117. {
  118. pattern *p = pattern::pattern_by_number( r + 1 );
  119. return p ? p->name() : NULL;
  120. }
  121. void
  122. phrase::draw_row_names ( Canvas *c ) const
  123. {
  124. for ( int y = viewport.h; y--; )
  125. {
  126. pattern *p = pattern::pattern_by_number( y + 1 );
  127. if ( p && p->name() )
  128. c->draw_row_name( y, p->name(), 0 );
  129. }
  130. }
  131. void
  132. phrase::trigger ( tick_t start, tick_t end )
  133. {
  134. _start = start;
  135. _end = end;
  136. }
  137. // FIXME: so much of this is copied from pattern.C, there has
  138. // to be a way to share more of this code.
  139. void
  140. phrase::play ( tick_t start, tick_t end )
  141. {
  142. /* get our own copy of this pointer so UI thread can change it. */
  143. const data *d = const_cast< const data * >(_rd);
  144. if ( start > _end )
  145. {
  146. _playing = false;
  147. return;
  148. }
  149. if ( start < _start )
  150. start = _start;
  151. if ( end > _end )
  152. end = _end;
  153. _playing = true;
  154. // where we are in the absolute time
  155. tick_t tick = start - _start;
  156. int num_played = tick / d->length;
  157. tick_t offset = _start + (d->length * num_played);
  158. _index = fmod( tick, d->length );
  159. if ( _index < end - start )
  160. DMESSAGE( "Triggered phrase %d at tick %lu (ls: %lu, le: %lu, o: %lu)", number(), start, _start, _end, offset );
  161. try_again:
  162. // pattern is empty
  163. if ( d->events.empty() )
  164. goto done;
  165. for ( const event *e = d->events.first(); e; e = e->next() )
  166. {
  167. // MESSAGE( "s[%ld] -> t[%ld] : %ld, len %ld", start, end, e->timestamp(), _length ); // (*e).print();
  168. const tick_t ts = e->timestamp() + offset;
  169. if ( ts >= end )
  170. goto done;
  171. if ( e->is_note_on() )
  172. {
  173. const tick_t tse = offset + e->link()->timestamp();
  174. if ( tse > start )
  175. {
  176. pattern *p = pattern::pattern_by_number( 1 + note_to_y( e->note() ) );
  177. if ( ! p->playing() )
  178. p->trigger( ts, tse );
  179. p->play( start, end );
  180. }
  181. }
  182. }
  183. // ran out of events, but there's still some loop left to play.
  184. offset += d->length;
  185. goto try_again;
  186. MESSAGE( "out of events, resetting to satisfy loop" );
  187. done: ;
  188. }
  189. void
  190. phrase::load ( smf *f )
  191. {
  192. lock();
  193. f->read_phrase_info( this );
  194. tick_t len;
  195. list <midievent> *me = f->read_track_events( &len );
  196. _rw->events = *me;
  197. delete me;
  198. if ( len )
  199. _rw->length = len;
  200. unlock();
  201. }
  202. void
  203. phrase::dump ( smf *f )
  204. {
  205. f->open_track( _name, -1 );
  206. f->write_phrase_info( this );
  207. f->cue( true );
  208. Grid::dump( f, 0 );
  209. f->close_track( length() );
  210. }