Update NTK.
[nondaw.git] / nonlib / JACK / Client.C
blob736299840019855197cbe8185d8246eab2dde344
2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles                                     */
4 /*                                                                             */
5 /* This program is free software; you can redistribute it and/or modify it     */
6 /* under the terms of the GNU General Public License as published by the       */
7 /* Free Software Foundation; either version 2 of the License, or (at your      */
8 /* option) any later version.                                                  */
9 /*                                                                             */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       */
12 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   */
13 /* more details.                                                               */
14 /*                                                                             */
15 /* You should have received a copy of the GNU General Public License along     */
16 /* with This program; see the file COPYING.  If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18 /*******************************************************************************/
20 #include "Client.H"
21 #include "Port.H"
23 #include <algorithm>
29 namespace JACK
32     nframes_t Client::_sample_rate = 0;
34     Client::Client ( )
35     {
36         _freewheeling = false;
37         _zombified = false;
38         _client = NULL;
39         _xruns = 0;
40     }
42     Client::~Client ( )
43     {
44         jack_client_close( _client );
45     }
47     /** Tell JACK to stop calling process callback. This MUST be called in
48      * an inheriting class' destructor */
49     void
50     Client::deactivate ( )
51     {
52         jack_deactivate( _client );
53     }
56 /*******************/
57 /* Static Wrappers */
58 /*******************/
60     int
61     Client::process ( nframes_t nframes, void *arg )
62     {
63         return ((Client*)arg)->process( nframes );
64     }
66     int
67     Client::sync ( jack_transport_state_t state, jack_position_t *pos, void *arg )
68     {
69         return ((Client*)arg)->sync( state, pos );
70     }
72     int
73     Client::xrun ( void *arg )
74     {
75         ++((Client*)arg)->_xruns;
76         return ((Client*)arg)->xrun();
77     }
79     void
80     Client::timebase ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg )
81     {
82         ((Client*)arg)->timebase( state, nframes, pos, new_pos );
83     }
85     void
86     Client::freewheel ( int starting, void *arg )
87     {
88         ((Client*)arg)->_freewheeling = starting;
89         ((Client*)arg)->freewheel( starting );
90     }
92     int
93     Client::buffer_size ( nframes_t nframes, void *arg )
94     {
95         return ((Client*)arg)->buffer_size( nframes );
96     }
98     void
99     Client::thread_init ( void *arg )
100     {
101         ((Client*)arg)->thread_init();
102     }
104     void
105     Client::shutdown ( void *arg )
106     {
107         ((Client*)arg)->_zombified = true;
108         ((Client*)arg)->shutdown();
109     }
113 /** Connect to JACK using client name /client_name/. Return a static
114  * pointer to actual name as reported by JACK */
115     const char *
116     Client::init ( const char *client_name, unsigned int opts )
117     {
118         if (( _client = jack_client_open ( client_name, (jack_options_t)0, NULL )) == 0 )
119             return NULL;
121 #define set_callback( name ) jack_set_ ## name ## _callback( _client, &Client:: name , this )
123         set_callback( thread_init );
124         set_callback( process );
125         set_callback( xrun );
126         set_callback( freewheel );
127         set_callback( buffer_size );
129         /* FIXME: should we wait to register this until after the project
130            has been loaded (and we have disk threads running)? */
131         if ( opts & SLOW_SYNC )
132             set_callback( sync );
134         if ( opts & TIMEBASE_MASTER )
135             jack_set_timebase_callback( _client, 0, &Client::timebase, this );
137         jack_on_shutdown( _client, &Client::shutdown, this );
139         jack_activate( _client );
141         _sample_rate = frame_rate();
143         return jack_get_client_name( _client );
144     }
148 /* THREAD: RT */
149 /** enter or leave freehweeling mode */
150     void
151     Client::freewheeling ( bool yes )
152     {
153         if ( jack_set_freewheel( _client, yes ) )
154             ;
155 //            WARNING( "Unkown error while setting freewheeling mode" );
156     }
159     void
160     Client::port_added ( Port *p )
161     {
162         std::list < JACK::Port * >::iterator i = std::find( _active_ports.begin(), _active_ports.end(), p );
164         if ( i != _active_ports.end() )
165             return;
167         _active_ports.push_back( p );
168     }
170     void
171     Client::port_removed ( Port *p )
172     {
173         _active_ports.remove( p );
174     }
177     void
178     Client::freeze_ports ( void )
179     {
180         for ( std::list < JACK::Port * >::iterator i = _active_ports.begin();
181               i != _active_ports.end();
182               ++i )
183         {
184             (*i)->freeze();
185         }
186     }
188     void
189     Client::thaw_ports ( void )
190     {
191         /* Sort ports for the sake of clients (e.g. patchage), for
192          * whom the order of creation may matter (for display) */
194         _active_ports.sort();
196         for ( std::list < JACK::Port * >::iterator i = _active_ports.begin();
197               i != _active_ports.end();
198               ++i )
199         {
200             (*i)->thaw();
201         }
202     }
204     void
205     Client::close ( void )
206     {
207         jack_deactivate( _client );
208         jack_client_close( _client );
210         _client = NULL;
211     }
213     const char *
214     Client::name ( const char *s )
215     {
216         /* Because the JACK API does not provide a mechanism for renaming
217          * clients, we have to save connections, destroy our client,
218          * create a client with the new name, and restore our
219          * connections. Lovely. */
221         freeze_ports();
223         jack_deactivate( _client );
224         jack_client_close( _client );
226         _client = NULL;
228         s = init( s );
230         thaw_ports();
232         return s;
233     }
235     void
236     Client::transport_stop ( )
237     {
238         jack_transport_stop( _client );
239     }
241     void
242     Client::transport_start ( )
243     {
244         jack_transport_start( _client );
245     }
247     void
248     Client::transport_locate ( nframes_t frame )
249     {
250         jack_transport_locate( _client, frame );
251     }
253     jack_transport_state_t
254     Client::transport_query ( jack_position_t *pos )
255     {
256         return jack_transport_query( _client, pos );
257     }