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.

456 lines
8.6KB

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