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.

302 lines
7.3KB

  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 "Audio_Sequence.H"
  19. #include "Waveform.H"
  20. #include "dsp.h"
  21. #include <Fl/fl_ask.H>
  22. #include "Track.H"
  23. Audio_Sequence::Audio_Sequence ( Track *track ) : Sequence( track )
  24. {
  25. _track = track;
  26. if ( track )
  27. track->add( this );
  28. log_create();
  29. /* FIXME: temporary */
  30. labeltype( FL_NO_LABEL );
  31. }
  32. Audio_Sequence::~Audio_Sequence ( )
  33. {
  34. log_destroy();
  35. }
  36. const Audio_Region *
  37. Audio_Sequence::capture ( void ) const
  38. {
  39. return track()->capture();
  40. }
  41. void
  42. Audio_Sequence::get ( Log_Entry &e ) const
  43. {
  44. e.add( ":track", _track );
  45. e.add( ":name", name() );
  46. }
  47. void
  48. Audio_Sequence::set ( Log_Entry &e )
  49. {
  50. for ( int i = 0; i < e.size(); ++i )
  51. {
  52. const char *s, *v;
  53. e.get( i, &s, &v );
  54. if ( ! strcmp( ":track", s ) )
  55. {
  56. int i;
  57. sscanf( v, "%X", &i );
  58. Track *t = (Track*)Loggable::find( i );
  59. assert( t );
  60. t->sequence( this );
  61. }
  62. else if ( ! strcmp( ":name", s ) )
  63. name( v );
  64. }
  65. }
  66. static
  67. void
  68. deurlify ( char *url )
  69. {
  70. char *r, *w;
  71. r = w = url;
  72. for ( ; *r; r++, w++ )
  73. {
  74. if ( *r == '%' )
  75. {
  76. char data[3] = { *(r + 1), *(r + 2), 0 };
  77. int c;
  78. sscanf( data, "%2X", &c );
  79. *w = c;
  80. r += 2;
  81. }
  82. else
  83. *w = *r;
  84. }
  85. *w = NULL;
  86. }
  87. void
  88. Audio_Sequence::draw ( void )
  89. {
  90. Sequence::draw();
  91. int xfades = 0;
  92. /* draw crossfades */
  93. for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ )
  94. {
  95. Sequence_Widget *o = overlaps( *r );
  96. if ( o )
  97. {
  98. if ( *o <= **r )
  99. {
  100. /* if ( o->x() == (*r)->x() && o->w() == (*r)->w() ) */
  101. /* printf( "complete superposition\n" ); */
  102. if ( (*r)->x() >= o->x() && (*r)->x() + (*r)->w() <= o->x() + o->w() )
  103. /* completely inside */
  104. continue;
  105. ++xfades;
  106. Rectangle b( (*r)->x(),
  107. o->y(),
  108. (o->x() + o->w()) - (*r)->x(),
  109. o->h() );
  110. Fl_Color c = fl_color_average( o->box_color(), (*r)->box_color(), 0.50f );
  111. c = fl_color_average( c, FL_YELLOW, 0.30f );
  112. fl_push_clip( b.x, b.y, b.w, b.h );
  113. draw_box( FL_FLAT_BOX, b.x - 100, b.y, b.w + 200, b.h, c );
  114. draw_box( FL_UP_FRAME, b.x - 100, b.y, b.w + 200, b.h, c );
  115. fl_pop_clip();
  116. }
  117. }
  118. }
  119. for ( list <Sequence_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ )
  120. {
  121. Sequence_Widget *o = overlaps( *r );
  122. if ( o )
  123. {
  124. if ( *o <= **r )
  125. {
  126. if ( (*r)->x() >= o->x() && (*r)->x() + (*r)->w() <= o->x() + o->w() )
  127. /* completely inside */
  128. continue;
  129. Rectangle b( (*r)->x(), o->y(), (o->x() + o->w()) - (*r)->x(), o->h() );
  130. /* draw overlapping waveforms in X-ray style. */
  131. bool t = Waveform::fill;
  132. Waveform::fill = false;
  133. fl_push_clip( b.x, b.y, b.w, b.h );
  134. o->draw();
  135. (*r)->draw();
  136. fl_pop_clip();
  137. Waveform::fill = t;
  138. }
  139. }
  140. }
  141. }
  142. /** event handler that supports DND of audio clips */
  143. int
  144. Audio_Sequence::handle ( int m )
  145. {
  146. switch ( m )
  147. {
  148. case FL_PASTE:
  149. {
  150. const char *text = Fl::event_text();
  151. if ( ! strcmp( text, "Audio_Region" ) )
  152. return 1;
  153. char *file;
  154. if ( ! sscanf( text, "file://%a[^\r\n]\n", &file ) )
  155. {
  156. printf( "invalid drop \"%s\"\n", text );
  157. return 0;
  158. }
  159. deurlify( file );
  160. printf( "pasted file \"%s\"\n", file );
  161. fl_cursor( FL_CURSOR_WAIT );
  162. Fl::check();
  163. Audio_File *c = Audio_File::from_file( file );
  164. fl_cursor( FL_CURSOR_DEFAULT );
  165. if ( ! c )
  166. {
  167. fl_alert( "Could not import file \"%s\": Unsupported file type.", file );
  168. printf( "could not open file\n" );
  169. free( file );
  170. return 0;
  171. }
  172. free( file );
  173. // Audio_Region *r =
  174. new Audio_Region( c, this, timeline->xoffset + timeline->x_to_ts( Fl::event_x() - x() ) );
  175. redraw();
  176. return 1;
  177. }
  178. default:
  179. return Sequence::handle( m );
  180. }
  181. }
  182. /**********/
  183. /* Engine */
  184. /**********/
  185. /* THREAD: IO */
  186. /** determine region coverage and fill /buf/ with interleaved samples
  187. * from /frame/ to /nframes/ for exactly /channels/ channels. */
  188. nframes_t
  189. Audio_Sequence::play ( sample_t *buf, nframes_t frame, nframes_t nframes, int channels )
  190. {
  191. sample_t *cbuf = new sample_t[ nframes ];
  192. memset( cbuf, 0, nframes * sizeof( sample_t ) );
  193. /* quick and dirty--let the regions figure out coverage for themselves */
  194. for ( list <Sequence_Widget *>::const_iterator i = _widgets.begin();
  195. i != _widgets.end(); ++i )
  196. {
  197. const Audio_Region *r = (Audio_Region*)(*i);
  198. for ( int i = channels; i--; )
  199. {
  200. int nfr;
  201. if ( ! ( nfr = r->read( cbuf, frame, nframes, i ) ) )
  202. /* error ? */
  203. continue;
  204. if ( channels == 1 )
  205. buffer_mix( buf, cbuf, nframes );
  206. else
  207. buffer_interleave_one_channel_and_mix( buf, cbuf, i, channels, nframes );
  208. }
  209. }
  210. delete[] cbuf;
  211. /* FIXME: bogus */
  212. return nframes;
  213. }
  214. /* /\* THREAD: RT *\/ */
  215. /* nframes_t */
  216. /* Audio_Sequence::process ( nframes_t nframes ) */
  217. /* { */
  218. /* return disktream->process( nframes ); */
  219. /* } */