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.

150 lines
4.5KB

  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. // size_t Disk_Stream::disk_block_frames = 2048;
  48. Disk_Stream::Disk_Stream ( Track *th, float frame_rate, nframes_t nframes, int channels ) : _th( th )
  49. {
  50. _frame = 0;
  51. _thread = 0;
  52. _terminate = false;
  53. _pending_seek = -1;
  54. printf( "nframes %lu\n", nframes );
  55. _total_blocks = frame_rate * seconds_to_buffer / nframes;
  56. _nframes = nframes;
  57. size_t bufsize = _total_blocks * nframes * sizeof( sample_t );
  58. for ( int i = channels; i--; )
  59. _rb.push_back( jack_ringbuffer_create( bufsize ) );
  60. sem_init( &_blocks, 0, _total_blocks );
  61. // run();
  62. }
  63. Disk_Stream::~Disk_Stream ( )
  64. {
  65. /* it isn't safe to do all this with the RT thread running */
  66. engine->lock();
  67. _th = NULL;
  68. sem_destroy( &_blocks );
  69. for ( int i = channels(); i--; )
  70. jack_ringbuffer_free( _rb[ i ] );
  71. engine->unlock();
  72. }
  73. /** stop the IO thread, block until it finishes. */
  74. void
  75. Disk_Stream::shutdown ( void )
  76. {
  77. _terminate = true;
  78. /* try to wake the thread so it'll see that it's time to die */
  79. block_processed();
  80. if ( _thread )
  81. pthread_join( _thread, NULL );
  82. _terminate = false;
  83. }
  84. Audio_Sequence *
  85. Disk_Stream::track ( void )
  86. {
  87. return (Audio_Sequence*)_th->track();
  88. }
  89. /** start Disk_Stream thread */
  90. void
  91. Disk_Stream::run ( void )
  92. {
  93. if ( pthread_create( &_thread, NULL, &Disk_Stream::disk_thread, this ) != 0 )
  94. /* error */;
  95. }
  96. /* to be called when the JACK buffer size changes. */
  97. void
  98. Disk_Stream::resize ( nframes_t nframes )
  99. {
  100. if ( nframes != _nframes )
  101. /* FIXME: to something here! */;
  102. }
  103. /* static wrapper */
  104. void *
  105. Disk_Stream::disk_thread ( void *arg )
  106. {
  107. ((Disk_Stream*)arg)->disk_thread();
  108. return NULL;
  109. }
  110. int
  111. Disk_Stream::buffer_percent ( void )
  112. {
  113. int n;
  114. sem_getvalue( &_blocks, &n );
  115. return 100 - (n * 100 / _total_blocks);
  116. }