diff --git a/mixer/src/AUX_Module.C b/mixer/src/AUX_Module.C new file mode 100644 index 0000000..2718e9a --- /dev/null +++ b/mixer/src/AUX_Module.C @@ -0,0 +1,179 @@ + +/*******************************************************************************/ +/* Copyright (C) 2013 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include +#include "AUX_Module.H" +#include "dsp.h" + +/* The purpose of this module is to provide auxiliary outputs, with + * gain. This allows one to create a 'send' type topology without + * having to use an extra strip to control the 'send' gain. */ + +AUX_Module::AUX_Module ( ) : JACK_Module ( false ) +{ + is_default( false ); + + _number = 0; + + { + Port p( this, Port::INPUT, Port::CONTROL, "Gain (dB)" ); + p.hints.type = Port::Hints::LOGARITHMIC; + p.hints.ranged = true; + p.hints.minimum = -70.0f; + p.hints.maximum = 6.0f; + p.hints.default_value = 0.0f; + + p.connect_to( new float ); + p.control_value( p.hints.default_value ); + + add_port( p ); + } + + log_create(); + + copy_label( "Aux" ); +} + +AUX_Module::~AUX_Module ( ) +{ + configure_outputs(0); + delete (float*)control_input[0].buffer(); +} + + + +void +AUX_Module::get ( Log_Entry &e ) const +{ + e.add( ":number", number() ); + JACK_Module::get(e); +} + +void +AUX_Module::set ( Log_Entry &e ) +{ + for ( int i = 0; i < e.size(); ++i ) + { + const char *s, *v; + + e.get( i, &s, &v ); + + if ( ! ( strcmp( s, ":number" ) ) ) + { + number( atoi(v) ); + } + } + + JACK_Module::set(e); +} + +void +AUX_Module::number ( int n ) +{ + _number = n; + + char s[10]; + snprintf( s, sizeof(s), "aux-%c", 'A' + n ); + prefix( s ); + snprintf( s, sizeof(s), "Aux (%c)", 'A' + n ); + copy_label( s ); +} + +void +AUX_Module::process ( nframes_t nframes ) +{ + if ( !bypass() ) + { + float g = DB_CO( control_input[0].control_value() ); + + for ( unsigned int i = 0; i < audio_input.size(); ++i ) + { + if ( audio_input[i].connected() ) + buffer_copy_and_apply_gain( (sample_t*)jack_output[i].buffer( nframes ), (sample_t*)audio_input[i].buffer(), nframes, g ); + } + } + else + { + for ( unsigned int i = 0; i < audio_input.size(); ++i ) + { + if ( audio_input[i].connected() ) + buffer_fill_with_silence( (sample_t*)jack_output[i].buffer( nframes ), nframes ); + } + } +} + +void +AUX_Module::draw ( void ) +{ + int W = 5; + + Module::draw_box(x(),y(),w() - W,h()); + Module::draw_label(x(),y(),w() - W,h()); + + Module *m = this; + + fl_color( fl_darker( FL_FOREGROUND_COLOR ) ); + + int spacing, offset; + + spacing = h() / m->ninputs(); + offset = spacing / 2; + for ( int i = m->ninputs(); i--; ) + { + int xi = offset + ( spacing * i ); + fl_rectf( m->x() + m->w() - W, m->y() + xi, W, 2 ); + } +} + +bool +AUX_Module::configure_outputs ( int n ) +{ + int on = audio_output.size(); + + if ( n > on ) + { + for ( int i = on; i < n; ++i ) + { + add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); + } + } + else + { + for ( int i = on; i > n; --i ) + { + audio_output.back().disconnect(); + audio_output.pop_back(); + } + } + + return true; +} + +bool +AUX_Module::configure_inputs ( int n ) +{ + bool b = JACK_Module::configure_inputs( n ); + + if ( b ) + { + return configure_outputs( n ); + } + + return false; +} diff --git a/mixer/src/AUX_Module.H b/mixer/src/AUX_Module.H new file mode 100644 index 0000000..86f5994 --- /dev/null +++ b/mixer/src/AUX_Module.H @@ -0,0 +1,54 @@ + +/*******************************************************************************/ +/* Copyright (C) 2013 Jonathan Moore Liles */ +/* */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#pragma once + +#include "JACK_Module.H" + +class AUX_Module : public JACK_Module +{ + int _number; + +protected: + + virtual void get ( Log_Entry &e ) const; + virtual void set ( Log_Entry &e ); + +public: + + virtual const char *name ( void ) const { return "AUX"; } + + virtual bool configure_outputs ( int n ); + virtual bool configure_inputs ( int n ); + + void number ( int n ); + int number ( void ) const { return _number; } + + AUX_Module ( ); + virtual ~AUX_Module ( ); + + LOG_CREATE_FUNC( AUX_Module ); + +protected: + + virtual void draw ( void ); + virtual void process ( nframes_t nframes ); + +}; + diff --git a/mixer/src/Controller_Module.H b/mixer/src/Controller_Module.H index de29b85..506d235 100644 --- a/mixer/src/Controller_Module.H +++ b/mixer/src/Controller_Module.H @@ -91,7 +91,7 @@ public: void draw ( void ) { - draw_box(); + draw_box(x(),y(),w(),h()); Fl_Group::draw(); } diff --git a/mixer/src/JACK_Module.C b/mixer/src/JACK_Module.C index 812859b..60125b6 100644 --- a/mixer/src/JACK_Module.C +++ b/mixer/src/JACK_Module.C @@ -32,41 +32,47 @@ -JACK_Module::JACK_Module ( ) +JACK_Module::JACK_Module ( bool log ) : Module ( 50, 24, name() ) { - /* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */ + _prefix = 0; + + if ( log ) { - Port p( this, Port::INPUT, Port::CONTROL, "Inputs" ); - p.hints.type = Port::Hints::INTEGER; - p.hints.minimum = 0; - p.hints.maximum = 16; - p.hints.ranged = true; + /* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */ + { + Port p( this, Port::INPUT, Port::CONTROL, "Inputs" ); + p.hints.type = Port::Hints::INTEGER; + p.hints.minimum = 0; + p.hints.maximum = 16; + p.hints.ranged = true; + p.hints.visible = false; - p.connect_to( new float ); - p.control_value_no_callback( 0 ); + p.connect_to( new float ); + p.control_value_no_callback( 0 ); - add_port( p ); + add_port( p ); + } + + { + Port p( this, Port::INPUT, Port::CONTROL, "Outputs" ); + p.hints.type = Port::Hints::INTEGER; + p.hints.minimum = 0; + p.hints.maximum = 16; + p.hints.ranged = true; + p.hints.visible = false; + + p.connect_to( new float ); + p.control_value_no_callback( 0 ); + + add_port( p ); + } + color( FL_BLACK ); + + log_create(); } - { - Port p( this, Port::INPUT, Port::CONTROL, "Outputs" ); - p.hints.type = Port::Hints::INTEGER; - p.hints.minimum = 0; - p.hints.maximum = 16; - p.hints.ranged = true; - - p.connect_to( new float ); - p.control_value_no_callback( 0 ); - - add_port( p ); - } - - end(); - - color( FL_BLACK ); - - log_create(); + end(); } JACK_Module::~JACK_Module ( ) @@ -74,6 +80,8 @@ JACK_Module::~JACK_Module ( ) log_destroy(); configure_inputs( 0 ); configure_outputs( 0 ); + if ( _prefix ) + free( _prefix ); } @@ -93,19 +101,26 @@ JACK_Module::configure_inputs ( int n ) { for ( int i = on; i < n; ++i ) { - JACK::Port po( chain()->engine(), JACK::Port::Output, i ); + JACK::Port *po = NULL; - if ( ! po.activate() ) + if ( !_prefix ) + po = new JACK::Port( chain()->engine(), JACK::Port::Output, i ); + else + po = new JACK::Port( chain()->engine(), JACK::Port::Output, _prefix, i ); + + if ( ! po->activate() ) { - jack_port_activation_error( &po ); + jack_port_activation_error( po ); return false; } - if ( po.valid() ) + if ( po->valid() ) { add_port( Port( this, Port::INPUT, Port::AUDIO ) ); - jack_output.push_back( po ); + jack_output.push_back( *po ); } + + delete po; } } else @@ -119,7 +134,8 @@ JACK_Module::configure_inputs ( int n ) } } - control_input[0].control_value_no_callback( n ); + if ( is_default() ) + control_input[0].control_value_no_callback( n ); return true; } @@ -139,19 +155,26 @@ JACK_Module::configure_outputs ( int n ) { for ( int i = on; i < n; ++i ) { - JACK::Port po( chain()->engine(), JACK::Port::Input, i ); + JACK::Port *po = NULL; - if ( ! po.activate() ) + if ( !_prefix ) + po = new JACK::Port( chain()->engine(), JACK::Port::Input, i ); + else + po = new JACK::Port( chain()->engine(), JACK::Port::Input, _prefix, i ); + + if ( ! po->activate() ) { - jack_port_activation_error( &po ); + jack_port_activation_error( po ); return false; } - if ( po.valid() ) + if ( po->valid() ) { add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); - jack_input.push_back( po ); + jack_input.push_back( *po ); } + + delete po; } } else @@ -165,7 +188,8 @@ JACK_Module::configure_outputs ( int n ) } } - control_input[1].control_value_no_callback( n ); + if ( is_default() ) + control_input[1].control_value_no_callback( n ); return true; } @@ -230,10 +254,19 @@ void JACK_Module::process ( nframes_t nframes ) { for ( unsigned int i = 0; i < audio_input.size(); ++i ) + { if ( audio_input[i].connected() ) - buffer_copy( (sample_t*)jack_output[i].buffer( nframes ), (sample_t*)audio_input[i].buffer(), nframes ); + buffer_copy( (sample_t*)jack_output[i].buffer( nframes ), + (sample_t*)audio_input[i].buffer(), + nframes ); + + } for ( unsigned int i = 0; i < audio_output.size(); ++i ) + { if ( audio_output[i].connected() ) - buffer_copy( (sample_t*)audio_output[i].buffer(), (sample_t*)jack_input[i].buffer( nframes ), nframes ); + buffer_copy( (sample_t*)audio_output[i].buffer(), + (sample_t*)jack_input[i].buffer( nframes ), + nframes ); + } } diff --git a/mixer/src/JACK_Module.H b/mixer/src/JACK_Module.H index a7e3e33..a866ad0 100644 --- a/mixer/src/JACK_Module.H +++ b/mixer/src/JACK_Module.H @@ -19,13 +19,27 @@ #pragma once - #include "Module.H" #include "JACK/Port.H" #include class JACK_Module : public Module { + char *_prefix; + +protected: + + void prefix ( const char *s ) + { + if ( _prefix ) + free( _prefix ); + + _prefix = NULL; + + if ( s ) + _prefix = strdup( s ); + } + std::vector jack_input; std::vector jack_output; @@ -33,21 +47,19 @@ class JACK_Module : public Module public: - JACK_Module ( ); + JACK_Module ( bool log = true ); virtual ~JACK_Module ( ); - const char *name ( void ) const { return "JACK"; } + virtual const char *name ( void ) const { return "JACK"; } - bool initialize ( void ); + virtual bool initialize ( void ); - int can_support_inputs ( int ); - bool configure_inputs ( int n ); - bool configure_outputs ( int n ); + virtual int can_support_inputs ( int ); + virtual bool configure_inputs ( int n ); + virtual bool configure_outputs ( int n ); - void add_output ( void ); - - void handle_control_changed ( Port *p ); - void handle_chain_name_changed (); + virtual void handle_control_changed ( Port *p ); + virtual void handle_chain_name_changed (); LOG_CREATE_FUNC( JACK_Module ); diff --git a/mixer/src/Meter_Module.H b/mixer/src/Meter_Module.H index e85b283..6fe59fa 100644 --- a/mixer/src/Meter_Module.H +++ b/mixer/src/Meter_Module.H @@ -48,5 +48,5 @@ protected: virtual int handle ( int m ); virtual void process ( nframes_t nframes ); - virtual void draw ( void ) { draw_box(); } + virtual void draw ( void ) { draw_box(x(),y(),w(),h()); } }; diff --git a/mixer/src/Module.C b/mixer/src/Module.C index 9268bff..ec2d0ce 100644 --- a/mixer/src/Module.C +++ b/mixer/src/Module.C @@ -33,6 +33,7 @@ #include "Mono_Pan_Module.H" #include "Meter_Module.H" #include "Plugin_Module.H" +#include "AUX_Module.H" #include #include "FL/test_press.H" @@ -395,7 +396,11 @@ Module::set ( Log_Entry &e ) e.get( i, &s, &v ); - if ( ! strcmp( s, ":chain" ) ) + if ( ! ( strcmp( s, ":is_default" ) ) ) + { + is_default( atoi( v ) ); + } + else if ( ! strcmp( s, ":chain" ) ) { /* This trickiness is because we may need to know the name of our chain before we actually get added to it. */ @@ -421,10 +426,6 @@ Module::set ( Log_Entry &e ) { set_parameters( v ); } - else if ( ! ( strcmp( s, ":is_default" ) ) ) - { - is_default( atoi( v ) ); - } else if ( ! ( strcmp( s, ":active" ) ) ) { bypass( ! atoi( v ) ); @@ -527,17 +528,10 @@ Module::set_parameters ( const char *parameters ) void -Module::draw_box ( void ) +Module::draw_box ( int tx, int ty, int tw, int th ) { fl_color( fl_contrast( FL_FOREGROUND_COLOR, color() ) ); - int tw, th, tx, ty; - - tw = w(); - th = h(); - ty = y(); - tx = x(); - fl_push_clip( tx, ty, tw, th ); Fl_Color c = color(); @@ -575,10 +569,8 @@ Module::draw_box ( void ) } void -Module::draw_label ( void ) +Module::draw_label ( int tx, int ty, int tw, int th ) { - int tw, th, tx, ty; - bbox( tx, ty, tw, th ); const char *lp = label(); @@ -616,47 +608,53 @@ Module::draw_label ( void ) void Module::insert_menu_cb ( const Fl_Menu_ *m ) { - unsigned long id = Plugin_Chooser::plugin_chooser( this->ninputs() ); + const char * picked = m->mvalue()->label(); + + DMESSAGE("picked = %s", picked ); + Module *mod = NULL; - switch ( id ) + if ( !strcmp( picked, "Aux" ) ) { - case 0: - return; - case 1: - mod = new JACK_Module(); - break; - case 2: - mod = new Gain_Module(); - break; - case 3: - mod = new Meter_Module(); - break; - case 4: - mod = new Mono_Pan_Module(); - break; - default: + int n = 0; + for ( int i = 0; i < chain()->modules(); i++ ) { - Plugin_Module *m = new Plugin_Module(); - - m->load( id ); - - mod = m; + if ( !strcmp( chain()->module(i)->name(), "AUX" ) ) + n++; } + + AUX_Module *jm = new AUX_Module(); + jm->chain( chain() ); + jm->number( n ); + jm->configure_inputs( ninputs() ); + jm->configure_outputs( ninputs() ); + jm->initialize(); + + mod = jm; + } + else if ( !strcmp( picked, "Gain" ) ) + mod = new Gain_Module(); + else if ( !strcmp( picked, "Meter" ) ) + mod = new Meter_Module(); + else if ( !strcmp( picked, "Mono Pan" )) + mod = new Mono_Pan_Module(); + else if ( !strcmp(picked, "Plugin" )) + { + unsigned long id = Plugin_Chooser::plugin_chooser( this->ninputs() ); + + if ( id == 0 ) + return; + + Plugin_Module *m = new Plugin_Module(); + + m->load( id ); + + mod = m; } if ( mod ) { - if ( !strcmp( mod->name(), "JACK" ) ) - { - DMESSAGE( "Special casing JACK module" ); - JACK_Module *jm = (JACK_Module*)mod; - jm->chain( chain() ); - jm->configure_inputs( ninputs() ); - jm->configure_outputs( ninputs() ); - } - if ( ! chain()->insert( this, mod ) ) { fl_alert( "Cannot insert this module at this point in the chain" ); @@ -737,16 +735,12 @@ Module::menu ( void ) const { insert_menu = new Fl_Menu_Button( 0, 0, 0, 0 ); - insert_menu->add( "Gain", 0, 0, new unsigned long(2) ); - insert_menu->add( "Meter", 0, 0, new unsigned long(3) ); - insert_menu->add( "Mono Pan", 0, 0, new unsigned long(4) ); + insert_menu->add( "Gain", 0, 0 ); + insert_menu->add( "Meter", 0, 0 ); + insert_menu->add( "Mono Pan", 0, 0 ); + insert_menu->add( "Aux", 0, 0 ); + insert_menu->add( "Plugin", 0, 0 ); - insert_menu->add( "Plugin", 0, 0, new unsigned long(4) ); - - - /* Plugin_Module::add_plugins_to_menu( insert_menu ); */ - -// menu_set_callback( insert_menu, &Module::insert_menu_cb, (void*)this ); insert_menu->callback( &Module::insert_menu_cb, (void*)this ); } diff --git a/mixer/src/Module.H b/mixer/src/Module.H index 7d1abd2..87153dd 100644 --- a/mixer/src/Module.H +++ b/mixer/src/Module.H @@ -269,10 +269,10 @@ public: void bbox ( int &X, int &Y, int &W, int &H ) { - X = x() + 5; - Y = y() + 5; - W = w() - 10; - H = h() - 10; + X += + 5; + Y += 5; + W -= 10; + H -= 10; } Module ( int W, int H, const char *L = 0 ); @@ -435,10 +435,10 @@ public: protected: void draw_connections ( void ); - void draw_label ( void ); - void draw_box ( void ); + void draw_label ( int X, int Y, int W, int H ); + void draw_box ( int X, int Y, int W, int H ); - virtual void draw ( void ) { Module::draw_box(); Module::draw_label(); } + virtual void draw ( void ) { Module::draw_box(x(),y(),w(),h()); Module::draw_label(x(),y(),w(),h()); } virtual int handle ( int m ); virtual void get ( Log_Entry &e ) const; diff --git a/mixer/src/main.C b/mixer/src/main.C index a42ac3c..8d270e3 100644 --- a/mixer/src/main.C +++ b/mixer/src/main.C @@ -51,7 +51,7 @@ #include "Mono_Pan_Module.H" #include "Chain.H" #include "Mixer_Strip.H" - +#include "AUX_Module.H" #include "NSM.H" #include @@ -156,6 +156,7 @@ main ( int argc, char **argv ) LOG_REGISTER_CREATE( Mono_Pan_Module ); LOG_REGISTER_CREATE( Meter_Indicator_Module ); LOG_REGISTER_CREATE( Controller_Module ); + LOG_REGISTER_CREATE( AUX_Module ); signal( SIGPIPE, SIG_IGN ); diff --git a/mixer/wscript b/mixer/wscript index 5e6a3b6..2dd3806 100644 --- a/mixer/wscript +++ b/mixer/wscript @@ -49,6 +49,7 @@ src/DPM.C src/Engine/Engine.C src/Gain_Module.C src/JACK_Module.C +src/AUX_Module.C src/LADSPAInfo.C src/Meter_Indicator_Module.C src/Meter_Module.C