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.

238 lines
6.0KB

  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 "Audio_Sequence.H"
  20. class Audio_Sequence;
  21. // #include "Port.H"
  22. #include "Engine.H" // for locking.
  23. #include "Disk_Stream.H"
  24. #include "dsp.h"
  25. /**********/
  26. /* Engine */
  27. /**********/
  28. /* A Disk_Stream uses a separate I/O thread to stream a track's
  29. regions from disk into a ringbuffer to be processed by the RT
  30. thread (or vice-versa). The I/O thread syncronizes access with the
  31. user thread via the Timeline mutex. The size of the buffer (in
  32. seconds) must be set before any Disk_Stream objects are created;
  33. that is, at startup time. The default is 5 seconds, which may or
  34. may not be excessive depending on various external factors. */
  35. /* FIXME: deal with (jack) buffer size changes */
  36. /* FIXME: needs error handling everywhere! */
  37. /* TODO: read/write data from/to disk in larger chunks to avoid
  38. * excessive seeking. 256k is supposedly the sweetspot. */
  39. //float Disk_Stream::seconds_to_buffer = 5.0f;
  40. float Disk_Stream::seconds_to_buffer = 2.0f;
  41. /* this is really only a rough estimate. The actual amount of data
  42. read depends on many factors. Overlapping regions, for example, will
  43. require more data to be read from disk, as will varying channel
  44. counts.*/
  45. size_t Disk_Stream::disk_io_kbytes = 256;
  46. Disk_Stream::Disk_Stream ( Track *track, float frame_rate, nframes_t nframes, int channels ) : _track( track )
  47. {
  48. assert( channels );
  49. _frame = 0;
  50. _thread = 0;
  51. _terminate = false;
  52. _pending_seek = -1;
  53. _xruns = 0;
  54. _frame_rate = frame_rate;
  55. _resize_buffers( nframes, channels );
  56. sem_init( &_blocks, 0, _total_blocks );
  57. }
  58. Disk_Stream::~Disk_Stream ( )
  59. {
  60. /* it isn't safe to do all this with the RT thread running */
  61. engine->lock();
  62. shutdown();
  63. _track = NULL;
  64. sem_destroy( &_blocks );
  65. for ( int i = channels(); i--; )
  66. jack_ringbuffer_free( _rb[ i ] );
  67. engine->unlock();
  68. }
  69. /* THREAD: RT */
  70. /** flush buffers and reset. Must only be called from the RT thread. */
  71. void
  72. Disk_Stream::base_flush ( bool is_output )
  73. {
  74. /* flush buffers */
  75. for ( int i = _rb.size(); i--; )
  76. jack_ringbuffer_read_advance( _rb[ i ], jack_ringbuffer_read_space( _rb[ i ] ) );
  77. /* sem_destroy( &_blocks ); */
  78. /* if ( is_output ) */
  79. /* sem_init( &_blocks, 0, _total_blocks ); */
  80. /* else */
  81. /* sem_init( &_blocks, 0, 0 ); */
  82. if ( is_output )
  83. {
  84. int n;
  85. sem_getvalue( &_blocks, &n );
  86. n = _total_blocks - n;
  87. while ( n-- )
  88. sem_post( &_blocks );
  89. }
  90. else
  91. {
  92. sem_destroy( &_blocks );
  93. sem_init( &_blocks, 0, 0 );
  94. }
  95. }
  96. /** signal thread to terminate, then detach it */
  97. void
  98. Disk_Stream::detach ( void )
  99. {
  100. _terminate = true;
  101. block_processed();
  102. pthread_detach( _thread );
  103. }
  104. /** stop the IO thread. */
  105. void
  106. Disk_Stream::shutdown ( void )
  107. {
  108. _terminate = true;
  109. /* try to wake the thread so it'll see that it's time to die */
  110. block_processed();
  111. if ( _thread )
  112. pthread_join( _thread, NULL );
  113. }
  114. Track *
  115. Disk_Stream::track ( void ) const
  116. {
  117. return _track;
  118. }
  119. Audio_Sequence *
  120. Disk_Stream::sequence ( void ) const
  121. {
  122. return (Audio_Sequence*)_track->sequence();
  123. }
  124. /** start Disk_Stream thread */
  125. void
  126. Disk_Stream::run ( void )
  127. {
  128. ASSERT( ! _thread, "Thread is already running" );
  129. if ( pthread_create( &_thread, NULL, &Disk_Stream::disk_thread, this ) != 0 )
  130. FATAL( "Could not create IO thread!" );
  131. }
  132. void
  133. Disk_Stream::_resize_buffers ( nframes_t nframes, int channels )
  134. {
  135. for ( int i = _rb.size(); i--; )
  136. jack_ringbuffer_free( _rb[ i ] );
  137. _rb.clear();
  138. _nframes = nframes;
  139. _total_blocks = _frame_rate * seconds_to_buffer / nframes;
  140. size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
  141. if ( disk_io_kbytes )
  142. _disk_io_blocks = ( bufsize * channels ) / ( disk_io_kbytes * 1024 );
  143. else
  144. _disk_io_blocks = 1;
  145. for ( int i = channels; i--; )
  146. _rb.push_back( jack_ringbuffer_create( bufsize ) );
  147. }
  148. /* THREAD: RT (non-RT) */
  149. /* to be called when the JACK buffer size changes. */
  150. void
  151. Disk_Stream::resize_buffers ( nframes_t nframes )
  152. {
  153. if ( nframes != _nframes )
  154. {
  155. DMESSAGE( "resizing buffers" );
  156. const bool was_running = _thread;
  157. if ( was_running )
  158. shutdown();
  159. flush();
  160. _resize_buffers( nframes, channels() );
  161. if ( was_running )
  162. run();
  163. }
  164. }
  165. /* static wrapper */
  166. void *
  167. Disk_Stream::disk_thread ( void *arg )
  168. {
  169. ((Disk_Stream*)arg)->disk_thread();
  170. return NULL;
  171. }
  172. int
  173. Disk_Stream::buffer_percent ( void )
  174. {
  175. int n;
  176. sem_getvalue( &_blocks, &n );
  177. return 100 - (n * 100 / _total_blocks);
  178. }