@@ -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; | |||
} |
@@ -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 ); | |||
}; | |||
@@ -91,7 +91,7 @@ public: | |||
void draw ( void ) | |||
{ | |||
draw_box(); | |||
draw_box(x(),y(),w(),h()); | |||
Fl_Group::draw(); | |||
} | |||
@@ -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; | |||
{ | |||
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 ); | |||
p.connect_to( new float ); | |||
p.control_value_no_callback( 0 ); | |||
add_port( p ); | |||
} | |||
add_port( p ); | |||
} | |||
color( FL_BLACK ); | |||
end(); | |||
color( FL_BLACK ); | |||
log_create(); | |||
} | |||
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 ); | |||
} | |||
} |
@@ -19,13 +19,27 @@ | |||
#pragma once | |||
#include "Module.H" | |||
#include "JACK/Port.H" | |||
#include <vector> | |||
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_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"; } | |||
bool initialize ( void ); | |||
virtual const char *name ( void ) const { return "JACK"; } | |||
int can_support_inputs ( int ); | |||
bool configure_inputs ( int n ); | |||
bool configure_outputs ( int n ); | |||
virtual bool initialize ( void ); | |||
void add_output ( void ); | |||
virtual int can_support_inputs ( int ); | |||
virtual bool configure_inputs ( int n ); | |||
virtual bool configure_outputs ( int n ); | |||
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 ); | |||
@@ -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()); } | |||
}; |
@@ -33,6 +33,7 @@ | |||
#include "Mono_Pan_Module.H" | |||
#include "Meter_Module.H" | |||
#include "Plugin_Module.H" | |||
#include "AUX_Module.H" | |||
#include <FL/Fl_Menu_Button.H> | |||
#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( "Plugin", 0, 0, new unsigned long(4) ); | |||
/* Plugin_Module::add_plugins_to_menu( insert_menu ); */ | |||
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 ); | |||
// menu_set_callback( insert_menu, &Module::insert_menu_cb, (void*)this ); | |||
insert_menu->callback( &Module::insert_menu_cb, (void*)this ); | |||
} | |||
@@ -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; | |||
@@ -51,7 +51,7 @@ | |||
#include "Mono_Pan_Module.H" | |||
#include "Chain.H" | |||
#include "Mixer_Strip.H" | |||
#include "AUX_Module.H" | |||
#include "NSM.H" | |||
#include <signal.h> | |||
@@ -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 ); | |||
@@ -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 | |||