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.

316 lines
7.7KB

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