aRts audio server
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.

audioiojack.cc 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. Copyright (C) 2004 Matthias Kretz <kretz@kde.org>
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License version 2 as published by the Free Software Foundation.
  6. This library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9. Library General Public License for more details.
  10. You should have received a copy of the GNU Library General Public License
  11. along with this library; see the file COPYING.LIB. If not, write to
  12. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  13. Boston, MA 02110-1301, USA.
  14. */
  15. #ifdef HAVE_CONFIG_H
  16. #include <config.h>
  17. #endif
  18. #ifdef HAVE_LIBJACK
  19. #include <jack/jack.h>
  20. #include <jack/ringbuffer.h>
  21. #include "debug.h"
  22. #include "audioio.h"
  23. #include "audiosubsys.h"
  24. #include "iomanager.h"
  25. #include "dispatcher.h"
  26. #ifndef MIN
  27. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  28. #endif
  29. #undef DEBUG_WAVEFORM
  30. #ifdef DEBUG_WAVEFORM
  31. #include <fstream>
  32. #endif
  33. #include <cstdlib>
  34. #include <cstring>
  35. namespace Arts {
  36. class AudioIOJack : public AudioIO, public TimeNotify {
  37. private:
  38. #ifdef DEBUG_WAVEFORM
  39. std::ofstream plotfile;
  40. #endif
  41. char * processBuffer;
  42. size_t buffersize;
  43. protected:
  44. jack_client_t *jack;
  45. jack_port_t *outleft, *outright;
  46. jack_port_t *inleft, *inright;
  47. jack_ringbuffer_t *olb, *orb, *ilb, *irb;
  48. public:
  49. AudioIOJack();
  50. void notifyTime();
  51. void setParam( AudioParam p, int & val );
  52. int getParam(AudioParam param);
  53. static int jackCallback( jack_nframes_t, void * );
  54. bool open();
  55. void close();
  56. int read(void *buffer, int size);
  57. int write(void *buffer, int size);
  58. };
  59. REGISTER_AUDIO_IO(AudioIOJack,"jack","Jack Audio Connection Kit");
  60. }
  61. using namespace std;
  62. using namespace Arts;
  63. AudioIOJack::AudioIOJack()
  64. :
  65. #ifdef DEBUG_WAVEFORM
  66. plotfile( "/dev/shm/audioiojack.plot" ),
  67. #endif
  68. jack( 0 )
  69. , outleft( 0 )
  70. , outright( 0 )
  71. , inleft( 0 )
  72. , inright( 0 )
  73. {
  74. /*
  75. * default parameters
  76. */
  77. param( samplingRate ) = 44100;
  78. paramStr( deviceName ) = "jack";
  79. param( fragmentSize ) = 512;
  80. param( fragmentCount ) = 2;
  81. param( channels ) = 2;
  82. param( direction ) = 2;
  83. param( format ) = 32;
  84. }
  85. bool AudioIOJack::open()
  86. {
  87. string& _error = paramStr( lastError );
  88. jack = jack_client_new( "artsd" );
  89. if( jack == 0 )
  90. {
  91. _error = "Couldn't connect to jackd";
  92. return false;
  93. }
  94. int& _sampleRate = param(samplingRate);
  95. _sampleRate = jack_get_sample_rate( jack );
  96. int& _fragmentSize = param(fragmentSize);
  97. int& _fragmentCount = param(fragmentCount);
  98. /*
  99. * don't allow unreasonable large fragmentSize/Count combinations,
  100. * because "real" hardware also doesn't
  101. */
  102. if(_fragmentSize > 1024*8) _fragmentSize = 1024*8;
  103. while(_fragmentSize * _fragmentCount > 1024*128)
  104. _fragmentCount--;
  105. jack_set_process_callback( jack, Arts::AudioIOJack::jackCallback, this );
  106. if( param( direction ) & directionWrite )
  107. {
  108. outleft = jack_port_register( jack, "out_1",
  109. JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
  110. outright = jack_port_register( jack, "out_2",
  111. JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
  112. olb = jack_ringbuffer_create(
  113. sizeof( jack_default_audio_sample_t ) *
  114. _fragmentSize * _fragmentCount );
  115. orb = jack_ringbuffer_create(
  116. sizeof( jack_default_audio_sample_t ) *
  117. _fragmentSize * _fragmentCount );
  118. }
  119. if( param( direction ) & directionRead )
  120. {
  121. inleft = jack_port_register( jack, "in_1",
  122. JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
  123. inright = jack_port_register( jack, "in_2",
  124. JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
  125. ilb = jack_ringbuffer_create(
  126. sizeof( jack_default_audio_sample_t ) *
  127. 1024 * 64 );
  128. irb = jack_ringbuffer_create(
  129. sizeof( jack_default_audio_sample_t ) *
  130. 1024 * 64 );
  131. }
  132. if( jack_activate( jack ) )
  133. {
  134. _error = "Activating as jack client failed.";
  135. return false;
  136. }
  137. const char **ports;
  138. if( param( direction ) & directionRead )
  139. {
  140. ports = jack_get_ports( jack, 0, 0, JackPortIsPhysical
  141. | JackPortIsOutput );
  142. if( ports == 0 )
  143. {
  144. arts_warning( "Cannot find any capture ports to"
  145. " connect to. You need to manually connect"
  146. " the capture ports in jack" );
  147. }
  148. else
  149. {
  150. if( ports[ 0 ] != 0 )
  151. jack_connect( jack, ports[ 0 ],
  152. jack_port_name( inleft ) );
  153. if( ports[ 1 ] != 0 )
  154. jack_connect( jack, ports[ 1 ],
  155. jack_port_name( inright ) );
  156. free( ports );
  157. }
  158. }
  159. if( param( direction ) & directionWrite )
  160. {
  161. ports = jack_get_ports( jack, 0, 0, JackPortIsPhysical
  162. | JackPortIsInput );
  163. if( ports == 0 )
  164. {
  165. arts_warning( "Cannot find any playback ports to"
  166. " connect to. You need to manually connect"
  167. " the playback ports in jack" );
  168. }
  169. else
  170. {
  171. if( ports[ 0 ] != 0 )
  172. jack_connect( jack, jack_port_name( outleft ),
  173. ports[ 0 ] );
  174. if( ports[ 1 ] != 0 )
  175. jack_connect( jack, jack_port_name( outright ),
  176. ports[ 1 ] );
  177. free( ports );
  178. }
  179. }
  180. // Install the timer
  181. Dispatcher::the()->ioManager()->addTimer(10, this);
  182. return true;
  183. }
  184. void AudioIOJack::close()
  185. {
  186. jack_client_close( jack );
  187. Dispatcher::the()->ioManager()->removeTimer(this);
  188. }
  189. int AudioIOJack::jackCallback( jack_nframes_t nframes, void * args )
  190. {
  191. AudioIOJack * that = static_cast<AudioIOJack*>( args );
  192. that->buffersize = nframes * sizeof( jack_default_audio_sample_t );
  193. if( that->outleft )
  194. {
  195. if( jack_ringbuffer_read_space( that->olb ) < that->buffersize )
  196. {
  197. that->processBuffer = static_cast<char *>(
  198. jack_port_get_buffer( that->outleft, nframes ) );
  199. memset( that->processBuffer, 0, that->buffersize );
  200. that->processBuffer = static_cast<char *>(
  201. jack_port_get_buffer( that->outright, nframes ) );
  202. memset( that->processBuffer, 0, that->buffersize );
  203. }
  204. else
  205. {
  206. that->processBuffer = static_cast<char *>(
  207. jack_port_get_buffer( that->outleft, nframes ) );
  208. jack_ringbuffer_read( that->olb, that->processBuffer, that->buffersize );
  209. that->processBuffer = static_cast<char *>(
  210. jack_port_get_buffer( that->outright, nframes ) );
  211. jack_ringbuffer_read( that->orb, that->processBuffer, that->buffersize );
  212. }
  213. }
  214. if( that->inleft )
  215. {
  216. that->processBuffer = static_cast<char *>(
  217. jack_port_get_buffer( that->inleft, nframes ) );
  218. jack_ringbuffer_write( that->ilb, that->processBuffer, that->buffersize );
  219. that->processBuffer = static_cast<char *>(
  220. jack_port_get_buffer( that->inright, nframes ) );
  221. jack_ringbuffer_write( that->irb, that->processBuffer, that->buffersize );
  222. }
  223. return 0;
  224. }
  225. void AudioIOJack::setParam( AudioParam p, int& val )
  226. {
  227. // don't change the format - jack only supports 32 bit float
  228. if( p == format )
  229. return;
  230. AudioIO::setParam( p, val );
  231. }
  232. int AudioIOJack::getParam(AudioParam p)
  233. {
  234. switch(p)
  235. {
  236. case canRead:
  237. return MIN( jack_ringbuffer_read_space( ilb ), jack_ringbuffer_read_space( irb ) ) * param( channels );
  238. case canWrite:
  239. return MIN( jack_ringbuffer_write_space( olb ), jack_ringbuffer_write_space( orb ) ) * param( channels );
  240. default:
  241. return AudioIO::getParam( p );
  242. }
  243. }
  244. int AudioIOJack::read(void *buffer, int size)
  245. {
  246. float * floatbuffer = static_cast<float *>( buffer );
  247. if( param( channels ) == 2 )
  248. {
  249. float * end = ( float * )( static_cast<char *>( buffer ) + size );
  250. while( floatbuffer < end )
  251. {
  252. jack_ringbuffer_read( ilb, ( char* )( floatbuffer++ ), sizeof( float ) );
  253. #ifdef DEBUG_WAVEFORM
  254. plotfile << *( floatbuffer - 1 ) << "\n";
  255. #endif
  256. jack_ringbuffer_read( irb, ( char* )( floatbuffer++ ), sizeof( float ) );
  257. }
  258. }
  259. else if( param( channels ) == 1 )
  260. {
  261. jack_ringbuffer_read( ilb, ( char* )( floatbuffer ), size );
  262. }
  263. return size;
  264. }
  265. int AudioIOJack::write(void *buffer, int size)
  266. {
  267. float * floatbuffer = static_cast<float *>( buffer );
  268. if( param( channels ) == 2 )
  269. {
  270. float * end = ( float * )( static_cast<char *>( buffer ) + size );
  271. while( floatbuffer < end )
  272. {
  273. jack_ringbuffer_write( olb, ( char* )( floatbuffer++ ), sizeof( float ) );
  274. jack_ringbuffer_write( orb, ( char* )( floatbuffer++ ), sizeof( float ) );
  275. }
  276. }
  277. else if( param( channels ) == 1 )
  278. {
  279. jack_ringbuffer_write( olb, ( char* )( floatbuffer ), size );
  280. }
  281. return size;
  282. }
  283. void AudioIOJack::notifyTime()
  284. {
  285. int& _direction = param(direction);
  286. int& _fragmentSize = param(fragmentSize);
  287. for( ;; )
  288. {
  289. int todo = 0;
  290. if( ( _direction & directionRead ) && ( getParam( canRead ) >= _fragmentSize ) )
  291. todo |= AudioSubSystem::ioRead;
  292. if( ( _direction & directionWrite ) && ( getParam( canWrite ) >= _fragmentSize ) )
  293. todo |= AudioSubSystem::ioWrite;
  294. if( ! todo )
  295. return;
  296. AudioSubSystem::the()->handleIO( todo );
  297. }
  298. }
  299. #endif
  300. // vim: sw=4 ts=4