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.

457 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 && pstart <= end )
  163. {
  164. p->trigger( pstart, pend );
  165. _playing = p->number();
  166. _index = start;
  167. p->play( start, end );
  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. if ( ! f.open( name, smf::READ ) )
  218. {
  219. WARNING( "error opening file: %s", strerror( errno ) );
  220. return false;
  221. }
  222. f.read_header();
  223. if ( f.format() != 2 )
  224. {
  225. WARNING( "not a Non song file" );
  226. return false;
  227. }
  228. f.next_track();
  229. DMESSAGE( "reading song info" );
  230. /* read song info */
  231. int mode = PATTERN;
  232. int phrases = 0;
  233. int patterns = 0;
  234. char *sname = NULL;
  235. char *notes = NULL;
  236. if ( ! f.read_song_info( &mode, &phrases, &patterns, &sname, &notes ) )
  237. {
  238. WARNING( "not a Non song file" );
  239. return false;
  240. }
  241. song.play_mode = (play_mode_e)mode;
  242. if ( sname )
  243. this->name( sname );
  244. if ( notes )
  245. this->notes( notes );
  246. /* tear it down */
  247. reset();
  248. DMESSAGE( "reading playlist" );
  249. // f.read_playlist( this );
  250. lock();
  251. char *s;
  252. while ( (s = f.read_cue_point() ) )
  253. {
  254. int n;
  255. sscanf( s, "%d:", &n );
  256. _rw->phrases.insert( _find( _rw->num++ ), n );
  257. }
  258. /* read playlist */
  259. DMESSAGE( "reading phrases" );
  260. while ( phrases-- && f.next_track() )
  261. {
  262. phrase *p = new phrase;
  263. p->load( &f );
  264. }
  265. DMESSAGE( "reading patterns" );
  266. while ( patterns-- && f.next_track() )
  267. {
  268. pattern *p = new pattern;
  269. p->load( &f );
  270. }
  271. unlock();
  272. signal_new_song();
  273. return true;
  274. }
  275. /** save entire sequence to file */
  276. void
  277. sequence::save ( const char *name ) const
  278. {
  279. smf f;
  280. /* open for writing */
  281. f.open( name, smf::WRITE );
  282. f.write_header( 2 );
  283. DMESSAGE( "saving playlist" );
  284. f.open_track( NULL, -1 );
  285. DMESSAGE( "saving song info" );
  286. f.write_song_info( song.play_mode, phrase::phrases(), pattern::patterns(), this->name(), notes() );
  287. for ( int i = 0; i < _rd->num; ++i )
  288. {
  289. char pat[256];
  290. phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] );
  291. snprintf( pat, 256, "%d: %s", p->number(), p->name() );
  292. f.write_meta_event( smf::CUEPOINT, pat );
  293. }
  294. f.close_track( 0 );
  295. DMESSAGE( "saving phrases" );
  296. for ( int i = 0; i < phrase::phrases(); i++ )
  297. {
  298. phrase *p = phrase::phrase_by_number( i + 1 );
  299. p->dump( &f );
  300. }
  301. DMESSAGE( "saving patterns" );
  302. for ( int i = 0; i < pattern::patterns(); i++ )
  303. {
  304. pattern *p = pattern::pattern_by_number( i + 1 );
  305. p->dump( &f );
  306. }
  307. }
  308. /*************/
  309. /* Accessors */
  310. /*************/
  311. char *
  312. sequence::name ( void ) const
  313. {
  314. return _name;
  315. }
  316. void
  317. sequence::name ( const char *s )
  318. {
  319. if ( _name ) free( _name );
  320. _name = strdup( s );
  321. song.set_dirty();
  322. }
  323. char *
  324. sequence::notes ( void ) const
  325. {
  326. return _notes;
  327. }
  328. void
  329. sequence::notes ( const char *s )
  330. {
  331. if ( _notes ) free( _notes );
  332. _notes = strdup( s );
  333. song.set_dirty();
  334. }