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.

291 lines
6.2KB

  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. _draw_shape = SQUARE;
  30. _add();
  31. char *s;
  32. asprintf( &s, "Phrase %d", number() );
  33. name( s );
  34. }
  35. phrase::~phrase ( void )
  36. {
  37. MESSAGE( "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. return new phrase;
  91. }
  92. phrase *
  93. phrase::by_number ( int n ) const
  94. {
  95. return phrase::phrase_by_number( n );
  96. }
  97. void
  98. phrase::put ( int x, int y, tick_t l )
  99. {
  100. // FIXME: fix insertion length to the length of the pattern
  101. // referred to by this row.
  102. l = 4;
  103. // FIXME: use translation here.
  104. pattern *p = pattern::pattern_by_number( y + 1 );
  105. if ( ! p )
  106. return;
  107. l = p->length();
  108. Grid::put( x, y, l );
  109. }
  110. const char *
  111. phrase::row_name ( int r ) const
  112. {
  113. pattern *p = pattern::pattern_by_number( r + 1 );
  114. return p ? p->name() : NULL;
  115. }
  116. void
  117. phrase::draw_row_names ( Canvas *c ) const
  118. {
  119. for ( int y = 128; y-- ; )
  120. {
  121. pattern *p = pattern::pattern_by_number( y + 1 );
  122. if ( p && p->name() )
  123. c->draw_row_name( y, p->name(), 0 );
  124. }
  125. }
  126. void
  127. phrase::trigger ( tick_t start, tick_t end )
  128. {
  129. _start = start;
  130. _end = end;
  131. }
  132. // FIXME: so much of this is copied from pattern.C, there has
  133. // to be a way to share more of this code.
  134. void
  135. phrase::play ( tick_t start, tick_t end )
  136. {
  137. /* get our own copy of this pointer so UI thread can change it. */
  138. const data *d = const_cast< const data * >(_rd);
  139. if ( start > _end )
  140. {
  141. WARNING( "attempt to play a phrase that has ended (%lu, %lu)", start, _end );
  142. return;
  143. }
  144. else
  145. if ( start < _start )
  146. // not ready yet
  147. return;
  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. MESSAGE( "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. tick_t ts = e->timestamp() + offset;
  168. if ( ts >= end )
  169. goto done;
  170. if ( ts >= start )
  171. {
  172. event ne = *e;
  173. if ( ne.is_note_on() || ne.is_note_off() )
  174. {
  175. int ev_note = e->note();
  176. // d->mapping.translate( &ne );
  177. pattern *p = pattern::pattern_by_number( 1 + note_to_y( ev_note ) );
  178. if ( p )
  179. {
  180. if ( e->is_note_on() )
  181. {
  182. p->trigger( ts, offset + e->link()->timestamp() );
  183. p->play( ts, end );
  184. }
  185. else
  186. if ( e->is_note_off() )
  187. p->stop();
  188. }
  189. }
  190. }
  191. }
  192. // ran out of events, but there's still some loop left to play.
  193. offset += d->length;
  194. goto try_again;
  195. MESSAGE( "out of events, resetting to satisfy loop" );
  196. done: ;
  197. }
  198. void
  199. phrase::load ( smf *f )
  200. {
  201. lock();
  202. f->read_phrase_info( this );
  203. tick_t len;
  204. list <midievent> *me = f->read_track_events( &len );
  205. _rw->events = *me;
  206. delete me;
  207. if ( len )
  208. _rw->length = len;
  209. unlock();
  210. }
  211. void
  212. phrase::dump ( smf *f )
  213. {
  214. f->open_track( _name, -1 );
  215. f->write_phrase_info( this );
  216. f->cue( true );
  217. Grid::dump( f, 0, false );
  218. f->close_track( length() );
  219. }