Update NTK.
[nondaw.git] / mixer / src / JACK_Module.C
blob1bc170cb5d6ab11d6fa6a990c4e81cabe26c9072
2 /*******************************************************************************/
3 /* Copyright (C) 2009 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 "const.h"
22 #include <string.h>
24 #include <FL/fl_ask.H>
26 #include "dsp.h"
28 #include "Engine/Engine.H"
29 #include "Chain.H"
31 #include "JACK_Module.H"
35 JACK_Module::JACK_Module ( )
36     : Module ( 50, 24, name() )
38     /* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */
39     {
40         Port p( this, Port::INPUT, Port::CONTROL, "Inputs" );
41         p.hints.type = Port::Hints::INTEGER;
42         p.hints.minimum = 0;
43         p.hints.maximum = 16;
44         p.hints.ranged = true;
46         p.connect_to( new float );
47         p.control_value_no_callback( 0 );
49         add_port( p );
50     }
52     {
53         Port p( this, Port::INPUT, Port::CONTROL, "Outputs" );
54         p.hints.type = Port::Hints::INTEGER;
55         p.hints.minimum = 0;
56         p.hints.maximum = 16;
57         p.hints.ranged = true;
59         p.connect_to( new float );
60         p.control_value_no_callback( 0 );
62         add_port( p );
63     }
65     end();
67     log_create();
70 JACK_Module::~JACK_Module ( )
72     log_destroy();
73     configure_inputs( 0 );
74     configure_outputs( 0 );
79 int
80 JACK_Module::can_support_inputs ( int )
82     return audio_output.size();
85 bool
86 JACK_Module::configure_inputs ( int n )
88     int on = audio_input.size();
90     if ( n > on )
91     {
92         for ( int i = on; i < n; ++i )
93         {
94             JACK::Port po( chain()->engine(), JACK::Port::Output, i );
96             if ( ! po.activate() )
97             {
98                 jack_port_activation_error( &po );
99                 return false;
100             }
102             if ( po.valid() )
103             {
104                 add_port( Port( this, Port::INPUT, Port::AUDIO ) );
105                 jack_output.push_back( po );
106             }
107         }
108     }
109     else
110     {
111         for ( int i = on; i > n; --i )
112         {
113             audio_input.back().disconnect();
114             audio_input.pop_back();
115             jack_output.back().shutdown();
116             jack_output.pop_back();
117         }
118     }
120     control_input[0].control_value_no_callback( n );
122     return true;
125 void
126 JACK_Module::jack_port_activation_error ( JACK::Port *p )
128     fl_alert( "Could not activate JACK port \"%s\"", p->name() );
131 bool
132 JACK_Module::configure_outputs ( int n )
134    int on = audio_output.size();
136     if ( n > on )
137     {
138         for ( int i = on; i < n; ++i )
139         {
140             JACK::Port po( chain()->engine(), JACK::Port::Input, i );
142             if ( ! po.activate() )
143             {
144                 jack_port_activation_error( &po );
145                 return false;
146             }
148             if ( po.valid() )
149             {
150                 add_port( Port( this, Port::OUTPUT, Port::AUDIO ) );
151                 jack_input.push_back( po );
152             }
153         }
154     }
155     else
156     {
157         for ( int i = on; i > n; --i )
158         {
159             audio_output.back().disconnect();
160             audio_output.pop_back();
161             jack_input.back().shutdown();
162             jack_input.pop_back();
163         }
164     }
166     control_input[1].control_value_no_callback( n );
168     return true;
171 bool
172 JACK_Module::initialize ( void )
174     return true;
177 void
178 JACK_Module::handle_control_changed ( Port *p )
180     THREAD_ASSERT( UI );
182     if ( 0 == strcmp( p->name(), "Inputs" ) )
183     {
184         DMESSAGE( "Adjusting number of inputs (JACK outputs)" );
185         configure_inputs( p->control_value() );
186         if ( chain() )
187             chain()->configure_ports();
188     }
189     else if ( 0 == strcmp( p->name(), "Outputs" ) )
190     {
191         DMESSAGE( "Adjusting number of outputs (JACK inputs)" );
193         if ( ! chain() )
194         {
195             configure_outputs( p->control_value() );
196         }
197         else if ( chain()->can_configure_outputs( this, p->control_value() ) )
198         {
199             configure_outputs( p->control_value() );
200             chain()->configure_ports();
201         }
202         else
203         {
204             p->connected_port()->control_value( noutputs() );
205         }
206     }
209 void
210 JACK_Module::handle_chain_name_changed ( void )
212     for ( unsigned int i = 0; i < jack_output.size(); ++i )
213         jack_output[ i ].name( NULL, i  );
215     for ( unsigned int i = 0; i < jack_input.size(); ++i )
216         jack_input[ i ].name( NULL, i );
218     Module::handle_chain_name_changed();
223 /**********/
224 /* Engine */
225 /**********/
227 void
228 JACK_Module::process ( nframes_t nframes )
230     for ( unsigned int i = 0; i < audio_input.size(); ++i )
231         if ( audio_input[i].connected() )
232             buffer_copy( (sample_t*)jack_output[i].buffer( nframes ), (sample_t*)audio_input[i].buffer(), nframes );
234     for ( unsigned int i = 0; i < audio_output.size(); ++i )
235         if ( audio_output[i].connected() )
236             buffer_copy( (sample_t*)audio_output[i].buffer(), (sample_t*)jack_input[i].buffer( nframes ), nframes );