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.

296 lines
7.3KB

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