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.

339 lines
8.1KB

  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 "Client.H"
  19. #include "Port.H"
  20. #include <algorithm>
  21. #include "debug.h"
  22. #ifdef __SSE2_MATH__
  23. #include <xmmintrin.h>
  24. #endif
  25. namespace JACK
  26. {
  27. // nframes_t Client::_sample_rate = 0;
  28. Client::Client ( )
  29. {
  30. _active = false;
  31. _freewheeling = false;
  32. _zombified = false;
  33. _client = NULL;
  34. _xruns = 0;
  35. }
  36. Client::~Client ( )
  37. {
  38. close();
  39. }
  40. /** Tell JACK to stop calling process callback. This MUST be called in
  41. * an inheriting class' destructor */
  42. void
  43. Client::deactivate ( )
  44. {
  45. if ( _active )
  46. jack_deactivate( _client );
  47. _active = false;
  48. }
  49. /*******************/
  50. /* Static Wrappers */
  51. /*******************/
  52. int
  53. Client::process ( nframes_t nframes, void *arg )
  54. {
  55. Client *c = (Client*)arg;
  56. if ( ! c->_frozen.trylock() )
  57. return 0;
  58. int r = c->process(nframes);
  59. c->_frozen.unlock();
  60. return r;
  61. }
  62. int
  63. Client::sync ( jack_transport_state_t state, jack_position_t *pos, void *arg )
  64. {
  65. return ((Client*)arg)->sync( state, pos );
  66. }
  67. int
  68. Client::xrun ( void *arg )
  69. {
  70. ++((Client*)arg)->_xruns;
  71. return ((Client*)arg)->xrun();
  72. }
  73. void
  74. Client::timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg )
  75. {
  76. ((Client*)arg)->timebase( state, nframes, pos, new_pos );
  77. }
  78. void
  79. Client::freewheel ( int starting, void *arg )
  80. {
  81. ((Client*)arg)->_freewheeling = starting;
  82. ((Client*)arg)->freewheel( starting );
  83. }
  84. int
  85. Client::buffer_size ( nframes_t nframes, void *arg )
  86. {
  87. return ((Client*)arg)->buffer_size( nframes );
  88. }
  89. void
  90. Client::thread_init ( void *arg )
  91. {
  92. #ifdef __SSE2_MATH__
  93. /* set FTZ and DAZ flags */
  94. _mm_setcsr(_mm_getcsr() | 0x8040);
  95. #endif
  96. ((Client*)arg)->thread_init();
  97. }
  98. void
  99. Client::latency ( jack_latency_callback_mode_t mode, void *arg )
  100. {
  101. ((Client*)arg)->latency( mode );
  102. }
  103. void
  104. Client::shutdown ( void *arg )
  105. {
  106. ((Client*)arg)->_zombified = true;
  107. ((Client*)arg)->shutdown();
  108. }
  109. void
  110. Client::port_connect ( jack_port_id_t a, jack_port_id_t b, int connect, void *arg )
  111. {
  112. Client *c = (Client*)arg;
  113. if (! c->_frozen.trylock() )
  114. return;
  115. ((Client*)arg)->port_connect( a, b, connect );
  116. c->_frozen.unlock();
  117. }
  118. int
  119. Client::sample_rate_changed ( nframes_t srate, void *arg )
  120. {
  121. // ((Client*)arg)->_sample_rate = srate;
  122. return ((Client*)arg)->sample_rate_changed( srate );
  123. }
  124. void
  125. Client::activate ( void )
  126. {
  127. jack_activate( _client );
  128. _active = true;
  129. }
  130. /** Connect to JACK using client name /client_name/. Return a static
  131. * pointer to actual name as reported by JACK */
  132. const char *
  133. Client::init ( const char *client_name, unsigned int opts )
  134. {
  135. if (( _client = jack_client_open ( client_name, (jack_options_t)0, NULL )) == 0 )
  136. return NULL;
  137. #define set_callback( name ) jack_set_ ## name ## _callback( _client, &Client:: name , this )
  138. set_callback( thread_init );
  139. set_callback( process );
  140. set_callback( xrun );
  141. set_callback( freewheel );
  142. set_callback( buffer_size );
  143. set_callback( port_connect );
  144. jack_set_sample_rate_callback( _client, &Client::sample_rate_changed, this );
  145. #ifdef HAVE_JACK_PORT_GET_LATENCY_RANGE
  146. set_callback( latency );
  147. #endif
  148. /* FIXME: should we wait to register this until after the project
  149. has been loaded (and we have disk threads running)? */
  150. if ( opts & SLOW_SYNC )
  151. set_callback( sync );
  152. if ( opts & TIMEBASE_MASTER )
  153. jack_set_timebase_callback( _client, 0, &Client::timebase, this );
  154. jack_on_shutdown( _client, &Client::shutdown, this );
  155. activate();
  156. // _sample_rate = frame_rate();
  157. return jack_get_client_name( _client );
  158. }
  159. /* THREAD: RT */
  160. /** enter or leave freehweeling mode */
  161. void
  162. Client::freewheeling ( bool yes )
  163. {
  164. if ( jack_set_freewheel( _client, yes ) )
  165. ;
  166. // WARNING( "Unkown error while setting freewheeling mode" );
  167. }
  168. const char *
  169. Client::jack_name ( void ) const
  170. {
  171. return jack_get_client_name( _client );
  172. }
  173. void
  174. Client::port_added ( Port *p )
  175. {
  176. std::list < JACK::Port * >::iterator i = std::find( _active_ports.begin(), _active_ports.end(), p );
  177. if ( i != _active_ports.end() )
  178. return;
  179. _active_ports.push_back( p );
  180. }
  181. void
  182. Client::port_removed ( Port *p )
  183. {
  184. _active_ports.remove( p );
  185. }
  186. void
  187. Client::freeze_ports ( void )
  188. {
  189. for ( std::list < JACK::Port * >::iterator i = _active_ports.begin();
  190. i != _active_ports.end();
  191. ++i )
  192. {
  193. (*i)->freeze();
  194. }
  195. }
  196. void
  197. Client::thaw_ports ( void )
  198. {
  199. /* Sort ports for the sake of clients (e.g. patchage), for
  200. * whom the order of creation may matter (for display) */
  201. _active_ports.sort();
  202. for ( std::list < JACK::Port * >::iterator i = _active_ports.begin();
  203. i != _active_ports.end();
  204. ++i )
  205. {
  206. (*i)->thaw();
  207. }
  208. }
  209. void
  210. Client::close ( void )
  211. {
  212. deactivate();
  213. if ( _client )
  214. {
  215. DMESSAGE( "Closing JACK client" );
  216. jack_client_close( _client );
  217. }
  218. _client = NULL;
  219. }
  220. const char *
  221. Client::name ( const char *s )
  222. {
  223. /* Because the JACK API does not provide a mechanism for renaming
  224. * clients, we have to save connections, destroy our client,
  225. * create a client with the new name, and restore our
  226. * connections. Lovely. */
  227. freeze_ports();
  228. jack_deactivate( _client );
  229. jack_client_close( _client );
  230. _client = NULL;
  231. _frozen.lock();
  232. s = init( s );
  233. thaw_ports();
  234. _frozen.unlock();
  235. return s;
  236. }
  237. void
  238. Client::recompute_latencies ( void )
  239. {
  240. jack_recompute_total_latencies( _client );
  241. }
  242. void
  243. Client::transport_stop ( )
  244. {
  245. jack_transport_stop( _client );
  246. }
  247. void
  248. Client::transport_start ( )
  249. {
  250. jack_transport_start( _client );
  251. }
  252. void
  253. Client::transport_locate ( nframes_t frame )
  254. {
  255. jack_transport_locate( _client, frame );
  256. }
  257. jack_transport_state_t
  258. Client::transport_query ( jack_position_t *pos )
  259. {
  260. return jack_transport_query( _client, pos );
  261. }
  262. }