Mixer: Add new module "Aux" to allow creation of "send" topology without requiring an extra strip to control the send gain.

pull/59/head
Jonathan Moore Liles 2013-04-16 22:42:28 -07:00
parent 7900ef6add
commit fc5ef8f9f9
10 changed files with 393 additions and 119 deletions

179
mixer/src/AUX_Module.C Normal file
View File

@ -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 <FL/fl_draw.H>
#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;
}

54
mixer/src/AUX_Module.H Normal file
View File

@ -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 );
};

View File

@ -91,7 +91,7 @@ public:
void draw ( void ) void draw ( void )
{ {
draw_box(); draw_box(x(),y(),w(),h());
Fl_Group::draw(); Fl_Group::draw();
} }

View File

@ -32,41 +32,47 @@
JACK_Module::JACK_Module ( ) JACK_Module::JACK_Module ( bool log )
: Module ( 50, 24, name() ) : 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" ); /* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */
p.hints.type = Port::Hints::INTEGER; {
p.hints.minimum = 0; Port p( this, Port::INPUT, Port::CONTROL, "Inputs" );
p.hints.maximum = 16; p.hints.type = Port::Hints::INTEGER;
p.hints.ranged = true; p.hints.minimum = 0;
p.hints.maximum = 16;
p.hints.ranged = true;
p.hints.visible = false;
p.connect_to( new float ); p.connect_to( new float );
p.control_value_no_callback( 0 ); 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();
} }
{ end();
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();
} }
JACK_Module::~JACK_Module ( ) JACK_Module::~JACK_Module ( )
@ -74,6 +80,8 @@ JACK_Module::~JACK_Module ( )
log_destroy(); log_destroy();
configure_inputs( 0 ); configure_inputs( 0 );
configure_outputs( 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 ) 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; return false;
} }
if ( po.valid() ) if ( po->valid() )
{ {
add_port( Port( this, Port::INPUT, Port::AUDIO ) ); add_port( Port( this, Port::INPUT, Port::AUDIO ) );
jack_output.push_back( po ); jack_output.push_back( *po );
} }
delete po;
} }
} }
else 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; return true;
} }
@ -139,19 +155,26 @@ JACK_Module::configure_outputs ( int n )
{ {
for ( int i = on; i < n; ++i ) 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; return false;
} }
if ( po.valid() ) if ( po->valid() )
{ {
add_port( Port( this, Port::OUTPUT, Port::AUDIO ) ); add_port( Port( this, Port::OUTPUT, Port::AUDIO ) );
jack_input.push_back( po ); jack_input.push_back( *po );
} }
delete po;
} }
} }
else 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; return true;
} }
@ -230,10 +254,19 @@ void
JACK_Module::process ( nframes_t nframes ) JACK_Module::process ( nframes_t nframes )
{ {
for ( unsigned int i = 0; i < audio_input.size(); ++i ) for ( unsigned int i = 0; i < audio_input.size(); ++i )
{
if ( audio_input[i].connected() ) 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 ) for ( unsigned int i = 0; i < audio_output.size(); ++i )
{
if ( audio_output[i].connected() ) 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 );
}
} }

View File

@ -19,13 +19,27 @@
#pragma once #pragma once
#include "Module.H" #include "Module.H"
#include "JACK/Port.H" #include "JACK/Port.H"
#include <vector> #include <vector>
class JACK_Module : public Module 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::Port> jack_input; std::vector<JACK::Port> jack_input;
std::vector<JACK::Port> jack_output; std::vector<JACK::Port> jack_output;
@ -33,21 +47,19 @@ class JACK_Module : public Module
public: public:
JACK_Module ( ); JACK_Module ( bool log = true );
virtual ~JACK_Module ( ); 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 ); virtual int can_support_inputs ( int );
bool configure_inputs ( int n ); virtual bool configure_inputs ( int n );
bool configure_outputs ( int n ); virtual bool configure_outputs ( int n );
void add_output ( void ); virtual void handle_control_changed ( Port *p );
virtual void handle_chain_name_changed ();
void handle_control_changed ( Port *p );
void handle_chain_name_changed ();
LOG_CREATE_FUNC( JACK_Module ); LOG_CREATE_FUNC( JACK_Module );

View File

@ -48,5 +48,5 @@ protected:
virtual int handle ( int m ); virtual int handle ( int m );
virtual void process ( nframes_t nframes ); virtual void process ( nframes_t nframes );
virtual void draw ( void ) { draw_box(); } virtual void draw ( void ) { draw_box(x(),y(),w(),h()); }
}; };

View File

@ -33,6 +33,7 @@
#include "Mono_Pan_Module.H" #include "Mono_Pan_Module.H"
#include "Meter_Module.H" #include "Meter_Module.H"
#include "Plugin_Module.H" #include "Plugin_Module.H"
#include "AUX_Module.H"
#include <FL/Fl_Menu_Button.H> #include <FL/Fl_Menu_Button.H>
#include "FL/test_press.H" #include "FL/test_press.H"
@ -395,7 +396,11 @@ Module::set ( Log_Entry &e )
e.get( i, &s, &v ); 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 /* This trickiness is because we may need to know the name of
our chain before we actually get added to it. */ our chain before we actually get added to it. */
@ -421,10 +426,6 @@ Module::set ( Log_Entry &e )
{ {
set_parameters( v ); set_parameters( v );
} }
else if ( ! ( strcmp( s, ":is_default" ) ) )
{
is_default( atoi( v ) );
}
else if ( ! ( strcmp( s, ":active" ) ) ) else if ( ! ( strcmp( s, ":active" ) ) )
{ {
bypass( ! atoi( v ) ); bypass( ! atoi( v ) );
@ -527,17 +528,10 @@ Module::set_parameters ( const char *parameters )
void void
Module::draw_box ( void ) Module::draw_box ( int tx, int ty, int tw, int th )
{ {
fl_color( fl_contrast( FL_FOREGROUND_COLOR, color() ) ); 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_push_clip( tx, ty, tw, th );
Fl_Color c = color(); Fl_Color c = color();
@ -575,10 +569,8 @@ Module::draw_box ( void )
} }
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 ); bbox( tx, ty, tw, th );
const char *lp = label(); const char *lp = label();
@ -616,47 +608,53 @@ Module::draw_label ( void )
void void
Module::insert_menu_cb ( const Fl_Menu_ *m ) 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; Module *mod = NULL;
switch ( id ) if ( !strcmp( picked, "Aux" ) )
{ {
case 0: int n = 0;
return; for ( int i = 0; i < chain()->modules(); i++ )
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:
{ {
Plugin_Module *m = new Plugin_Module(); if ( !strcmp( chain()->module(i)->name(), "AUX" ) )
n++;
m->load( id );
mod = m;
} }
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 ( 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 ) ) if ( ! chain()->insert( this, mod ) )
{ {
fl_alert( "Cannot insert this module at this point in the chain" ); 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 = new Fl_Menu_Button( 0, 0, 0, 0 );
insert_menu->add( "Gain", 0, 0, new unsigned long(2) ); insert_menu->add( "Gain", 0, 0 );
insert_menu->add( "Meter", 0, 0, new unsigned long(3) ); insert_menu->add( "Meter", 0, 0 );
insert_menu->add( "Mono Pan", 0, 0, new unsigned long(4) ); 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 ); insert_menu->callback( &Module::insert_menu_cb, (void*)this );
} }

View File

@ -269,10 +269,10 @@ public:
void bbox ( int &X, int &Y, int &W, int &H ) void bbox ( int &X, int &Y, int &W, int &H )
{ {
X = x() + 5; X += + 5;
Y = y() + 5; Y += 5;
W = w() - 10; W -= 10;
H = h() - 10; H -= 10;
} }
Module ( int W, int H, const char *L = 0 ); Module ( int W, int H, const char *L = 0 );
@ -435,10 +435,10 @@ public:
protected: protected:
void draw_connections ( void ); void draw_connections ( void );
void draw_label ( void ); void draw_label ( int X, int Y, int W, int H );
void draw_box ( void ); 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 int handle ( int m );
virtual void get ( Log_Entry &e ) const; virtual void get ( Log_Entry &e ) const;

View File

@ -51,7 +51,7 @@
#include "Mono_Pan_Module.H" #include "Mono_Pan_Module.H"
#include "Chain.H" #include "Chain.H"
#include "Mixer_Strip.H" #include "Mixer_Strip.H"
#include "AUX_Module.H"
#include "NSM.H" #include "NSM.H"
#include <signal.h> #include <signal.h>
@ -156,6 +156,7 @@ main ( int argc, char **argv )
LOG_REGISTER_CREATE( Mono_Pan_Module ); LOG_REGISTER_CREATE( Mono_Pan_Module );
LOG_REGISTER_CREATE( Meter_Indicator_Module ); LOG_REGISTER_CREATE( Meter_Indicator_Module );
LOG_REGISTER_CREATE( Controller_Module ); LOG_REGISTER_CREATE( Controller_Module );
LOG_REGISTER_CREATE( AUX_Module );
signal( SIGPIPE, SIG_IGN ); signal( SIGPIPE, SIG_IGN );

View File

@ -49,6 +49,7 @@ src/DPM.C
src/Engine/Engine.C src/Engine/Engine.C
src/Gain_Module.C src/Gain_Module.C
src/JACK_Module.C src/JACK_Module.C
src/AUX_Module.C
src/LADSPAInfo.C src/LADSPAInfo.C
src/Meter_Indicator_Module.C src/Meter_Indicator_Module.C
src/Meter_Module.C src/Meter_Module.C