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.

151 lines
4.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 "Disk_Stream.H"
  19. #include "Track.H"
  20. #include "Audio_Sequence.H"
  21. #include "Port.H"
  22. #include "Engine.H" // for locking.
  23. #include "dsp.h"
  24. /**********/
  25. /* Engine */
  26. /**********/
  27. /* A Disk_Stream uses a separate I/O thread to stream a track's
  28. regions from disk into a ringbuffer to be processed by the RT
  29. thread (or vice-versa). The I/O thread syncronizes access with the
  30. user thread via the Timeline mutex. The size of the buffer (in
  31. seconds) must be set before any Disk_Stream objects are created;
  32. that is, at startup time. The default is 5 seconds, which may or
  33. may not be excessive depending on various external factors. */
  34. /* FIXME: handle termination of IO thread in destructor */
  35. /* FIXME: deal with (jack) buffer size changes */
  36. /* FIXME: needs error handling everywhere! */
  37. /* TODO: handle capture too. For this to work with some kind of
  38. * punch-in/out system, I believe we'll have to always keep at least
  39. * one buffer's worth of input. We would need this anyway in order to
  40. * pass input through to output (software monitoring). What about
  41. * looped recording? */
  42. /* TODO: latency compensation? Does this really apply to us? (we're
  43. * not hosting plugins here) */
  44. /* TODO: read/write data from/to disk in larger chunks to avoid
  45. * excessive seeking. 256k is supposedly the sweetspot. */
  46. //float Disk_Stream::seconds_to_buffer = 5.0f;
  47. float Disk_Stream::seconds_to_buffer = 2.0f;
  48. // size_t Disk_Stream::disk_block_frames = 2048;
  49. Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ) : _th( th )
  50. {
  51. _frame = 0;
  52. _thread = 0;
  53. _terminate = false;
  54. _pending_seek = -1;
  55. printf( "nframes %lu\n", nframes );
  56. _total_blocks = frame_rate * seconds_to_buffer / nframes;
  57. _nframes = nframes;
  58. size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
  59. for ( int i = channels; i--; )
  60. _rb.push_back( jack_ringbuffer_create( bufsize ) );
  61. sem_init( &_blocks, 0, _total_blocks );
  62. // run();
  63. }
  64. Disk_Stream::~Disk_Stream ( )
  65. {
  66. /* it isn't safe to do all this with the RT thread running */
  67. engine->lock();
  68. _th = NULL;
  69. sem_destroy( &_blocks );
  70. for ( int i = channels(); i--; )
  71. jack_ringbuffer_free( _rb[ i ] );
  72. engine->unlock();
  73. }
  74. /** stop the IO thread, block until it finishes. */
  75. void
  76. Disk_Stream::shutdown ( void )
  77. {
  78. _terminate = true;
  79. /* try to wake the thread so it'll see that it's time to die */
  80. block_processed();
  81. if ( _thread )
  82. pthread_join( _thread, NULL );
  83. _terminate = false;
  84. }
  85. Audio_Sequence *
  86. Disk_Stream::track ( void )
  87. {
  88. return (Audio_Sequence*)_th->track();
  89. }
  90. /** start Disk_Stream thread */
  91. void
  92. Disk_Stream::run ( void )
  93. {
  94. if ( pthread_create( &_thread, NULL, &Disk_Stream::disk_thread, this ) != 0 )
  95. /* error */;
  96. }
  97. /* to be called when the JACK buffer size changes. */
  98. void
  99. Disk_Stream::resize ( nframes_t nframes )
  100. {
  101. if ( nframes != _nframes )
  102. /* FIXME: to something here! */;
  103. }
  104. /* static wrapper */
  105. void *
  106. Disk_Stream::disk_thread ( void *arg )
  107. {
  108. ((Disk_Stream*)arg)->disk_thread();
  109. return NULL;
  110. }
  111. int
  112. Disk_Stream::buffer_percent ( void )
  113. {
  114. int n;
  115. sem_getvalue( &_blocks, &n );
  116. return 100 - (n * 100 / _total_blocks);
  117. }