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.

444 lines
8.4KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 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 "sequence.H"
  19. #include "phrase.H"
  20. #include "pattern.H"
  21. #include "smf.H"
  22. #include "non.H"
  23. /* #include <string> */
  24. /* using std::string; */
  25. sequence::sequence ( void )
  26. {
  27. _rd = new data;
  28. _name = _notes = NULL;
  29. _index = 0;
  30. _playing = 0;
  31. }
  32. void
  33. sequence::lock ( void )
  34. {
  35. // create a copy of the lock-free data.
  36. _rw = new data;
  37. data *d = const_cast< data *> (_rd);
  38. _rw->phrases = d->phrases;
  39. _rw->num = d->num;
  40. }
  41. void
  42. sequence::unlock ( void )
  43. {
  44. _history.push_back( const_cast<data *>( _rd ) );
  45. if ( _history.size() > MAX_UNDO + 1 )
  46. {
  47. data *d = _history.front();
  48. if ( d == _rw || d == _rd )
  49. ASSERTION( "something bad has happend." );
  50. delete d;
  51. _history.pop_front();
  52. }
  53. // swap the copy back in (atomically).
  54. _rd = _rw;
  55. _rw = NULL;
  56. }
  57. void
  58. sequence::insert ( unsigned int n, int pn )
  59. {
  60. lock();
  61. /* if ( n > _rw->phrases.size() ) */
  62. /* _rw->phrases.resize( n + 10 ); */
  63. // MESSAGE( "inserting %d at %d", pn, n );
  64. _rw->phrases.insert( _find( n ), pn );
  65. _rw->num++;
  66. unlock();
  67. }
  68. vector <int>::iterator
  69. sequence::_find ( int n )
  70. {
  71. // boy I hate C++/STL.. So lame.
  72. int i = 0;
  73. for ( vector <int>::iterator e = _rw->phrases.begin(); e != _rw->phrases.end(); e++ )
  74. {
  75. if ( i == n )
  76. return e;
  77. i++;
  78. }
  79. return _rw->phrases.end();
  80. }
  81. void
  82. sequence::remove ( int n )
  83. {
  84. lock();
  85. _rw->phrases.erase( _find( n ) );
  86. _rw->num--;
  87. unlock();
  88. }
  89. /** return the number of phrases in this sequence */
  90. int
  91. sequence::phrases ( void ) const
  92. {
  93. return _rd->num;
  94. }
  95. void
  96. sequence::_swap ( int n1, int n2 )
  97. {
  98. int x = _rw->phrases[ n1 ];
  99. _rw->phrases[ n1 ] = _rw->phrases[ n2 ];
  100. _rw->phrases[ n2 ] = x;
  101. }
  102. void
  103. sequence::move ( int n, int dir )
  104. {
  105. lock();
  106. switch ( dir )
  107. {
  108. case UP:
  109. {
  110. if ( n - 1 >= 0 )
  111. _swap( n - 1, n );
  112. break;
  113. }
  114. case DOWN:
  115. {
  116. if ( n + 1 < _rw->num )
  117. _swap( n + 1, n );
  118. break;
  119. }
  120. }
  121. unlock();
  122. }
  123. /* Render sequence to a string.. suitable for display in the UI */
  124. char *
  125. sequence::dump ( void )
  126. {
  127. char *s = (char *)malloc( 256 );
  128. s[0] = '\0';
  129. size_t siz = 256;
  130. int start = 1;
  131. for ( int i = 0; i < _rd->num; i++ )
  132. {
  133. const int len = 256;
  134. char line[len];
  135. int x = _rd->phrases[ i ];
  136. phrase *p = phrase::phrase_by_number( x );
  137. if ( ! p )
  138. return NULL;
  139. snprintf( line, len, "%d\t%d\t%s\n", start, p->number(), p->name() );
  140. start += p->bars();
  141. s = (char *)realloc( s, siz += strlen( line ) + 1 );
  142. strcat( s, line );
  143. }
  144. return s;
  145. }
  146. void
  147. sequence::play ( tick_t start, tick_t end ) const
  148. {
  149. // keep our own copy.
  150. data *d = _rd;
  151. tick_t offset = 0;
  152. for ( int i = 0; i < d->num; i++ )
  153. {
  154. phrase *p = phrase::phrase_by_number( d->phrases[ i ] );
  155. if ( p )
  156. {
  157. tick_t pstart = offset;
  158. tick_t pend = offset + p->length();
  159. // this phrase seems to be current.
  160. if ( pend > start )
  161. {
  162. // FIXME: don't really need to trigger more than once!
  163. _playing = p->number();
  164. _index = start;
  165. p->trigger( pstart, pend );
  166. p->play( start, end );
  167. break;
  168. }
  169. offset = pend;
  170. }
  171. else
  172. WARNING( "programming error: no such phrase." );
  173. }
  174. }
  175. /** return the number of the currently playing phrase, or 0 if none. */
  176. int
  177. sequence::playing ( void ) const
  178. {
  179. return _playing;
  180. }
  181. /** return the location of the playhead for this sequence */
  182. tick_t
  183. sequence::index ( void ) const
  184. {
  185. return _index;
  186. }
  187. /** return the total length of the sequence in ticks */
  188. tick_t
  189. sequence::length ( void ) const
  190. {
  191. tick_t l = 0;
  192. for ( int i = 0; i < _rd->num; i++ )
  193. {
  194. phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] );
  195. if ( ! p )
  196. break;
  197. l += p->length();
  198. }
  199. return l;
  200. }
  201. /** return to a blank slate */
  202. void
  203. sequence::reset ( void )
  204. {
  205. // MESSAGE( "reseting" );
  206. lock();
  207. _rw->num = 0;
  208. phrase::reset();
  209. pattern::reset();
  210. unlock();
  211. }
  212. /** load entire sequence from file, replacing everything */
  213. bool
  214. sequence::load ( const char *name )
  215. {
  216. smf f;
  217. f.open( name, smf::READ );
  218. f.read_header();
  219. if ( f.format() != 2 )
  220. {
  221. WARNING( "not a Non song file" );
  222. return false;
  223. }
  224. f.next_track();
  225. MESSAGE( "reading song info" );
  226. /* read song info */
  227. int mode, phrases, patterns;
  228. char *sname, *notes;
  229. if ( ! f.read_song_info( &mode, &phrases, &patterns, &sname, &notes ) )
  230. {
  231. WARNING( "not a Non song file" );
  232. return false;
  233. }
  234. song.play_mode = (play_mode_e)mode;
  235. if ( sname )
  236. this->name( sname );
  237. if ( notes )
  238. this->notes( notes );
  239. /* tear it down */
  240. reset();
  241. MESSAGE( "reading playlist" );
  242. // f.read_playlist( this );
  243. lock();
  244. char *s;
  245. while ( (s = f.read_cue_point() ) )
  246. {
  247. int n;
  248. sscanf( s, "%d:", &n );
  249. _rw->phrases.insert( _find( _rw->num++ ), n );
  250. }
  251. /* read playlist */
  252. MESSAGE( "reading phrases" );
  253. while ( phrases-- && f.next_track() )
  254. {
  255. phrase *p = new phrase;
  256. p->load( &f );
  257. }
  258. MESSAGE( "reading patterns" );
  259. while ( patterns-- && f.next_track() )
  260. {
  261. pattern *p = new pattern;
  262. p->load( &f );
  263. }
  264. unlock();
  265. signal_new_song();
  266. return true;
  267. }
  268. /** save entire sequence to file */
  269. void
  270. sequence::save ( const char *name ) const
  271. {
  272. smf f;
  273. /* open for writing */
  274. f.open( name, smf::WRITE );
  275. f.write_header( 2 );
  276. MESSAGE( "saving playlist" );
  277. f.open_track( NULL, -1 );
  278. MESSAGE( "saving song info" );
  279. f.write_song_info( song.play_mode, phrase::phrases(), pattern::patterns(), this->name(), notes() );
  280. for ( int i = 0; i < _rd->num; ++i )
  281. {
  282. char pat[256];
  283. phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] );
  284. snprintf( pat, 256, "%d: %s", p->number(), p->name() );
  285. f.write_meta_event( smf::CUEPOINT, pat );
  286. }
  287. f.close_track( 0 );
  288. MESSAGE( "saving phrases" );
  289. for ( int i = 0; i < phrase::phrases(); i++ )
  290. {
  291. phrase *p = phrase::phrase_by_number( i + 1 );
  292. p->dump( &f );
  293. }
  294. MESSAGE( "saving patterns" );
  295. for ( int i = 0; i < pattern::patterns(); i++ )
  296. {
  297. pattern *p = pattern::pattern_by_number( i + 1 );
  298. p->dump( &f );
  299. }
  300. }
  301. /*************/
  302. /* Accessors */
  303. /*************/
  304. char *
  305. sequence::name ( void ) const
  306. {
  307. return _name;
  308. }
  309. void
  310. sequence::name ( const char *s )
  311. {
  312. if ( _name ) free( _name );
  313. _name = strdup( s );
  314. }
  315. char *
  316. sequence::notes ( void ) const
  317. {
  318. return _notes;
  319. }
  320. void
  321. sequence::notes ( const char *s )
  322. {
  323. if ( _notes ) free( _notes );
  324. _notes = strdup( s );
  325. }