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.

450 lines
8.5KB

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