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.

313 lines
7.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 "../Track.H"
  19. #include "../Transport.H" // for rolling
  20. #include "../Control_Sequence.H"
  21. #include "Playback_DS.H"
  22. #include "Record_DS.H"
  23. #include "Engine.H"
  24. /**********/
  25. /* Engine */
  26. /**********/
  27. const Audio_Region *
  28. Track::capture_region ( void ) const
  29. {
  30. if ( record_ds )
  31. return record_ds->capture_region();
  32. else
  33. return NULL;
  34. }
  35. void
  36. Track::update_port_names ( void )
  37. {
  38. for ( unsigned int i = 0; i < output.size(); ++i )
  39. output[ i ].name( name(), i );
  40. for ( unsigned int i = 0; i < input.size(); ++i )
  41. input[ i ].name( name(), i );
  42. /* /\* tell any attached control sequences to do the same *\/ */
  43. /* for ( int i = control->children(); i-- ) */
  44. /* ((Control_Sequence*)control->child( i ))->update_port_names(); */
  45. }
  46. bool
  47. Track::configure_outputs ( int n )
  48. {
  49. int on = output.size();
  50. if ( n == on )
  51. return true;
  52. // engine->lock();
  53. if ( playback_ds )
  54. {
  55. Playback_DS *ds = playback_ds;
  56. playback_ds = NULL;
  57. delete ds;
  58. }
  59. if ( n > on )
  60. {
  61. for ( int i = on; i < n; ++i )
  62. {
  63. JACK::Port p( engine, JACK::Port::Output, name(), i );
  64. if ( !p.activate() )
  65. {
  66. FATAL( "could not created output port!");
  67. }
  68. if ( p.valid() )
  69. output.push_back( p );
  70. else
  71. WARNING( "could not create output port!" );
  72. }
  73. }
  74. else
  75. {
  76. for ( int i = on; i > n; --i )
  77. {
  78. output.back().shutdown();
  79. output.pop_back();
  80. }
  81. }
  82. if ( output.size() )
  83. playback_ds = new Playback_DS( this, engine->frame_rate(), engine->nframes(), output.size() );
  84. // engine->unlock();
  85. /* FIXME: bogus */
  86. return true;
  87. }
  88. bool
  89. Track::configure_inputs ( int n )
  90. {
  91. int on = input.size();
  92. if ( n == on )
  93. return true;
  94. // engine->lock();
  95. if ( record_ds )
  96. {
  97. Record_DS *ds = record_ds;
  98. record_ds = NULL;
  99. delete ds;
  100. }
  101. if ( n > on )
  102. {
  103. for ( int i = on; i < n; ++i )
  104. {
  105. JACK::Port p( engine, JACK::Port::Input, name(), i );
  106. if ( !p.activate() )
  107. {
  108. FATAL( "could not created output port!");
  109. }
  110. if ( p.valid() )
  111. input.push_back( p );
  112. else
  113. WARNING( "could not create input port!" );
  114. }
  115. }
  116. else
  117. {
  118. for ( int i = on; i > n; --i )
  119. {
  120. input.back().shutdown();
  121. input.pop_back();
  122. }
  123. }
  124. if ( input.size() )
  125. record_ds = new Record_DS( this, engine->frame_rate(), engine->nframes(), input.size() );
  126. // engine->unlock();
  127. /* FIXME: bogus */
  128. return true;
  129. }
  130. nframes_t
  131. Track::process_input ( nframes_t nframes )
  132. {
  133. THREAD_ASSERT( RT );
  134. if ( ! transport->rolling )
  135. {
  136. /* There is no work to do when we're not rolling. */
  137. return 0;
  138. }
  139. if ( record_ds )
  140. return record_ds->process( nframes );
  141. else
  142. return 0;
  143. }
  144. nframes_t
  145. Track::process_output ( nframes_t nframes )
  146. {
  147. THREAD_ASSERT( RT );
  148. if ( ! transport->rolling )
  149. {
  150. for ( int i = output.size(); i--; )
  151. output[ i ].silence( nframes );
  152. return 0;
  153. }
  154. /* FIXME: should we blank the control output here or leave it floating? */
  155. for ( int i = control->children(); i--; )
  156. ((Control_Sequence*)control->child( i ))->process( nframes );
  157. if ( playback_ds )
  158. return playback_ds->process( nframes );
  159. else
  160. return 0;
  161. }
  162. void
  163. Track::seek ( nframes_t frame )
  164. {
  165. THREAD_ASSERT( RT );
  166. if ( playback_ds )
  167. return playback_ds->seek( frame );
  168. }
  169. void
  170. Track::delay ( nframes_t frames )
  171. {
  172. // THREAD_ASSERT( RT );
  173. if ( playback_ds )
  174. playback_ds->delay( frames );
  175. }
  176. /* THREAD: RT (non-RT) */
  177. void
  178. Track::resize_buffers ( nframes_t nframes )
  179. {
  180. if ( record_ds )
  181. record_ds->resize_buffers( nframes );
  182. if ( playback_ds )
  183. playback_ds->resize_buffers( nframes );
  184. }
  185. #include <time.h>
  186. /** very cheap UUID generator... */
  187. unsigned long long
  188. uuid ( void )
  189. {
  190. time_t t = time( NULL );
  191. return (unsigned long long) t;
  192. }
  193. /** create capture region and prepare to record */
  194. void
  195. Track::record ( Capture *c, nframes_t frame )
  196. {
  197. THREAD_ASSERT( Capture );
  198. char pat[256];
  199. snprintf( pat, sizeof( pat ), "%s-%llu", name(), uuid() );
  200. c->audio_file = Audio_File_SF::create( pat, engine->sample_rate(), input.size(), Track::capture_format );
  201. if ( ! c->audio_file )
  202. FATAL( "Could not create file for new capture!" );
  203. /* open it again for reading in the GUI thread */
  204. Audio_File *af = Audio_File::from_file( c->audio_file->name() );
  205. c->region = new Audio_Region( af, sequence(), frame );
  206. c->region->prepare();
  207. }
  208. /** write a block to the (already opened) capture file */
  209. void
  210. Track::write ( Capture *c, sample_t *buf, nframes_t nframes )
  211. {
  212. THREAD_ASSERT( Capture );
  213. nframes_t l = c->audio_file->write( buf, nframes );
  214. c->region->write( l );
  215. }
  216. #include <stdio.h>
  217. void
  218. Track::finalize ( Capture *c, nframes_t frame )
  219. {
  220. THREAD_ASSERT( Capture );
  221. /* adjust region start for latency */
  222. /* FIXME: is just looking at the first channel good enough? */
  223. c->region->finalize( frame );
  224. DMESSAGE( "finalizing audio file" );
  225. c->audio_file->finalize();
  226. nframes_t capture_offset = 0;
  227. /* Add the system latency twice. Once for the input (usually
  228. * required) and again for the output latency of whatever we're
  229. * playing along to (should only apply when overdubbing) */
  230. /* Limitations in the JACK latency reporting API prevent us from
  231. * compensating from any software latency introduced by other
  232. * clients in our graph... Oh well */
  233. capture_offset += engine->system_latency();
  234. capture_offset += engine->system_latency();
  235. DMESSAGE( "Adjusting capture by %lu frames.", (unsigned long)capture_offset );
  236. c->region->offset( capture_offset );
  237. delete c->audio_file;
  238. }