Mixer: Allow controller modules to be removed.
[nondaw.git] / mixer / src / Module.H
blob2ee4d9ca1d60c3c68bb4d44d81e9f97dde7aca7a
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 #pragma once
22 #include <FL/Fl.H>
23 #include <FL/Fl_Group.H>
25 #include <stdlib.h>
26 #include "debug.h"
27 #include <vector>
29 #include "Thread.H"
31 #include "Loggable.H"
32 #include "JACK/Port.H"
33 #include "OSC/Endpoint.H"
35 class Chain;
36 class Module_Parameter_Editor;
37 class Fl_Menu_;
38 class Fl_Menu_Button;
39 class Fl_Button;
41 class Module : public Fl_Group, public Loggable {
43     int _ins;
44     int _outs;
45     int _instances;
46     nframes_t _nframes;
47     Chain *_chain;
48     bool _is_default;
49     bool _bypass;
51     Module_Parameter_Editor *_editor;
53     static Module *_copied_module_empty;
54     static char *_copied_module_settings;
56     void init ( void );
58     void insert_menu_cb ( const Fl_Menu_ *m );
59     static void insert_menu_cb ( Fl_Widget *w, void *v );
61     void menu_cb ( const Fl_Menu_ *m );
62     static void menu_cb ( Fl_Widget *w, void *v );
63     Fl_Menu_Button & menu ( void ) const;
65     void copy ( void ) const;
66     void paste_before ( void );
68 public:
70     /* true if this module was added by default and not under normal user control */
71     bool is_default ( void ) const { return _is_default; }
72     void is_default ( bool v ) { _is_default = v; }
74     virtual bool allows_external_control ( void ) const { return true; }
76     class Port
77     {
78         /* char *type_names[] = { "Audio", "Control" }; */
79         /* char *direction_names[] = { "Input", "Output" }; */
81         void update_connected_port_buffer ( void )
82             {
83                 if ( connected() )
84                     connected_port()->_buf = _buf;
85             }
87     public:
89         enum Direction { INPUT, OUTPUT };
90         enum Type { AUDIO, CONTROL };
92         /* hints for control ports (specifically control inputs) */
93         struct Hints
94         {
95             enum Type { LINEAR, LOGARITHMIC, BOOLEAN, INTEGER };
97             Type type;
98             bool ranged;
99             float minimum;
100             float maximum;
101             float default_value;
102             int dimensions;
103             
104             Hints ( )
105                 {
106                     type = LINEAR;
107                     ranged = false;
108                     minimum = 0;
109                     maximum = 0;
110                     default_value = 0.0f;
111                     dimensions = 1;
112                 }
113         };
115         static int osc_control_change_exact ( float v, void *user_data );
116         static int osc_control_change_cv ( float v, void *user_data );
118         Hints hints;
120         Port ( Module *module, Direction direction, Type type, const char *name = 0 )
121             {
122                 _name = name;
123                 _direction = direction;
124                 _type = type;
125                 _buf = 0;
126                 _nframes = 0;
127                 _connected = 0;
128                 _module = module;
129                 _scaled_signal = 0;
130                 _unscaled_signal = 0;
131             }
133         Port ( const Port& p )
134             {
135                 _name = p._name;
136                 _direction = p._direction;
137                 _type = p._type;
138                 _buf = p._buf;
139                 _nframes = p._nframes;
140                 _connected = p._connected;
141                 _module = p._module;
142                 hints = p.hints;
143                 _scaled_signal = p._scaled_signal;
144                 _unscaled_signal = p._unscaled_signal;
145             }
147         virtual ~Port ( )
148             {
149                 //     change_osc_path( NULL );
150                 //   disconnect();
151             }
153         const char *name ( void ) const { return _name; }
154         Type type ( void ) const { return _type; }
155         Direction direction ( void ) const  { return _direction; }
157         Module * module ( void ) const { return _module; }
158         nframes_t nframes ( void ) const { return _nframes; }
160         void buffer ( void *buf, nframes_t nframes ) { _buf = buf; _nframes = nframes; };
161         void *buffer ( void ) const { return _buf; }
163         const char *osc_path ( )
164             {
165                 if ( _scaled_signal )
166                     return _scaled_signal->path();
167                 else
168                     return NULL;
169             }
171         void update_osc_port ( )
172             {
173 //                if ( INPUT == _direction )
174                 change_osc_path( generate_osc_path() );
175             }
177         void destroy_osc_port ( )
178             {
179                 delete _unscaled_signal;
180                 delete _scaled_signal;
181                 
182                 _unscaled_signal = _scaled_signal = NULL;
183             }
185         void control_value_no_callback ( float f )
186             {
187               /* can also be called from the OSC thread */
188                 ASSERT( Thread::is( "UI" ) || Thread::is( "OSC" ),
189                         "Function called from wrong thread! (is %s)",  Thread::current()->name() );
191                 if ( buffer() )
192                 {
193                     *((float*)buffer()) = f;
194                 }
195             }
197         void control_value ( float f )
198             {
199                 control_value_no_callback( f );
200                 _module->handle_control_changed( this );
201                 if ( connected() )
202                     connected_port()->_module->handle_control_changed( connected_port() );
203             }
205         float control_value ( ) const
206             {
207                 if ( buffer() )
208                     return *((float*)buffer());
209                 else
210                     return 0.0f;
211             }
213         bool connected ( void ) const { return _connected; }
214         bool connected_osc ( void ) const;
216         Port *connected_port ( void ) const
217             {
218                 return _connected;
219             }
221         void connect_to ( Port *to )
222             {
223                 _buf = to->_buf;
224                 to->_connected = this;
225                 _connected = to;
226             }
228         void connect_to ( void *buf )
229             {
230                 _buf = buf;
231                 update_connected_port_buffer();
232             }
234         void disconnect ( void )
235             {
236                 if ( _connected && _connected != (void*)0x01 )
237                 {
238                     _connected->_connected = NULL;
239                     _connected = NULL;
240                 }
241                 else
242                     _connected = NULL;
244                 /* FIXME: do something! */
245             }
247     private:
249         char *generate_osc_path ( void );
250         void change_osc_path ( char *path );
251     
252         Port *_connected;
253         Type _type;
254         Direction _direction;
255         const char *_name;
256         void *_buf;
257         nframes_t _nframes;
258         Module *_module;
261         OSC::Signal *_scaled_signal;
262         OSC::Signal *_unscaled_signal;
264         static void handle_signal_connection_state_changed ( OSC::Signal *, void *o );
265     };
267     void bbox ( int &X, int &Y, int &W, int &H )
268         {
269             X = x() + 5;
270             Y = y() + 5;
271             W = w() - 10;
272             H = h() - 10;
273         }
275     Module ( int W, int H, const char *L = 0 );
276     Module ( );
277     Module ( bool is_default, int W, int H, const char *L = 0 );
279     virtual ~Module ( );
281     LOG_NAME_FUNC( Module );
283     nframes_t nframes ( void ) const { return _nframes; }
284     void resize_buffers ( nframes_t v ) { _nframes = v; }
287     int instances ( void ) const { return _instances; }
288     void instances ( int i ) { _instances = i; }
290     bool is_being_controlled ( void ) const
291         {
292             for ( nframes_t i = control_input.size(); i--; )
293                 if ( control_input[i].connected() )
294                     return true;
295             return false;
296         }
298     bool is_controlling ( void ) const
299         {
300             for ( nframes_t i = control_output.size(); i--; )
301                 if ( control_output[i].connected() )
302                     return true;
303             return false;
304         }
306     bool
307     is_being_controlled_osc ( void ) const
308         {
309             for ( nframes_t i = control_input.size(); i--; )
310                 if ( control_input[i].connected_osc() )
311                     return true;
312             return false;
313         }
315     virtual const char *name ( void ) const = 0;
317     std::vector<Port> audio_input;
318     std::vector<Port> audio_output;
319     std::vector<Port> control_input;
320     std::vector<Port> control_output;
322     void add_port ( const Port &p )
323         {
324             if ( p.type() == Port::AUDIO && p.direction() == Port::INPUT )
325                 audio_input.push_back( p );
326             else if ( p.type() == Port::AUDIO && p.direction() == Port::OUTPUT )
327                 audio_output.push_back( p );
328             else if ( p.type() == Port::CONTROL && p.direction() == Port::INPUT )
329                 control_input.push_back( p );
330             else if ( p.type() == Port::CONTROL && p.direction() == Port::OUTPUT )
331                 control_output.push_back( p );
332         }
334     int noutputs ( void ) const
335         {
336             return audio_output.size();
337         }
339     int ninputs ( void ) const
340         {
341             return audio_input.size();
342         }
344     int ncontrol_inputs ( void ) const
345         {
346             return control_input.size();
347         }
349     int ncontrol_outputs ( void ) const
350         {
351             return control_output.size();
352         }
354     bool bypass ( void ) const { return _bypass; }
355     void bypass ( bool v ) { _bypass = v; redraw(); }
357     int control_input_port_index ( Port *p )
358         {
359             for ( nframes_t i = control_input.size(); i--; )
360                 if ( &control_input[i] == p )
361                     return i;
363             return -1;
364         }
366     int control_output_port_index ( Port *p )
367         {
368             for ( nframes_t i = control_output.size(); i--; )
369                 if ( &control_output[i] == p )
370                     return i;
372             return -1;
373         }
375     Chain *chain ( void ) const { return _chain; }
376     void chain ( Chain * v )
377         {
378             if ( _chain != v )
379             {
380                 _chain = v; 
382                 for ( int i = 0; i < ncontrol_inputs(); ++i )
383                 {
384                     control_input[i].update_osc_port();
385                 }
386             }
387         }
389     char *get_parameters ( void ) const;
390     void set_parameters ( const char * );
392     virtual bool initialize ( void ) { return true; }
394     /* for the given number of inputs, return how many outputs this
395      * plugin would have. -1 if this plugin can't support so many
396      * inputs. */
397     virtual int can_support_inputs ( int n ) = 0;
398     /* called by the chain whenever we need to adjust our input
399      * channel configuration, but only if can_support_inputs() returns
400      * true */
401     virtual bool configure_inputs ( int n ) = 0;
403     virtual void process ( nframes_t ) = 0;
405     /* called whenever the value of a control port is changed.
406        This can be used to take appropriate action from the GUI thread */
407     virtual void handle_control_changed ( Port * );
409     /* called whenever the name of the chain changes (usually because
410      * the name of the mixer strip changed). */
411     virtual void handle_chain_name_changed ();
413     virtual void handle_port_connection_change () {}
415 #define MODULE_CLONE_FUNC(class)                                \
416     virtual Module *clone_empty ( void ) const                  \
417         {                                                       \
418             return new class ();                                \
419         }
421     virtual Module *clone_empty ( void ) const { return NULL; }
422     Module *clone ( Chain *dest ) const;
423     Module *clone ( void ) const;
425 protected:
427     void draw_connections ( void );
428     void draw_label ( void );
429     void draw_box ( void );
431     virtual void draw ( void ) { Module::draw_box(); Module::draw_label(); }
432     virtual int handle ( int m );
434     virtual void get ( Log_Entry &e ) const;
435     virtual void set ( Log_Entry &e );
437 public:
439     void command_open_parameter_editor();
440     virtual void command_activate ( void );
441     virtual void command_deactivate ( void );
442     virtual void command_remove ( void );