Compare commits
100 Commits
non-daw-v1
...
master
Author | SHA1 | Date |
---|---|---|
Jonathan Moore Liles | cdad26211b | |
Jonathan Moore Liles | ba30c91dad | |
Jonathan Moore Liles | 3aa5fc3c21 | |
Jonathan Moore Liles | ce633212bb | |
Jonathan Moore Liles | 0f8017a1ef | |
Jonathan Moore Liles | e909d9594b | |
Jonathan Moore Liles | f76de32c44 | |
Jonathan Moore Liles | 181dd64689 | |
Jonathan Moore Liles | c83aa8ebd8 | |
Jonathan Moore Liles | 0b23c871ee | |
Jonathan Moore Liles | e7c85f1a37 | |
Jonathan Moore Liles | 826bea3c30 | |
Jonathan Moore Liles | 393684f376 | |
Jonathan Moore Liles | ab469f8a23 | |
Jonathan Moore Liles | cf03ea1562 | |
Jonathan Moore Liles | cda92589e9 | |
Jonathan Moore Liles | f2aeb8a1f8 | |
Jonathan Moore Liles | 9f3181b9c7 | |
Jonathan Moore Liles | 20dce6c6e6 | |
Jonathan Moore Liles | 793a9c1d4b | |
Jonathan Moore Liles | f6e3ca8831 | |
Jonathan Moore Liles | 286dec338c | |
Jonathan Moore Liles | 00c02c7d74 | |
Jonathan Moore Liles | e46fac4470 | |
Jonathan Moore Liles | e0402a3b99 | |
Jonathan Moore Liles | 7c071c7422 | |
Jonathan Moore Liles | 9e82b28f07 | |
Jonathan Moore Liles | a0fd557baf | |
Jonathan Moore Liles | 82f9610ca8 | |
Jonathan Moore Liles | 1f0f01c0ad | |
Jonathan Moore Liles | e290c6ea60 | |
Jonathan Moore Liles | 9aa275e0af | |
Jonathan Moore Liles | f5b215066a | |
Jonathan Moore Liles | c808c53d6c | |
Jonathan Moore Liles | ae773fbf62 | |
Jonathan Moore Liles | 6bde5017f5 | |
Jonathan Moore Liles | da78618e5b | |
Jonathan Moore Liles | 368492f1c0 | |
Jonathan Moore Liles | 5ea0c24468 | |
Jonathan Moore Liles | d84416c196 | |
Jonathan Moore Liles | a59823e4c5 | |
Jonathan Moore Liles | 6673606262 | |
Jonathan Moore Liles | 54e8737a90 | |
Jonathan Moore Liles | 0157734a30 | |
Jonathan Moore Liles | 655ccf94c3 | |
Jonathan Moore Liles | a9846d1fc3 | |
Jonathan Moore Liles | ad6dbba07c | |
Jonathan Moore Liles | 362a153412 | |
Jonathan Moore Liles | 830823a226 | |
Jonathan Moore Liles | dd274db49b | |
Jonathan Moore Liles | 13c107ebcc | |
Jonathan Moore Liles | b1d59fc68a | |
Jonathan Moore Liles | e42b50814a | |
Jonathan Moore Liles | 628fef30e9 | |
Jonathan Moore Liles | 53ff9621ff | |
Jonathan Moore Liles | ee872467fb | |
Jonathan Moore Liles | 9987f78a72 | |
Jonathan Moore Liles | 7895b5ec7e | |
Jonathan Moore Liles | 83f7aa87f0 | |
Jonathan Moore Liles | 8d6885387b | |
Jonathan Moore Liles | 4c14cdd350 | |
Jonathan Moore Liles | b13d2da674 | |
Jonathan Moore Liles | 5378bbbb27 | |
Jonathan Moore Liles | b0d850ff76 | |
Jonathan Moore Liles | e5c08b3b58 | |
Jonathan Moore Liles | 572f94ad44 | |
Jonathan Moore Liles | e36a053b84 | |
Jonathan Moore Liles | 10bcd0c2d7 | |
Jonathan Moore Liles | cd4896b762 | |
Jonathan Moore Liles | 19b7927f08 | |
Jonathan Moore Liles | a2089421b1 | |
Jonathan Moore Liles | 5affbe4cef | |
Jonathan Moore Liles | 9b87c089d0 | |
Jonathan Moore Liles | cb3d4f9254 | |
Jonathan Moore Liles | 9330b07d99 | |
Jonathan Moore Liles | a578cbb8e1 | |
Jonathan Moore Liles | 820298f4dd | |
Jonathan Moore Liles | 992e55bf0d | |
Jonathan Moore Liles | 81e24f4239 | |
Jonathan Moore Liles | 6bee859f6f | |
Jonathan Moore Liles | 455cc0f3ad | |
Jonathan Moore Liles | 8109ff7bc0 | |
Jonathan Moore Liles | 1a07dda5d9 | |
Jonathan Moore Liles | b3ffef17b5 | |
Jonathan Moore Liles | a7a7b967c8 | |
falkTX | 55de086026 | |
Jonathan Moore Liles | 7565be85fb | |
Jonathan Moore Liles | 0106604073 | |
Jonathan Moore Liles | 97d12322f5 | |
Jonathan Moore Liles | bbe8386499 | |
Nils | aa940df662 | |
Jonathan Moore Liles | d958df0486 | |
Olivier Humbert | c15bfa85fd | |
Olivier Humbert | 7f0cc1d733 | |
Olivier Humbert | 911a9bded4 | |
Olivier Humbert | d280f9391f | |
Jonathan Moore Liles | ea6ff30cea | |
Jonathan Moore Liles | d0432caa0b | |
Jonathan Moore Liles | 9e9f90f2f0 | |
Jonathan Moore Liles | 5ae43bb27c |
|
@ -30,6 +30,7 @@
|
|||
class Fl_Sometimes_Input : public Fl_Input
|
||||
{
|
||||
Fl_Boxtype _up_box;
|
||||
char *_text;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -53,7 +54,7 @@ public:
|
|||
{
|
||||
fl_draw_box( up_box(), x(), y(), w(), h(), color() );
|
||||
|
||||
Fl_Color c = fl_contrast( textcolor(), color() );
|
||||
Fl_Color c = textcolor();// fl_contrast( textcolor(), color() );
|
||||
|
||||
fl_color( active_r() ? c : fl_inactive( c ) );
|
||||
|
||||
|
@ -80,19 +81,30 @@ public:
|
|||
case FL_KEYDOWN:
|
||||
{
|
||||
if ( ( Fl::event_key() == FL_Enter ||
|
||||
Fl::event_key() == FL_Tab ) )
|
||||
Fl::event_key() == FL_Tab ) )
|
||||
{
|
||||
do_callback();
|
||||
free( _text );
|
||||
Fl::focus( NULL );
|
||||
r = 1;
|
||||
}
|
||||
else if ( Fl::event_key() == FL_Escape )
|
||||
{
|
||||
value( _text );
|
||||
Fl::focus( NULL );
|
||||
|
||||
r = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FL_FOCUS:
|
||||
_text = strdup( value() );
|
||||
redraw();
|
||||
r = 1;
|
||||
break;
|
||||
case FL_UNFOCUS:
|
||||
do_callback();
|
||||
_text = NULL;
|
||||
redraw();
|
||||
r = 1;
|
||||
break;
|
||||
case FL_PUSH:
|
||||
|
|
2
lib/ntk
2
lib/ntk
|
@ -1 +1 @@
|
|||
Subproject commit 92365eca0f9a6f054abc70489c009aba0fcde0ff
|
||||
Subproject commit 720d8d33200ebd030df700c6c7a5a9cdf4581c03
|
|
@ -1,6 +1,7 @@
|
|||
[Desktop Entry]
|
||||
Name=Non Mixer
|
||||
Comment=Modular Digital Audio Workstation - Mixer
|
||||
Comment[fr]=Station de travail audio-numérique modulaire - Mixeur
|
||||
Exec=@BIN_PATH@/non-mixer
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
|
|
@ -29,8 +29,6 @@ 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::LINEAR;
|
||||
|
@ -49,8 +47,6 @@ AUX_Module::AUX_Module ( ) : JACK_Module ( false )
|
|||
|
||||
color( FL_DARK1 );
|
||||
|
||||
copy_label( "Aux" );
|
||||
|
||||
smoothing.sample_rate( sample_rate() );
|
||||
}
|
||||
|
||||
|
@ -62,35 +58,10 @@ AUX_Module::~AUX_Module ( )
|
|||
|
||||
|
||||
|
||||
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;
|
||||
JACK_Module::number(n);
|
||||
|
||||
char s[10];
|
||||
snprintf( s, sizeof(s), "aux-%c", 'A' + n );
|
||||
|
|
|
@ -24,17 +24,12 @@
|
|||
|
||||
class AUX_Module : public JACK_Module
|
||||
{
|
||||
int _number;
|
||||
|
||||
Value_Smoothing_Filter smoothing;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void get ( Log_Entry &e ) const;
|
||||
virtual void set ( Log_Entry &e );
|
||||
|
||||
public:
|
||||
|
||||
virtual void number ( int v );
|
||||
|
||||
virtual const char *name ( void ) const { return "AUX"; }
|
||||
|
||||
int can_support_inputs ( int n ) { return n > 0 ? n : -1; }
|
||||
|
@ -42,9 +37,6 @@ public:
|
|||
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 ( );
|
||||
|
||||
|
|
|
@ -174,17 +174,23 @@ Chain::~Chain ( )
|
|||
|
||||
_deleting = true;
|
||||
|
||||
client()->lock();
|
||||
/* FIXME: client may already be dead during teardown if group is destroyed first. */
|
||||
if ( client() )
|
||||
client()->lock();
|
||||
|
||||
for ( unsigned int i = scratch_port.size(); i--; )
|
||||
free( (sample_t*)scratch_port[i].buffer() );
|
||||
scratch_port.clear();
|
||||
|
||||
/* if we leave this up to FLTK, it will happen after we've
|
||||
already destroyed the client */
|
||||
modules_pack->clear();
|
||||
modules_pack = NULL;
|
||||
controls_pack->clear();
|
||||
modules_pack = NULL;
|
||||
|
||||
client()->unlock();
|
||||
if ( client() )
|
||||
client()->unlock();
|
||||
}
|
||||
|
||||
Group *
|
||||
|
@ -322,10 +328,17 @@ Chain::remove ( Controller_Module *m )
|
|||
}
|
||||
|
||||
void
|
||||
Chain::send_feedback ( void )
|
||||
Chain::send_feedback ( bool force )
|
||||
{
|
||||
for ( int i = 0; i < modules(); i++ )
|
||||
module(i)->send_feedback();
|
||||
module(i)->send_feedback( force );
|
||||
}
|
||||
|
||||
void
|
||||
Chain::schedule_feedback ( void )
|
||||
{
|
||||
for ( int i = 0; i < modules(); i++ )
|
||||
module(i)->schedule_feedback();
|
||||
}
|
||||
|
||||
/* remove a module from the chain. this isn't guaranteed to succeed,
|
||||
|
@ -365,7 +378,7 @@ Chain::configure_ports ( void )
|
|||
client()->lock();
|
||||
|
||||
for ( int i = 0; i < modules(); ++i )
|
||||
{
|
||||
{
|
||||
module( i )->configure_inputs( nouts );
|
||||
nouts = module( i )->noutputs();
|
||||
}
|
||||
|
@ -376,17 +389,21 @@ Chain::configure_ports ( void )
|
|||
|
||||
if ( scratch_port.size() < req_buffers )
|
||||
{
|
||||
for ( unsigned int i = scratch_port.size(); i--; )
|
||||
free(scratch_port[i].buffer());
|
||||
scratch_port.clear();
|
||||
|
||||
for ( unsigned int i = 0; i < req_buffers; ++i )
|
||||
{
|
||||
Module::Port p( NULL, Module::Port::OUTPUT, Module::Port::AUDIO );
|
||||
for ( unsigned int i = req_buffers - scratch_port.size(); i--; )
|
||||
{
|
||||
Module::Port p( NULL, Module::Port::OUTPUT, Module::Port::AUDIO );
|
||||
p.set_buffer( buffer_alloc( client()->nframes() ) );
|
||||
buffer_fill_with_silence( (sample_t*)p.buffer(), client()->nframes() );
|
||||
scratch_port.push_back( p );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( scratch_port.size() > req_buffers )
|
||||
{
|
||||
for ( unsigned int i = scratch_port.size() - req_buffers; i--; )
|
||||
{
|
||||
free(scratch_port.back().buffer());
|
||||
scratch_port.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
build_process_queue();
|
||||
|
@ -445,8 +462,8 @@ Chain::get_module_instance_number ( Module *m )
|
|||
{
|
||||
int n = 0;
|
||||
|
||||
for ( int i = 0; i < modules() && module(i) != m; ++i )
|
||||
if ( ! strcmp( module(i)->label(), m->label() ) )
|
||||
for ( int i = 0; i < modules(); ++i )
|
||||
if ( ! strcmp( module(i)->base_label(), m->base_label() ) )
|
||||
n++;
|
||||
|
||||
return n;
|
||||
|
@ -534,6 +551,8 @@ Chain::name ( const char *name )
|
|||
if ( strip()->group() )
|
||||
{
|
||||
if ( strip()->group()->single() )
|
||||
/* we are the owner of this group and its only member, so
|
||||
* rename it */
|
||||
strip()->group()->name(name);
|
||||
}
|
||||
|
||||
|
@ -566,6 +585,13 @@ Chain::insert ( Module *m, Module *n )
|
|||
{
|
||||
client()->lock();
|
||||
|
||||
Module::sample_rate( client()->sample_rate() );
|
||||
n->resize_buffers( client()->nframes() );
|
||||
|
||||
/* inserting a new instance */
|
||||
if ( -1 == n->number() )
|
||||
n->number( get_module_instance_number( n ) );
|
||||
|
||||
if ( !m )
|
||||
{
|
||||
if ( modules() == 0 && n->can_support_inputs( 0 ) >= 0 )
|
||||
|
@ -713,6 +739,8 @@ Chain::add_to_process_queue ( Module *m )
|
|||
void
|
||||
Chain::build_process_queue ( void )
|
||||
{
|
||||
client()->lock();
|
||||
|
||||
process_queue.clear();
|
||||
|
||||
for ( int i = 0; i < modules(); ++i )
|
||||
|
@ -780,6 +808,8 @@ Chain::build_process_queue ( void )
|
|||
/* delete[] s; */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
client()->unlock();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -901,9 +931,9 @@ Chain::process ( nframes_t nframes )
|
|||
{
|
||||
for ( std::list<Module*>::const_iterator i = process_queue.begin(); i != process_queue.end(); ++i )
|
||||
{
|
||||
Module *m = *i;
|
||||
|
||||
m->process( nframes );
|
||||
Module *m = *i;
|
||||
|
||||
m->process( nframes );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -927,7 +957,7 @@ Chain::buffer_size ( nframes_t nframes )
|
|||
int
|
||||
Chain::sample_rate_change ( nframes_t nframes )
|
||||
{
|
||||
Module::set_sample_rate ( nframes );
|
||||
Module::sample_rate ( nframes );
|
||||
for ( int i = 0; i < modules(); ++i )
|
||||
{
|
||||
Module *m = module(i);
|
||||
|
|
|
@ -100,8 +100,9 @@ public:
|
|||
const char *name ( void ) const { return _name; }
|
||||
void name ( const char *name );
|
||||
|
||||
void send_feedback ( void );
|
||||
|
||||
void send_feedback ( bool force );
|
||||
void schedule_feedback ( void );
|
||||
|
||||
int get_module_instance_number ( Module *m );
|
||||
|
||||
void configure_ports ( void );
|
||||
|
@ -109,7 +110,7 @@ public:
|
|||
|
||||
bool can_support_input_channels ( int n );
|
||||
|
||||
int modules ( void ) const { return modules_pack->children(); }
|
||||
int modules ( void ) const { return modules_pack ? modules_pack->children() : 0; }
|
||||
Module *module ( int n ) const { return (Module*)modules_pack->child( n ); }
|
||||
void remove ( Controller_Module *m );
|
||||
void remove ( Module *m );
|
||||
|
|
|
@ -50,6 +50,9 @@
|
|||
|
||||
bool Controller_Module::learn_by_number = false;
|
||||
bool Controller_Module::_learn_mode = false;
|
||||
|
||||
Controller_Module* Controller_Module::_learning_control = NULL;
|
||||
|
||||
|
||||
|
||||
void
|
||||
|
@ -96,8 +99,6 @@ Controller_Module::~Controller_Module ( )
|
|||
|
||||
/* shutdown JACK port, if we have one */
|
||||
mode( GUI );
|
||||
|
||||
// disconnect();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -188,7 +189,6 @@ Controller_Module::set ( Log_Entry &e )
|
|||
{
|
||||
connect_to( &module->control_input[port] );
|
||||
module->chain()->add_control( this );
|
||||
label( module->control_input[port].name() );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < e.size(); ++i )
|
||||
|
@ -219,8 +219,15 @@ Controller_Module::mode ( Mode m )
|
|||
Port *p = control_output[0].connected_port();
|
||||
|
||||
char prefix[512];
|
||||
snprintf( prefix, sizeof(prefix), "CV-%s", p->name() );
|
||||
|
||||
|
||||
const Module *m = p->module();
|
||||
|
||||
if ( m->number() >= 0 )
|
||||
/* we do it this way now to ensure uniqueness */
|
||||
snprintf( prefix, sizeof(prefix), "CV-%s/%s", m->label(), p->name() );
|
||||
else
|
||||
snprintf( prefix, sizeof(prefix), "CV-%s", p->name() );
|
||||
|
||||
add_aux_cv_input( prefix, 0 );
|
||||
|
||||
chain()->client()->unlock();
|
||||
|
@ -403,6 +410,19 @@ Controller_Module::connect_spatializer_to ( Module *m )
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Controller_Module::apply_label ( Port *p, Fl_Widget *o )
|
||||
{
|
||||
char path[256];
|
||||
|
||||
if ( is_default() )
|
||||
snprintf( path, sizeof(path) - 1, "%s", p->name() );
|
||||
else
|
||||
snprintf( path, sizeof(path) - 1, "%s/%s", p->module()->label(), p->name() );
|
||||
|
||||
o->copy_label(path);
|
||||
}
|
||||
|
||||
void
|
||||
Controller_Module::connect_to ( Port *p )
|
||||
{
|
||||
|
@ -414,7 +434,7 @@ Controller_Module::connect_to ( Port *p )
|
|||
|
||||
if ( p->hints.type == Module::Port::Hints::BOOLEAN )
|
||||
{
|
||||
Fl_Button *o = new Fl_Button( 0, 0, 40, 40, p->name() );
|
||||
Fl_Button *o = new Fl_Button( 0, 0, 40, 40 );
|
||||
w = o;
|
||||
o->type( FL_TOGGLE_BUTTON );
|
||||
o->value( p->control_value() );
|
||||
|
@ -428,7 +448,8 @@ Controller_Module::connect_to ( Port *p )
|
|||
else if ( p->hints.type == Module::Port::Hints::INTEGER )
|
||||
{
|
||||
|
||||
Fl_Counter *o = new Fl_Counter(0, 0, 58, 24, p->name() );
|
||||
Fl_Counter *o = new Fl_Counter(0, 0, 58, 24 );
|
||||
|
||||
control = o;
|
||||
w = o;
|
||||
|
||||
|
@ -448,7 +469,8 @@ Controller_Module::connect_to ( Port *p )
|
|||
// else if ( p->hints.type == Module::Port::Hints::LOGARITHMIC )
|
||||
else
|
||||
{
|
||||
Fl_Value_SliderX *o = new Fl_Value_SliderX(0, 0, 30, 250, p->name() );
|
||||
Fl_Value_SliderX *o = new Fl_Value_SliderX(0, 0, 30, 250 );
|
||||
|
||||
control = o;
|
||||
w = o;
|
||||
|
||||
|
@ -512,6 +534,8 @@ Controller_Module::connect_to ( Port *p )
|
|||
/* _type = KNOB; */
|
||||
/* } */
|
||||
|
||||
apply_label(p,control);
|
||||
|
||||
control_value = p->control_value();
|
||||
|
||||
w->clear_visible_focus();
|
||||
|
@ -838,10 +862,27 @@ Controller_Module::draw ( void )
|
|||
|
||||
if ( learn_mode() )
|
||||
{
|
||||
fl_rectf( x(),y(),w(),h(), fl_color_add_alpha( FL_MAGENTA, 50 ) );
|
||||
fl_rectf( x(),y(),w(),h(),
|
||||
fl_color_add_alpha(
|
||||
this == _learning_control
|
||||
? FL_RED
|
||||
: FL_GREEN,
|
||||
60 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_Module::learning_callback ( void *userdata )
|
||||
{
|
||||
((Controller_Module*)userdata)->learning_callback();
|
||||
}
|
||||
|
||||
void Controller_Module::learning_callback ( void )
|
||||
{
|
||||
_learning_control = NULL;
|
||||
this->redraw();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Controller_Module::handle ( int m )
|
||||
{
|
||||
|
@ -854,6 +895,10 @@ Controller_Module::handle ( int m )
|
|||
{
|
||||
tooltip( "Now learning control. Move the desired control on your controller" );
|
||||
|
||||
_learning_control = this;
|
||||
|
||||
this->redraw();
|
||||
|
||||
//connect_to( &module->control_input[port] );
|
||||
Port *p = control_output[0].connected_port();
|
||||
|
||||
|
@ -863,7 +908,7 @@ Controller_Module::handle ( int m )
|
|||
|
||||
DMESSAGE( "Will learn %s", path );
|
||||
|
||||
mixer->osc_endpoint->learn( path );
|
||||
mixer->osc_endpoint->learn( path, Controller_Module::learning_callback, this );
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -47,9 +47,13 @@ class Controller_Module : public Module
|
|||
void add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix );
|
||||
void add_osc_connections_to_menu ( Fl_Menu_Button *m, const char *prefix );
|
||||
|
||||
static void learning_callback ( void *userdata );
|
||||
void learning_callback ( void );
|
||||
|
||||
public:
|
||||
|
||||
static bool _learn_mode;
|
||||
static Controller_Module *_learning_control;
|
||||
|
||||
static bool learn_by_number;
|
||||
static bool learn_mode ( void ) { return _learn_mode; }
|
||||
|
@ -115,6 +119,7 @@ protected:
|
|||
|
||||
private:
|
||||
|
||||
void apply_label ( Port *p, Fl_Widget *o );
|
||||
void maybe_create_panner ( void );
|
||||
char *generate_osc_path ( void );
|
||||
void change_osc_path ( char *path );
|
||||
|
|
224
mixer/src/DPM.C
224
mixer/src/DPM.C
|
@ -43,33 +43,44 @@ DPM::DPM ( int X, int Y, int W, int H, const char *L ) :
|
|||
|
||||
_last_drawn_hi_segment = 0;
|
||||
|
||||
pixels_per_segment( 4 );
|
||||
pixels_per_segment( 5 );
|
||||
|
||||
type( FL_VERTICAL );
|
||||
|
||||
// resize( X, Y, W, H );
|
||||
|
||||
dim( 0.85f );
|
||||
dim( 0.95f );
|
||||
|
||||
box( FL_FLAT_BOX );
|
||||
|
||||
color(FL_BLACK);
|
||||
|
||||
/* color( fl_color_average( FL_BLACK, FL_BACKGROUND_COLOR, 0.25f ) ); */
|
||||
|
||||
/* initialize gradients */
|
||||
if ( DPM::_gradient[ 0 ] == 0 )
|
||||
{
|
||||
int breaks[] = {0,60,70,80,90,127};
|
||||
int breaks[] = {0,80,90,110,127};
|
||||
|
||||
Fl_Color cols[] = {
|
||||
fl_rgb_color( 45,58,64),
|
||||
fl_rgb_color( 84,181,195 ),
|
||||
fl_rgb_color( 122,200,211 ),
|
||||
fl_rgb_color( 178,213,212 ),
|
||||
fl_rgb_color( 209,213,179 ),
|
||||
fl_rgb_color( 250, 40, 30 )
|
||||
Fl_Color cols[] = {
|
||||
fl_darker( FL_CYAN ),
|
||||
FL_CYAN,
|
||||
fl_lighter( FL_CYAN ),
|
||||
fl_color_average( FL_YELLOW, FL_RED, 0.50f ),
|
||||
FL_RED
|
||||
};
|
||||
|
||||
DPM::blend( 6, breaks, cols );
|
||||
}
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
{
|
||||
cols[i] = fl_color_average( cols[i], FL_BACKGROUND_COLOR, 0.60f );
|
||||
}
|
||||
|
||||
box( FL_FLAT_BOX );
|
||||
color( FL_BACKGROUND_COLOR );
|
||||
DPM::blend( 5,
|
||||
breaks,
|
||||
cols,
|
||||
color() );
|
||||
|
||||
}
|
||||
|
||||
resize( X,Y,W,H);
|
||||
}
|
||||
|
@ -78,40 +89,40 @@ DPM::DPM ( int X, int Y, int W, int H, const char *L ) :
|
|||
const int marks [] = { -70, -50, -40, -30, -20, -10, -3, 0, 4 };
|
||||
|
||||
void
|
||||
DPM::draw_label ( void )
|
||||
DPM::public_draw_label ( int X, int Y, int W, int H )
|
||||
{
|
||||
|
||||
/* dirty hack */
|
||||
if ( parent()->child( 0 ) == this )
|
||||
fl_push_clip(X,Y,W,H);
|
||||
fl_rectf( X,Y,W,H, FL_BACKGROUND_COLOR);
|
||||
|
||||
fl_font( FL_TIMES, 8 );
|
||||
fl_color( active_r() ? FL_FOREGROUND_COLOR : fl_inactive( FL_FOREGROUND_COLOR ) );
|
||||
/* draw marks */
|
||||
char pat[5];
|
||||
if ( type() == FL_HORIZONTAL )
|
||||
{
|
||||
fl_font( FL_TIMES, 8 );
|
||||
fl_color( FL_WHITE );
|
||||
/* draw marks */
|
||||
char pat[5];
|
||||
if ( type() == FL_HORIZONTAL )
|
||||
{
|
||||
for ( int i = sizeof( marks ) / sizeof( marks[0] ); i-- ; )
|
||||
{
|
||||
sprintf( pat, "%d", marks[ i ] );
|
||||
for ( int i = sizeof( marks ) / sizeof( marks[0] ); i-- ; )
|
||||
{
|
||||
sprintf( pat, "%d", marks[ i ] );
|
||||
|
||||
int v = w() * deflection( (float)marks[ i ] );
|
||||
int v = w() * deflection( (float)marks[ i ] );
|
||||
|
||||
fl_draw( pat, x() + v, (y() + h() + 8), 19, 8, (Fl_Align) (FL_ALIGN_RIGHT | FL_ALIGN_TOP) );
|
||||
}
|
||||
fl_draw( pat, X + v, (Y + H + 8), W, 8, (Fl_Align) (FL_ALIGN_RIGHT | FL_ALIGN_TOP) );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = sizeof( marks ) / sizeof( marks[0] ); i-- ; )
|
||||
{
|
||||
sprintf( pat, "%d", marks[ i ] );
|
||||
|
||||
int v = h() * deflection( (float)marks[ i ] );
|
||||
|
||||
fl_draw( pat, x() - 20, (y() + h() - 4) - v, 19, 8, (Fl_Align) (FL_ALIGN_RIGHT | FL_ALIGN_TOP) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = sizeof( marks ) / sizeof( marks[0] ); i-- ; )
|
||||
{
|
||||
sprintf( pat, "%d", marks[ i ] );
|
||||
|
||||
int v = h() * deflection( (float)marks[ i ] );
|
||||
|
||||
fl_draw( pat, X, (Y + H - 4) - v, W, 8, (Fl_Align) (FL_ALIGN_RIGHT | FL_ALIGN_TOP) );
|
||||
}
|
||||
}
|
||||
|
||||
fl_pop_clip();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -135,12 +146,17 @@ DPM::resize ( int X, int Y, int W, int H )
|
|||
|
||||
void DPM::bbox ( int &X, int &Y, int &W, int &H )
|
||||
{
|
||||
X = x() + 2;
|
||||
Y = y() + 2;
|
||||
W = w() - 4;
|
||||
H = h() - 4;
|
||||
/* X = x() + 2; */
|
||||
/* Y = y() + 2; */
|
||||
/* W = w() - 4; */
|
||||
/* H = h() - 4; */
|
||||
X = x();
|
||||
Y = y();
|
||||
W = w();
|
||||
H = h();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DPM::draw ( void )
|
||||
{
|
||||
|
@ -149,7 +165,7 @@ DPM::draw ( void )
|
|||
|
||||
int X,Y,W,H;
|
||||
bbox(X,Y,W,H);
|
||||
|
||||
|
||||
int v = pos( value() );
|
||||
int pv = pos( peak() );
|
||||
|
||||
|
@ -159,15 +175,17 @@ DPM::draw ( void )
|
|||
/* int bh = _pixels_per_segment; */
|
||||
/* int bw = _pixels_per_segment; */
|
||||
int bw = W / _segments;
|
||||
|
||||
if ( 0 == fl_not_clipped(X,Y,W,H ) )
|
||||
return;
|
||||
|
||||
if ( damage() & FL_DAMAGE_ALL )
|
||||
{
|
||||
draw_label();
|
||||
/* draw_label(); */
|
||||
|
||||
draw_box( FL_FLAT_BOX, x(), y(), w(), h(), FL_DARK1 );
|
||||
draw_box( box(), X, Y, W, H, color() );
|
||||
}
|
||||
|
||||
fl_push_clip( X, Y, W, H );
|
||||
|
||||
|
||||
const int active = active_r();
|
||||
|
||||
|
@ -176,12 +194,16 @@ DPM::draw ( void )
|
|||
/* only draw as many segments as necessary */
|
||||
if ( damage() == FL_DAMAGE_USER1 )
|
||||
{
|
||||
if ( v > _last_drawn_hi_segment )
|
||||
if ( v == _last_drawn_hi_segment )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if ( v > _last_drawn_hi_segment )
|
||||
{
|
||||
hi = v;
|
||||
lo = _last_drawn_hi_segment;
|
||||
}
|
||||
else
|
||||
else if ( v < _last_drawn_hi_segment )
|
||||
{
|
||||
hi = _last_drawn_hi_segment;
|
||||
lo = v;
|
||||
|
@ -195,62 +217,50 @@ DPM::draw ( void )
|
|||
|
||||
_last_drawn_hi_segment = v;
|
||||
|
||||
for ( int p = lo; p <= hi; p++ )
|
||||
fl_push_clip( X, Y, W, H );
|
||||
|
||||
for ( int p = lo; p <= hi + 1; ++p )
|
||||
{
|
||||
Fl_Color c;
|
||||
|
||||
if ( p <= v )
|
||||
{
|
||||
if ( p == clipv )
|
||||
c = fl_color_average( FL_YELLOW, div_color( p ), 0.40 );
|
||||
else
|
||||
c = div_color( p );
|
||||
}
|
||||
else if ( p == pv )
|
||||
c = div_color( p );
|
||||
else
|
||||
c = dim_div_color( p );
|
||||
|
||||
if ( ! active )
|
||||
c = fl_inactive( c );
|
||||
|
||||
int yy = 0;
|
||||
int xx = 0;
|
||||
|
||||
if ( type() == FL_HORIZONTAL )
|
||||
{
|
||||
xx = X + p * bw;
|
||||
fl_rectf( X + (p * bw), Y, bw, H, c );
|
||||
}
|
||||
else
|
||||
{
|
||||
yy = Y + H - ((p+1) * bh);
|
||||
fl_rectf( X, yy, W, bh, c );
|
||||
}
|
||||
|
||||
if ( _pixels_per_segment >= 3 )
|
||||
{
|
||||
fl_color( FL_DARK1 );
|
||||
|
||||
if ( type() == FL_HORIZONTAL )
|
||||
{
|
||||
fl_line( xx, Y, xx, Y + H - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
fl_line( X, yy, X + W - 1, yy );
|
||||
}
|
||||
}
|
||||
|
||||
/* } */
|
||||
/* else */
|
||||
/* { */
|
||||
/* if ( type() == FL_HORIZONTAL ) */
|
||||
/* fl_draw_box( box(), X + (p * bw), Y, bw, H, c ); */
|
||||
/* else */
|
||||
/* fl_draw_box( box(), X, Y + H - ((p + 1) * bh), W, bh, c ); */
|
||||
/* } */
|
||||
Fl_Color c;
|
||||
|
||||
if ( p <= v || p == pv )
|
||||
{
|
||||
if ( p == clipv )
|
||||
c = fl_color_average( FL_YELLOW, div_color( p ), 0.40 );
|
||||
else
|
||||
c = div_color( p );
|
||||
}
|
||||
else
|
||||
c = fl_darker( FL_BACKGROUND_COLOR );//FL_DARK1; // fl_color_average( FL_BACKGROUND_COLOR, FL_BLACK, 0.50f );// FL_BACKGROUND_COLOR; //dim_div_color( p );
|
||||
|
||||
if ( ! active )
|
||||
c = fl_inactive( c );
|
||||
|
||||
int yy = 0;
|
||||
int xx = 0;
|
||||
|
||||
if ( type() == FL_HORIZONTAL )
|
||||
{
|
||||
xx = X + p * bw;
|
||||
fl_rectf( xx + 1, Y, bw - 1, H, c );
|
||||
}
|
||||
else
|
||||
{
|
||||
yy = Y + H - ((p+1) * bh);
|
||||
fl_rectf( X, yy + 1, W, bh - 1, c );
|
||||
}
|
||||
}
|
||||
|
||||
fl_pop_clip();
|
||||
}
|
||||
|
||||
void
|
||||
DPM::update ( void )
|
||||
{
|
||||
/* do falloff */
|
||||
float f = value() - 0.33f;
|
||||
if ( f < -80.0f )
|
||||
f = -80.0f;
|
||||
|
||||
value(f);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,7 @@ class DPM : public Meter
|
|||
int _segments;
|
||||
int _pixels_per_segment;
|
||||
int _last_drawn_hi_segment;
|
||||
|
||||
float _value;
|
||||
|
||||
|
||||
int pos ( float v )
|
||||
{
|
||||
float pv = deflection( v ) * ( _segments - 1 );
|
||||
|
@ -55,44 +53,43 @@ class DPM : public Meter
|
|||
{
|
||||
return _dim_gradient[ i * 127 / _segments ];
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
virtual void draw_label ( void );
|
||||
virtual void draw ( void );
|
||||
virtual void resize ( int, int, int, int );
|
||||
/* virtual void draw_label ( void ); */
|
||||
|
||||
void bbox ( int &X, int &Y, int &W, int &H );
|
||||
|
||||
public:
|
||||
|
||||
void public_draw_label ( int X, int Y, int W, int H );
|
||||
|
||||
DPM ( int X, int Y, int W, int H, const char *L = 0 );
|
||||
|
||||
void value ( float v )
|
||||
{
|
||||
if ( _value != v )
|
||||
{
|
||||
if ( pos( v ) != pos( _value ) )
|
||||
Meter::value( v );
|
||||
}
|
||||
|
||||
_value = v;
|
||||
}
|
||||
|
||||
float value ( void ) const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
void pixels_per_segment ( int v ) { _pixels_per_segment = v; }
|
||||
|
||||
float dim ( void ) const { return _dim; }
|
||||
void dim ( float v ) { _dim = v; if ( visible_r() ) redraw(); }
|
||||
|
||||
|
||||
virtual void value ( float v )
|
||||
{
|
||||
/* only trigger redraw for changes at or above our resolution*/
|
||||
if ( pos( value() ) != pos( v ) && visible_r() )
|
||||
damage( FL_DAMAGE_USER1 );
|
||||
|
||||
Meter::value( v );
|
||||
}
|
||||
|
||||
virtual float value ( void ) { return Meter::value(); }
|
||||
|
||||
void update ( void );
|
||||
|
||||
static
|
||||
void
|
||||
blend ( int nbreaks, int* b, Fl_Color *c )
|
||||
blend ( int nbreaks, int* b, Fl_Color *c, Fl_Color bc )
|
||||
{
|
||||
for ( int i = 0; i < nbreaks - 1; i++ )
|
||||
{
|
||||
|
|
|
@ -56,9 +56,20 @@ Group::~Group ( )
|
|||
{
|
||||
DMESSAGE( "Destroying group" );
|
||||
|
||||
mixer->remove_group(this);
|
||||
|
||||
for ( std::list<Mixer_Strip*>::iterator i = strips.begin();
|
||||
i != strips.end();
|
||||
i++ )
|
||||
{
|
||||
/* avoid a use after free during project close when the group
|
||||
* may be destroyed before its member strips are */
|
||||
(*i)->clear_group();
|
||||
}
|
||||
|
||||
if ( _name )
|
||||
free( _name );
|
||||
|
||||
|
||||
deactivate();
|
||||
}
|
||||
|
||||
|
@ -101,12 +112,16 @@ Group::set ( Log_Entry &e )
|
|||
void
|
||||
Group::latency ( jack_latency_callback_mode_t mode )
|
||||
{
|
||||
for ( std::list<Mixer_Strip*>::iterator i = strips.begin();
|
||||
i != strips.end();
|
||||
i++ )
|
||||
if ( trylock() )
|
||||
{
|
||||
if ( (*i)->chain() )
|
||||
(*i)->chain()->set_latency(mode == JackCaptureLatency ? JACK::Port::Input : JACK::Port::Output );
|
||||
for ( std::list<Mixer_Strip*>::iterator i = strips.begin();
|
||||
i != strips.end();
|
||||
i++ )
|
||||
{
|
||||
if ( (*i)->chain() )
|
||||
(*i)->chain()->set_latency(mode == JackCaptureLatency ? JACK::Port::Input : JACK::Port::Output );
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,8 +223,9 @@ Group::process ( nframes_t nframes )
|
|||
void
|
||||
Group::recal_load_coef ( void )
|
||||
{
|
||||
_load_coef = 1.0f / ( nframes() / (float)sample_rate() * 1000000.0 );
|
||||
_load_coef = 1.0f / ( nframes() / (float)sample_rate() * 1000000.0f );
|
||||
}
|
||||
|
||||
int
|
||||
Group::sample_rate_changed ( nframes_t srate )
|
||||
{
|
||||
|
@ -261,7 +277,7 @@ Group::name ( const char *n )
|
|||
if ( !active() )
|
||||
{
|
||||
Client::init( ename );
|
||||
Module::set_sample_rate( sample_rate() );
|
||||
Module::sample_rate( sample_rate() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -273,6 +289,7 @@ void
|
|||
Group::add ( Mixer_Strip *o )
|
||||
{
|
||||
lock();
|
||||
|
||||
if ( ! active() )
|
||||
{
|
||||
/* to call init */
|
||||
|
@ -280,10 +297,12 @@ Group::add ( Mixer_Strip *o )
|
|||
name(n);
|
||||
free(n);
|
||||
}
|
||||
|
||||
if ( o->chain() )
|
||||
o->chain()->thaw_ports();
|
||||
|
||||
strips.push_back(o);
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
@ -291,13 +310,15 @@ void
|
|||
Group::remove ( Mixer_Strip *o )
|
||||
{
|
||||
lock();
|
||||
|
||||
strips.remove(o);
|
||||
|
||||
if ( o->chain() )
|
||||
o->chain()->freeze_ports();
|
||||
|
||||
if ( strips.size() == 0 && active() )
|
||||
{
|
||||
Client::close();
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,8 @@ public:
|
|||
void add (Mixer_Strip*);
|
||||
void remove (Mixer_Strip*);
|
||||
|
||||
int children ( void ) const { return strips.size(); }
|
||||
|
||||
/* Engine *engine ( void ) { return _engine; } */
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Pack.H>
|
||||
#include <FL/Fl_Scalepack.H>
|
||||
#include <FL/Enumerations.H>
|
||||
|
||||
#include "dsp.h"
|
||||
|
||||
|
@ -48,6 +49,8 @@ extern char *instance_name;
|
|||
#include "Mixer.H"
|
||||
#include "Group.H"
|
||||
|
||||
#include "Project.H"
|
||||
|
||||
|
||||
static JACK_Module *receptive_to_drop = NULL;
|
||||
|
||||
|
@ -164,7 +167,7 @@ JACK_Module::JACK_Module ( bool log )
|
|||
Fl_Browser *o = connection_display = new Fl_Browser( 0, 0, w(), h() );
|
||||
o->has_scrollbar(Fl_Browser_::VERTICAL);
|
||||
o->textsize( 10 );
|
||||
o->textcolor( FL_LIGHT3 );
|
||||
o->textcolor( fl_contrast( FL_LIGHT3, FL_BACKGROUND_COLOR ) );
|
||||
o->textfont( FL_COURIER );
|
||||
o->box( FL_FLAT_BOX );
|
||||
o->color( FL_DARK1 );
|
||||
|
@ -298,12 +301,23 @@ JACK_Module::update_connection_status ( void )
|
|||
return;
|
||||
}
|
||||
|
||||
/* /\* causes a lot of unnecessary redraws to do this when loading *\/ */
|
||||
/* if ( Project::is_opening_closing() ) */
|
||||
/* return; */
|
||||
|
||||
/* FIXME: only do something if port list actually changed! */
|
||||
std::list<std::string> output_names = get_connections_for_ports( aux_audio_output );
|
||||
std::list<std::string> input_names = get_connections_for_ports( aux_audio_input );
|
||||
|
||||
if ( (unsigned int)connection_display->size() == input_names.size() + output_names.size() )
|
||||
/* looks like nothing was added or removed, bail.
|
||||
FIXME: this would be better if it actually compared the lists item by item. */
|
||||
return;
|
||||
|
||||
connection_display->clear();
|
||||
|
||||
int n = 0;
|
||||
|
||||
for ( std::list<std::string>::const_iterator j = input_names.begin();
|
||||
j != input_names.end();
|
||||
j++ )
|
||||
|
@ -599,13 +613,12 @@ JACK_Module::handle ( int m )
|
|||
if ( Fl::event_inside( output_connection_handle ) ||
|
||||
Fl::event_inside( output_connection2_handle ) ||
|
||||
Fl::event_inside( input_connection_handle ) )
|
||||
{
|
||||
fl_cursor( FL_CURSOR_HAND );
|
||||
}
|
||||
else
|
||||
fl_cursor( FL_CURSOR_DEFAULT );
|
||||
|
||||
Module::handle(m);
|
||||
/* This calls Fl_Group::handle() which somehow prevent DND FL_PASTE event from being delivered later */
|
||||
/* Module::handle(m); */
|
||||
return 1;
|
||||
case FL_ENTER:
|
||||
case FL_DND_ENTER:
|
||||
|
|
|
@ -84,17 +84,14 @@ public:
|
|||
|
||||
virtual void value ( float v )
|
||||
{
|
||||
if ( visible_r() )
|
||||
damage( FL_DAMAGE_USER1 );
|
||||
|
||||
_value = v;
|
||||
|
||||
if ( _value > _peak )
|
||||
_peak = _value;
|
||||
_value = v;
|
||||
|
||||
if ( _value > _peak )
|
||||
_peak = _value;
|
||||
}
|
||||
|
||||
virtual float value ( void ) const { return _value; }
|
||||
float peak ( void ) const { return _peak; }
|
||||
virtual float peak ( void ) const { return _peak; }
|
||||
|
||||
void reset ( void ) { _peak = -80.0f; redraw(); }
|
||||
|
||||
|
|
|
@ -31,18 +31,22 @@
|
|||
#include "FL/Fl_Dial.H"
|
||||
#include "FL/Fl_Labelpad_Group.H"
|
||||
#include "FL/Fl_Scalepack.H"
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include "Chain.H"
|
||||
#include "DPM.H"
|
||||
#include "dsp.h"
|
||||
|
||||
#include "FL/test_press.H"
|
||||
|
||||
|
||||
const int DX = 1;
|
||||
|
||||
Meter_Indicator_Module::Meter_Indicator_Module ( bool is_default )
|
||||
: Module ( is_default, 50, 100, name() )
|
||||
{
|
||||
box( FL_FLAT_BOX );
|
||||
/* color( fl_darker( fl_darker( FL_BACKGROUND_COLOR ))); */
|
||||
color( FL_BLACK );
|
||||
|
||||
_disable_context_menu = false;
|
||||
|
@ -53,15 +57,23 @@ Meter_Indicator_Module::Meter_Indicator_Module ( bool is_default )
|
|||
|
||||
control_input[0].hints.visible = false;
|
||||
|
||||
dpm_pack = new Fl_Scalepack( x(), y(), w(), h() );
|
||||
dpm_pack->color( FL_BACKGROUND_COLOR );
|
||||
dpm_pack->box( FL_FLAT_BOX );
|
||||
/* dpm_pack = new Fl_Scalepack( x() + 2, y() + 2, w() - 4, h() - 4 ); */
|
||||
/* /\* dpm_pack->color( FL_BACKGROUND_COLOR ); *\/ */
|
||||
/* dpm_pack->box( FL_NO_BOX ); */
|
||||
/* dpm_pack->type( FL_HORIZONTAL ); */
|
||||
/* dpm_pack->spacing(1); */
|
||||
|
||||
dpm_pack = new Fl_Scalepack( x() + 20 + 2, y() + 2, w() - 20 - 4, h() - 4 );
|
||||
/* dpm_pack->color( FL_BACKGROUND_COLOR ); */
|
||||
dpm_pack->box( FL_NO_BOX );
|
||||
dpm_pack->type( FL_HORIZONTAL );
|
||||
dpm_pack->spacing(1);
|
||||
|
||||
end();
|
||||
end();
|
||||
|
||||
control_value = new float[1];
|
||||
*control_value = -70.0f;
|
||||
control_value = new float[1*2];
|
||||
control_value[0] =
|
||||
control_value[1] = 0;
|
||||
|
||||
align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE ) );
|
||||
|
||||
|
@ -81,6 +93,32 @@ Meter_Indicator_Module::~Meter_Indicator_Module ( )
|
|||
|
||||
|
||||
|
||||
void Meter_Indicator_Module::resize ( int X, int Y, int W, int H )
|
||||
{
|
||||
Fl_Group::resize(X,Y,W,H);
|
||||
dpm_pack->resize( x() + 20 + DX , y() + DX, w() - 20 - DX*2, h() - DX*2);
|
||||
}
|
||||
|
||||
void
|
||||
Meter_Indicator_Module::draw ( void )
|
||||
{
|
||||
/* if ( damage() & FL_DAMAGE_ALL ) */
|
||||
|
||||
/* draw_box(x(),y(),w(),h()); */
|
||||
Fl_Group::draw();
|
||||
|
||||
if ( damage() & FL_DAMAGE_ALL )
|
||||
{
|
||||
/* need to trigger redraw of exterior label */
|
||||
if ( dpm_pack->children() )
|
||||
{
|
||||
((DPM*)dpm_pack->child(0))->public_draw_label( x(), y(), 19, h() );
|
||||
}
|
||||
}
|
||||
|
||||
fl_rect( x(), y(), w(), h(), fl_darker(fl_darker(FL_BACKGROUND_COLOR)));
|
||||
}
|
||||
|
||||
void
|
||||
Meter_Indicator_Module::get ( Log_Entry &e ) const
|
||||
{
|
||||
|
@ -138,37 +176,29 @@ Meter_Indicator_Module::update ( void )
|
|||
// A little hack to detect that the connected module's number
|
||||
// of control outs has changed.
|
||||
Port *p = control_input[0].connected_port();
|
||||
|
||||
for ( int i = 0; i < dpm_pack->children(); ++i )
|
||||
{
|
||||
DPM *o = (DPM*)dpm_pack->child(i);
|
||||
|
||||
if ( dpm_pack->children() != p->hints.dimensions )
|
||||
{
|
||||
/* engine->lock(); */
|
||||
float dB = CO_DB( control_value[i] );
|
||||
|
||||
if ( dB > o->value() )
|
||||
o->value( dB );
|
||||
|
||||
dpm_pack->clear();
|
||||
o->update();
|
||||
/* else */
|
||||
/* { */
|
||||
/* /\* do falloff *\/ */
|
||||
/* float f = o->value() - 0.75f; */
|
||||
/* if ( f < -70.0f ) */
|
||||
/* f = -70.0f; */
|
||||
|
||||
/* o->value( f ); */
|
||||
/* } */
|
||||
|
||||
control_value = new float[p->hints.dimensions];
|
||||
|
||||
for ( int i = p->hints.dimensions; i--; )
|
||||
{
|
||||
|
||||
DPM *dpm = new DPM( x(), y(), w(), h() );
|
||||
dpm->type( FL_VERTICAL );
|
||||
|
||||
dpm_pack->add( dpm );
|
||||
|
||||
control_value[i] = -70.0f;
|
||||
dpm->value( -70.0f );
|
||||
}
|
||||
|
||||
/* engine->unlock(); */
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < dpm_pack->children(); ++i )
|
||||
{
|
||||
((DPM*)dpm_pack->child( i ))->value( control_value[i] );
|
||||
control_value[i] = -70.0f;
|
||||
}
|
||||
}
|
||||
control_value[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +258,7 @@ Meter_Indicator_Module::handle_control_changed ( Port *p )
|
|||
|
||||
control_value = new float[p->hints.dimensions];
|
||||
|
||||
for ( int i = p->hints.dimensions; i--; )
|
||||
for ( int i = 0; i < p->hints.dimensions; i++ )
|
||||
{
|
||||
DPM *dpm = new DPM( x(), y(), w(), h() );
|
||||
dpm->type( FL_VERTICAL );
|
||||
|
@ -237,8 +267,10 @@ Meter_Indicator_Module::handle_control_changed ( Port *p )
|
|||
dpm_pack->add( dpm );
|
||||
dpm_pack->redraw();
|
||||
|
||||
control_value[i] = -70.0f;
|
||||
dpm->value( -70.0f );
|
||||
control_value[i] = 0;
|
||||
|
||||
dpm->value( CO_DB( control_value[i] ));
|
||||
|
||||
}
|
||||
|
||||
redraw();
|
||||
|
@ -256,12 +288,22 @@ Meter_Indicator_Module::process ( nframes_t )
|
|||
if ( control_input[0].connected() )
|
||||
{
|
||||
Port *p = control_input[0].connected_port();
|
||||
|
||||
volatile float *cv = control_value;
|
||||
float *pv = (float*)control_input[0].buffer();
|
||||
|
||||
for ( int i = 0; i < p->hints.dimensions; ++i )
|
||||
{
|
||||
float dB = ((float*)control_input[0].buffer())[i];
|
||||
if ( dB > control_value[i])
|
||||
control_value[i] = dB;
|
||||
/* peak value since we last checked */
|
||||
if ( *pv > *cv )
|
||||
{
|
||||
*cv = *pv;
|
||||
/* reset now that we've got it */
|
||||
*pv = 0;
|
||||
}
|
||||
|
||||
cv++;
|
||||
pv++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,12 +70,8 @@ protected:
|
|||
void get ( Log_Entry &e ) const;
|
||||
void set ( Log_Entry &e );
|
||||
|
||||
virtual void draw ( void )
|
||||
{
|
||||
// draw_box();
|
||||
Fl_Group::draw();
|
||||
}
|
||||
|
||||
virtual void draw ( void );
|
||||
virtual void resize ( int X, int Y, int W, int H );
|
||||
virtual int handle ( int m );
|
||||
|
||||
private:
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <math.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Single_Window.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include "FL/Fl_Scalepack.H"
|
||||
#include "FL/test_press.H"
|
||||
|
@ -30,30 +31,33 @@
|
|||
#include "DPM.H"
|
||||
#include "JACK/Port.H"
|
||||
#include "dsp.h"
|
||||
|
||||
|
||||
|
||||
Meter_Module::Meter_Module ( )
|
||||
: Module ( 50, 100, name() )
|
||||
{
|
||||
box( FL_NO_BOX );
|
||||
dpm_pack = new Fl_Scalepack( x(), y(), w(), h() );
|
||||
box( FL_FLAT_BOX );
|
||||
dpm_pack = new Fl_Scalepack( x() + 2, y() + 2, w() - 4, h() - 4 );
|
||||
dpm_pack->type( FL_HORIZONTAL );
|
||||
|
||||
dpm_pack->spacing( 1 );
|
||||
|
||||
control_value = 0;
|
||||
|
||||
color( FL_BLACK );
|
||||
peaks = 0;
|
||||
meter_sample_period_count = 0;
|
||||
meter_sample_periods = 0;
|
||||
|
||||
color( fl_darker( fl_darker( FL_BACKGROUND_COLOR )));
|
||||
|
||||
end();
|
||||
|
||||
Port p( this, Port::OUTPUT, Port::CONTROL, "dB level" );
|
||||
p.hints.type = Port::Hints::LOGARITHMIC;
|
||||
Port p( this, Port::OUTPUT, Port::CONTROL, "peak level" );
|
||||
p.hints.type = Port::Hints::LINEAR;
|
||||
p.hints.ranged = true;
|
||||
p.hints.maximum = 6.0f;
|
||||
p.hints.minimum = -70.0f;
|
||||
p.hints.maximum = 10.0f;
|
||||
p.hints.minimum = 0.0f;
|
||||
p.hints.dimensions = 1;
|
||||
p.connect_to( new float[1] );
|
||||
p.control_value_no_callback( -70.0f );
|
||||
p.control_value_no_callback( 0 );
|
||||
|
||||
add_port( p );
|
||||
|
||||
|
@ -70,13 +74,40 @@ Meter_Module::~Meter_Module ( )
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
void Meter_Module::resize ( int X, int Y, int W, int H )
|
||||
{
|
||||
Fl_Group::resize(X,Y,W,H);
|
||||
dpm_pack->resize( x() + 2, y() + 2, w() - 4, h() - 4 );
|
||||
}
|
||||
|
||||
void
|
||||
Meter_Module::draw ( void )
|
||||
{
|
||||
/* draw_box(x(),y(),w(),h()); */
|
||||
|
||||
Fl_Group::draw();
|
||||
|
||||
fl_rect( x(), y(), w(), h(), fl_darker(FL_BACKGROUND_COLOR));
|
||||
fl_rect( x()+1, y()+1, w()-2, h()-2, fl_darker(fl_darker(FL_BACKGROUND_COLOR)));
|
||||
}
|
||||
|
||||
void
|
||||
Meter_Module::update ( void )
|
||||
{
|
||||
for ( int i = dpm_pack->children(); i--; )
|
||||
{
|
||||
((DPM*)dpm_pack->child( i ))->value( control_value[i] );
|
||||
control_value[i] = -70.0f;
|
||||
DPM* o = ((DPM*)dpm_pack->child( i ));
|
||||
|
||||
const float v = CO_DB( control_value[i] );
|
||||
|
||||
if ( v > o->value() )
|
||||
o->value( v );
|
||||
|
||||
o->update();
|
||||
|
||||
control_value[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +130,6 @@ Meter_Module::configure_inputs ( int n )
|
|||
|
||||
add_port( Port( this, Port::INPUT, Port::AUDIO ) );
|
||||
add_port( Port( this, Port::OUTPUT, Port::AUDIO ) );
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -114,16 +144,20 @@ Meter_Module::configure_inputs ( int n )
|
|||
audio_input.pop_back();
|
||||
audio_output.back().disconnect();
|
||||
audio_output.pop_back();
|
||||
|
||||
smoothing.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/* DMESSAGE( "sample rate: %lu, nframes: %lu", sample_rate(), this->nframes() ); */
|
||||
|
||||
control_output[0].hints.dimensions = n;
|
||||
delete[] (float*)control_output[0].buffer();
|
||||
{
|
||||
float *f = new float[n];
|
||||
|
||||
for ( int i = n; i--; )
|
||||
f[i] = -70.0f;
|
||||
f[i] = 0;
|
||||
|
||||
control_output[0].connect_to( f );
|
||||
}
|
||||
|
@ -133,7 +167,7 @@ Meter_Module::configure_inputs ( int n )
|
|||
|
||||
control_value = new float[n];
|
||||
for ( int i = n; i--; )
|
||||
control_value[i] = -70.0f;
|
||||
control_value[i] = 0;
|
||||
|
||||
if ( control_output[0].connected() )
|
||||
control_output[0].connected_port()->module()->handle_control_changed( control_output[0].connected_port() );
|
||||
|
@ -175,11 +209,19 @@ Meter_Module::process ( nframes_t nframes )
|
|||
{
|
||||
for ( unsigned int i = 0; i < audio_input.size(); ++i )
|
||||
{
|
||||
// float dB = 20 * log10( get_peak_sample( (float*)audio_input[i].buffer(), nframes ) / 2.0f );
|
||||
float dB = 20 * log10( buffer_get_peak( (sample_t*) audio_input[i].buffer(), nframes ) );
|
||||
const float peak = buffer_get_peak( (sample_t*) audio_input[i].buffer(), nframes );
|
||||
|
||||
/* const float RMS = sqrtf( peak / (float)nframes); */
|
||||
|
||||
((float*)control_output[0].buffer())[i] = dB;
|
||||
if (dB > control_value[i])
|
||||
control_value[i] = dB;
|
||||
/* since the GUI only updates at 20 or 30hz, there's no point in doing this more often than necessary. */
|
||||
|
||||
/* need to store this separately from other peaks as it must be reset each time we do a round of smoothing output */
|
||||
|
||||
/* store peak value */
|
||||
if ( peak > ((float*)control_output[0].buffer())[i] )
|
||||
((float*)control_output[0].buffer())[i] = peak;
|
||||
|
||||
if ( peak > control_value[i] )
|
||||
control_value[i] = peak;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Module.H"
|
||||
#include "dsp.h"
|
||||
#include <vector>
|
||||
|
||||
class Fl_Scalepack;
|
||||
|
||||
|
@ -27,8 +29,19 @@ class Meter_Module : public Module
|
|||
{
|
||||
Fl_Scalepack *dpm_pack;
|
||||
|
||||
std::vector <Value_Smoothing_Filter> smoothing;
|
||||
|
||||
volatile float *control_value;
|
||||
volatile float *peaks;
|
||||
|
||||
int meter_sample_periods; /* no need to do computations every
|
||||
* buffer when the gui only updates at
|
||||
* 30Hz. So only do it every n
|
||||
* buffers */
|
||||
int meter_sample_period_count;
|
||||
|
||||
void set_smoothing_sample_rate ( nframes_t nframes, nframes_t sample_rate );
|
||||
|
||||
public:
|
||||
|
||||
Meter_Module ( );
|
||||
|
@ -47,5 +60,6 @@ protected:
|
|||
|
||||
virtual int handle ( int m );
|
||||
virtual void process ( nframes_t nframes );
|
||||
virtual void draw ( void ) { draw_box(x(),y(),w(),h()); }
|
||||
virtual void draw ( void );
|
||||
virtual void resize ( int X, int Y, int W, int H );
|
||||
};
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
|
||||
#include "Controller_Module.H"
|
||||
|
||||
const double FEEDBACK_UPDATE_FREQ = 1.0f;
|
||||
/* const double FEEDBACK_UPDATE_FREQ = 1.0f; */
|
||||
const double FEEDBACK_UPDATE_FREQ = 1.0f / 30.0f;
|
||||
|
||||
extern char *user_config_dir;
|
||||
extern char *instance_name;
|
||||
|
@ -308,7 +309,7 @@ void Mixer::cb_menu(Fl_Widget* o) {
|
|||
}
|
||||
else if ( !strcmp( picked, "&Remote Control/Send State" ) )
|
||||
{
|
||||
send_feedback();
|
||||
send_feedback(true);
|
||||
}
|
||||
else if ( ! strcmp( picked, "&Remote Control/Clear All Mappings" ) )
|
||||
{
|
||||
|
@ -354,7 +355,7 @@ void Mixer::cb_menu(Fl_Widget* o) {
|
|||
{
|
||||
fl_theme_chooser();
|
||||
}
|
||||
else if ( ! strcmp( picked, "&Mixer/Swap &Fader//Signal View" ) )
|
||||
else if ( ! strcmp( picked, "&Mixer/Toggle &Fader View" ) )
|
||||
{
|
||||
command_toggle_fader_view();
|
||||
}
|
||||
|
@ -416,7 +417,7 @@ Mixer::update_cb ( void )
|
|||
{
|
||||
Fl::repeat_timeout( _update_interval, &Mixer::update_cb, this );
|
||||
|
||||
if ( active_r() && visible_r() )
|
||||
/* if ( active_r() && visible_r() ) */
|
||||
{
|
||||
for ( int i = 0; i < mixer_strips->children(); i++ )
|
||||
{
|
||||
|
@ -527,7 +528,7 @@ Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) :
|
|||
o->add( "&Mixer/&Import Strip" );
|
||||
o->add( "&Mixer/Paste", FL_CTRL + 'v', 0, 0 );
|
||||
o->add( "&Mixer/&Spatialization Console", FL_F + 8, 0, 0, FL_MENU_TOGGLE );
|
||||
o->add( "&Mixer/Swap &Fader//Signal View", FL_ALT + 'f', 0, 0, FL_MENU_TOGGLE );
|
||||
o->add( "&Mixer/Toggle &Fader View", FL_ALT + 'f', 0, 0, FL_MENU_TOGGLE );
|
||||
// o->add( "&Mixer/&Signal View", FL_ALT + 's', 0, 0, FL_MENU_TOGGLE );
|
||||
o->add( "&Remote Control/Start Learning", FL_F + 9, 0, 0 );
|
||||
o->add( "&Remote Control/Stop Learning", FL_F + 10, 0, 0 );
|
||||
|
@ -571,6 +572,7 @@ Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) :
|
|||
align( (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE) );
|
||||
o->flow( false );
|
||||
o->box( FL_FLAT_BOX );
|
||||
o->color( fl_darker(FL_BACKGROUND_COLOR ));
|
||||
o->type( Fl_Pack::HORIZONTAL );
|
||||
o->hspacing( 2 );
|
||||
o->vspacing( 2 );
|
||||
|
@ -590,9 +592,8 @@ Mixer::Mixer ( int X, int Y, int W, int H, const char *L ) :
|
|||
|
||||
resize( X,Y,W,H );
|
||||
|
||||
update_frequency( 15 );
|
||||
update_frequency( 24 );
|
||||
|
||||
Fl::add_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, this );
|
||||
|
||||
update_menu();
|
||||
|
||||
|
@ -621,8 +622,14 @@ Mixer::osc_strip_by_number ( const char *path, const char *types, lo_arg **argv,
|
|||
}
|
||||
|
||||
char *new_path;
|
||||
|
||||
char *stripname = escape_url( o->name() );
|
||||
|
||||
asprintf( &new_path, "%s/strip/%s/%s", client_name, o->name(), rem );
|
||||
asprintf( &new_path, "%s/strip/%s/%s", client_name, stripname, rem );
|
||||
|
||||
free( stripname );
|
||||
|
||||
/* DMESSAGE( "Forwarding by-number OSC path: %s === %s", path, new_path ); */
|
||||
|
||||
free( rem );
|
||||
|
||||
|
@ -743,6 +750,8 @@ void Mixer::resize ( int X, int Y, int W, int H )
|
|||
{
|
||||
Fl_Group::resize( X, Y, W, H );
|
||||
|
||||
sm_blinker->resize( X + W - 40, Y + 5, 35, 15 );
|
||||
|
||||
scroll->resize( X, Y + 24, W, H - 24 - 18 );
|
||||
|
||||
mixer_strips->resize( X, Y + 24, W, H - (18*2) - 24 );
|
||||
|
@ -757,8 +766,10 @@ void Mixer::add ( Mixer_Strip *ms )
|
|||
mixer_strips->add( ms );
|
||||
|
||||
ms->size( ms->w(), _strip_height );
|
||||
ms->redraw();
|
||||
ms->take_focus();
|
||||
ms->redraw();
|
||||
ms->take_focus();
|
||||
|
||||
renumber_strips();
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -775,12 +786,25 @@ Mixer::quit ( void )
|
|||
while ( Fl::first_window() ) Fl::first_window()->hide();
|
||||
}
|
||||
|
||||
void
|
||||
Mixer::renumber_strips ( void )
|
||||
{
|
||||
for ( int i = mixer_strips->children(); i--; )
|
||||
{
|
||||
Mixer_Strip *o = (Mixer_Strip*)mixer_strips->child(i);
|
||||
|
||||
o->number( find_strip( o ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Mixer::insert ( Mixer_Strip *ms, Mixer_Strip *before )
|
||||
{
|
||||
// mixer_strips->remove( ms );
|
||||
mixer_strips->insert( *ms, before );
|
||||
renumber_strips();
|
||||
schedule_feedback();
|
||||
// scroll->redraw();
|
||||
}
|
||||
void
|
||||
|
@ -789,6 +813,7 @@ Mixer::insert ( Mixer_Strip *ms, int i )
|
|||
Mixer_Strip *before = (Mixer_Strip*)mixer_strips->child( i );
|
||||
|
||||
insert( ms, before);
|
||||
renumber_strips();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -799,6 +824,7 @@ Mixer::move_left ( Mixer_Strip *ms )
|
|||
if ( i > 0 )
|
||||
insert( ms, i - 1 );
|
||||
|
||||
renumber_strips();
|
||||
/* FIXME: do better */
|
||||
mixer_strips->redraw();
|
||||
}
|
||||
|
@ -811,6 +837,8 @@ Mixer::move_right ( Mixer_Strip *ms )
|
|||
if ( i < mixer_strips->children() - 1 )
|
||||
insert( ms, i + 2 );
|
||||
|
||||
renumber_strips();
|
||||
|
||||
/* FIXME: do better */
|
||||
mixer_strips->redraw();
|
||||
}
|
||||
|
@ -821,10 +849,11 @@ void Mixer::remove ( Mixer_Strip *ms )
|
|||
|
||||
mixer_strips->remove( ms );
|
||||
|
||||
ms->group()->remove( ms );
|
||||
|
||||
if ( parent() )
|
||||
parent()->redraw();
|
||||
|
||||
renumber_strips();
|
||||
schedule_feedback();
|
||||
}
|
||||
|
||||
|
||||
|
@ -893,7 +922,7 @@ Mixer::rows ( int ideal_rows )
|
|||
|
||||
_rows = ideal_rows;
|
||||
|
||||
if ( _strip_height != sh );
|
||||
if ( _strip_height != sh )
|
||||
{
|
||||
mixer_strips->redraw();
|
||||
scroll->redraw();
|
||||
|
@ -1051,20 +1080,24 @@ Mixer::send_feedback_cb ( void *v )
|
|||
{
|
||||
Mixer *m = (Mixer*)v;
|
||||
|
||||
m->send_feedback();
|
||||
m->send_feedback(false);
|
||||
|
||||
/* just to it once at the start... */
|
||||
Fl::repeat_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, v );
|
||||
}
|
||||
|
||||
/** unconditionally send feedback to all mapped controls. This is
|
||||
* useful for updating the state of an external controller. */
|
||||
void
|
||||
Mixer::send_feedback ( void )
|
||||
Mixer::send_feedback ( bool force )
|
||||
{
|
||||
for ( int i = 0; i < mixer_strips->children(); i++ )
|
||||
{
|
||||
((Mixer_Strip*)mixer_strips->child(i))->send_feedback();
|
||||
}
|
||||
((Mixer_Strip*)mixer_strips->child(i))->send_feedback(force);
|
||||
}
|
||||
|
||||
void
|
||||
Mixer::schedule_feedback ( void )
|
||||
{
|
||||
for ( int i = 0; i < mixer_strips->children(); i++ )
|
||||
((Mixer_Strip*)mixer_strips->child(i))->schedule_feedback();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1072,6 +1105,9 @@ Mixer::send_feedback ( void )
|
|||
int
|
||||
Mixer::handle ( int m )
|
||||
{
|
||||
/* if user presses certain keys when project is loading it can cause a crash. Don't respond to input. */
|
||||
if ( Project::is_opening_closing() )
|
||||
return 0;
|
||||
|
||||
if ( Fl_Group::handle( m ) )
|
||||
return 1;
|
||||
|
@ -1082,7 +1118,9 @@ Mixer::handle ( int m )
|
|||
{
|
||||
if ( ! Fl::event_inside( this ) )
|
||||
return 0;
|
||||
|
||||
|
||||
DMESSAGE( "Got paste into mixer, expecting strip file..." );
|
||||
|
||||
const char *text = Fl::event_text();
|
||||
|
||||
char *file;
|
||||
|
@ -1148,7 +1186,7 @@ Mixer::get_auto_connect_targets ( void )
|
|||
void
|
||||
Mixer::auto_connect ( void )
|
||||
{
|
||||
if ( Project::is_opening() )
|
||||
if ( Project::is_opening_closing() )
|
||||
/* it's more efficient to do this once at the end rather than as we go. */
|
||||
return;
|
||||
|
||||
|
@ -1176,7 +1214,7 @@ Mixer::auto_connect ( void )
|
|||
void
|
||||
Mixer::maybe_auto_connect_output ( Module::Port *p )
|
||||
{
|
||||
if ( Project::is_opening() )
|
||||
if ( Project::is_opening_closing() )
|
||||
/* it's more efficient to do this once at the end rather than as we go. */
|
||||
return;
|
||||
|
||||
|
@ -1192,7 +1230,7 @@ Mixer::maybe_auto_connect_output ( Module::Port *p )
|
|||
return;
|
||||
}
|
||||
|
||||
/* now do that catch-alls, first one wins! */
|
||||
/* now do the catch-alls, first one wins! */
|
||||
for ( int i = 0; i < mixer_strips->children(); i++ )
|
||||
{
|
||||
Mixer_Strip *s = ((Mixer_Strip*)mixer_strips->child(i));
|
||||
|
@ -1267,6 +1305,9 @@ Mixer::command_load ( const char *path, const char *display_name )
|
|||
|
||||
mixer->activate();
|
||||
|
||||
/* Fl::remove_timeout( send_feedback_cb, this ); */
|
||||
Fl::add_timeout( FEEDBACK_UPDATE_FREQ, send_feedback_cb, this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,8 @@ private:
|
|||
void load_translations ( void );
|
||||
|
||||
static void send_feedback_cb ( void *v );
|
||||
void send_feedback ( void );
|
||||
void send_feedback ( bool force );
|
||||
void schedule_feedback ( void );
|
||||
void redraw_windows ( void );
|
||||
|
||||
static void handle_dirty ( int, void *v );
|
||||
|
@ -159,6 +160,8 @@ public:
|
|||
void save_project_settings ( void );
|
||||
void load_project_settings ( void );
|
||||
|
||||
void renumber_strips ( void );
|
||||
|
||||
public:
|
||||
|
||||
void command_toggle_fader_view ( void );
|
||||
|
|
|
@ -73,6 +73,7 @@ Mixer_Strip::Mixer_Strip( const char *strip_name ) : Fl_Group( 0, 0, 120, 600 )
|
|||
|
||||
init();
|
||||
|
||||
/* create single member group */
|
||||
_group = new Group(strip_name, true);
|
||||
|
||||
_group->add( this );
|
||||
|
@ -105,14 +106,30 @@ Mixer_Strip::~Mixer_Strip ( )
|
|||
// _chain->engine()->lock();
|
||||
|
||||
log_destroy();
|
||||
|
||||
|
||||
mixer->remove( this );
|
||||
|
||||
/* make sure this gets destroyed before the chain */
|
||||
fader_tab->clear();
|
||||
|
||||
delete _chain;
|
||||
_chain = NULL;
|
||||
if ( _group )
|
||||
{
|
||||
_group->remove( this );
|
||||
}
|
||||
|
||||
if ( _chain )
|
||||
{
|
||||
delete _chain;
|
||||
_chain = NULL;
|
||||
}
|
||||
|
||||
if ( _group )
|
||||
{
|
||||
if ( 0 == _group->children() )
|
||||
delete _group;
|
||||
|
||||
_group = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -347,6 +364,7 @@ void Mixer_Strip::cb_handle(Fl_Widget* o, void* v) {
|
|||
void
|
||||
Mixer_Strip::group ( Group *g )
|
||||
{
|
||||
/* FIXME: what is the intention here? */
|
||||
if ( !g && _group && _group->single() )
|
||||
return;
|
||||
|
||||
|
@ -544,16 +562,35 @@ Mixer_Strip::init ( )
|
|||
o->box(FL_FLAT_BOX);
|
||||
o->tooltip( "Drag and drop to move strip" );
|
||||
}
|
||||
|
||||
{ Fl_Progress* o = dsp_load_progress = new Fl_Progress(61, 183, 45, 14, "group dsp");
|
||||
o->box(FL_BORDER_BOX);
|
||||
o->type(FL_HORIZONTAL);
|
||||
/* o->labelsize( 9 ); */
|
||||
o->minimum( 0 );
|
||||
// o->maximum( 0.25f );
|
||||
o->maximum( 1 );
|
||||
/* o->color(fl_rgb_color( 10,10,10 ) ); */
|
||||
o->color2(FL_CYAN);
|
||||
|
||||
o->color(fl_contrast(FL_DARK1,FL_FOREGROUND_COLOR));
|
||||
o->labelcolor(FL_FOREGROUND_COLOR);
|
||||
/* o->labeltype(FL_NORMAL_LABEL); */
|
||||
o->labeltype(FL_NORMAL_LABEL);
|
||||
o->labelfont( FL_COURIER_BOLD );
|
||||
o->labelsize( 12 );
|
||||
}
|
||||
|
||||
{ Fl_Pack *o = new Fl_Pack( 2, 2, 114, 100 );
|
||||
o->type( Fl_Pack::VERTICAL );
|
||||
o->spacing( 2 );
|
||||
o->spacing(2);
|
||||
{
|
||||
Fl_Sometimes_Input *o = new Fl_Sometimes_Input( 2, 2, 144, 15 );
|
||||
name_field = o;
|
||||
|
||||
o->up_box( FL_NO_BOX );
|
||||
o->up_box( FL_FLAT_BOX );
|
||||
o->box( FL_FLAT_BOX );
|
||||
o->color( FL_BACKGROUND_COLOR );
|
||||
o->selection_color( FL_BLACK );
|
||||
o->labeltype( FL_NO_LABEL );
|
||||
o->labelcolor( FL_GRAY0 );
|
||||
|
@ -564,7 +601,7 @@ Mixer_Strip::init ( )
|
|||
}
|
||||
{ Fl_Scalepack *o = new Fl_Scalepack( 7, 143, 110, 18 );
|
||||
o->type( Fl_Pack::HORIZONTAL );
|
||||
|
||||
o->spacing(2);
|
||||
{ Fl_Flip_Button* o = width_button = new Fl_Flip_Button(61, 183, 45, 22, "[]/[-]");
|
||||
o->type(1);
|
||||
o->tooltip( "Switch between wide and narrow views" );
|
||||
|
@ -586,16 +623,6 @@ Mixer_Strip::init ( )
|
|||
|
||||
o->end();
|
||||
} // Fl_Group* o
|
||||
{ Fl_Progress* o = dsp_load_progress = new Fl_Progress(61, 183, 45, 14, "group dsp");
|
||||
o->box(FL_BORDER_BOX);
|
||||
o->type(FL_HORIZONTAL);
|
||||
o->labelsize( 9 );
|
||||
o->minimum( 0 );
|
||||
// o->maximum( 0.25f );
|
||||
o->maximum( 1 );
|
||||
o->color(fl_rgb_color( 10,10,10 ) );
|
||||
o->color2(FL_CYAN);
|
||||
}
|
||||
{ Fl_Choice* o = group_choice = new Fl_Choice(61, 183, 45, 22);
|
||||
o->tooltip( "Create or assign group" );
|
||||
o->labeltype(FL_NO_LABEL);
|
||||
|
@ -607,6 +634,7 @@ Mixer_Strip::init ( )
|
|||
}
|
||||
{ Fl_Scalepack *o = new Fl_Scalepack( 0,0, 45, 22 );
|
||||
o->type( FL_HORIZONTAL );
|
||||
o->spacing(2);
|
||||
{ Fl_Flip_Button* o = tab_button = new Fl_Flip_Button(61, 183, 45, 22, "Fadr/Signl");
|
||||
o->tooltip( "Switch between fader and signal views" );
|
||||
o->type(1);
|
||||
|
@ -647,7 +675,7 @@ Mixer_Strip::init ( )
|
|||
{ Fl_Scalepack* o = new Fl_Scalepack(2, 135, 105, 311 );
|
||||
// o->box( FL_BORDER_BOX );
|
||||
// o->color( FL_RED );
|
||||
o->spacing( 20 );
|
||||
o->spacing( 0 );
|
||||
o->type( Fl_Scalepack::HORIZONTAL );
|
||||
{ Controller_Module *o = gain_controller = new Controller_Module( true );
|
||||
o->horizontal(false);
|
||||
|
@ -790,9 +818,8 @@ Mixer_Strip::export_strip ( const char *filename )
|
|||
{
|
||||
MESSAGE( "Exporting chain state" );
|
||||
Loggable::snapshot_callback( &Mixer_Strip::snapshot, this );
|
||||
Loggable::snapshot( filename );
|
||||
return true;
|
||||
}
|
||||
return Loggable::snapshot( filename );
|
||||
}
|
||||
|
||||
bool
|
||||
Mixer_Strip::import_strip ( const char *filename )
|
||||
|
@ -865,9 +892,12 @@ Mixer_Strip::menu_cb ( const Fl_Menu_ *m )
|
|||
free( suggested_name );
|
||||
|
||||
if ( s )
|
||||
export_strip( s );
|
||||
|
||||
fl_message( "Strip exported." );
|
||||
{
|
||||
if ( export_strip( s ) )
|
||||
fl_message( "Strip exported." );
|
||||
else
|
||||
fl_alert("Failed to export strip");
|
||||
}
|
||||
}
|
||||
else if ( ! strcmp( picked, "/Remove" ) )
|
||||
{
|
||||
|
@ -912,6 +942,9 @@ Mixer_Strip::menu_cb ( Fl_Widget *w, void *v )
|
|||
void
|
||||
Mixer_Strip::auto_input ( const char *s )
|
||||
{
|
||||
/* break old connections */
|
||||
disconnect_auto_inputs(s);
|
||||
|
||||
if ( _auto_input )
|
||||
free( _auto_input );
|
||||
|
||||
|
@ -920,6 +953,7 @@ Mixer_Strip::auto_input ( const char *s )
|
|||
if ( s )
|
||||
_auto_input = strdup( s );
|
||||
|
||||
/* make new connections */
|
||||
mixer->auto_connect();
|
||||
}
|
||||
|
||||
|
@ -952,13 +986,13 @@ static bool matches_pattern ( const char *pattern, Module::Port *p )
|
|||
return false;
|
||||
}
|
||||
|
||||
/* DMESSAGE( "Auto-connect comparing pattern: %s, to port %s", pattern, */
|
||||
/* p->jack_port()->name() ); */
|
||||
|
||||
/* group matches... try port group */
|
||||
if ( ! strcmp( port_group, "mains" ) )
|
||||
{
|
||||
if ( index( p->jack_port()->name(), '/' ) )
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
{
|
||||
return !index( p->jack_port()->name(), '/' );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -968,7 +1002,7 @@ static bool matches_pattern ( const char *pattern, Module::Port *p )
|
|||
if ( n )
|
||||
{
|
||||
// *n = 0;
|
||||
if ( ! strncmp( port_group, pn, ( n - 1 ) - pn ) )
|
||||
if ( ! strncmp( port_group, pn, n - pn ) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -996,6 +1030,42 @@ Mixer_Strip::has_group_affinity ( void ) const
|
|||
return _auto_input && strncmp( _auto_input, "*/", 2 );
|
||||
}
|
||||
|
||||
void
|
||||
Mixer_Strip::disconnect_auto_inputs ( const char *exclude_pattern )
|
||||
{
|
||||
if ( chain() )
|
||||
{
|
||||
JACK_Module *m = (JACK_Module*)chain()->module(0);
|
||||
|
||||
if ( m )
|
||||
{
|
||||
for ( unsigned int i = 0; i < m->aux_audio_input.size(); ++i )
|
||||
{
|
||||
Module::Port *p1 = &m->aux_audio_input[i];
|
||||
|
||||
if ( _auto_input && exclude_pattern )
|
||||
{
|
||||
/* avoid disconnecting a port that we'll immediately be reconnecting */
|
||||
for ( unsigned int j = 0; j < p1->nconnected(); ++j )
|
||||
{
|
||||
Module::Port *p2 = p1->connected_port( j );
|
||||
|
||||
if ( !matches_pattern( exclude_pattern, p2 ) )
|
||||
{
|
||||
p1->disconnect( p2 );
|
||||
j--; /* keep our place in the iteration */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m->aux_audio_input[i].disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Mixer_Strip::maybe_auto_connect_output ( Module::Port *p )
|
||||
{
|
||||
|
@ -1008,15 +1078,19 @@ Mixer_Strip::maybe_auto_connect_output ( Module::Port *p )
|
|||
|
||||
if ( ! _auto_input )
|
||||
{
|
||||
/* break any previous connection between this port and this module */
|
||||
p->disconnect_from_strip(this);
|
||||
/* not accepting auto inputs, so ensure all previous auto
|
||||
input connection are broken and ignore this port. */
|
||||
p->disconnect_from_strip(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( _auto_input && matches_pattern( _auto_input, p ) )
|
||||
if ( _auto_input &&
|
||||
matches_pattern( _auto_input, p ) )
|
||||
{
|
||||
/* break any prior auto-connection */
|
||||
p->disconnect();
|
||||
|
||||
/* got a match, add this to list of accepted connections */
|
||||
|
||||
|
||||
|
||||
// FIXME: Find a better way to get the port index.
|
||||
const char* jack_name = p->jack_port()->jack_name();
|
||||
|
||||
|
@ -1039,6 +1113,9 @@ Mixer_Strip::maybe_auto_connect_output ( Module::Port *p )
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( ! m->aux_audio_input[n].connected_to( p ) )
|
||||
m->aux_audio_input[n].connect_to( p );
|
||||
|
||||
m->aux_audio_input[n].connect_to( p );
|
||||
|
||||
if ( p->module()->is_default() )
|
||||
|
@ -1121,6 +1198,9 @@ Mixer_Strip::handle ( int m )
|
|||
{
|
||||
static int _button = 0;
|
||||
|
||||
if (!_chain )
|
||||
return 0;
|
||||
|
||||
Logger log( this );
|
||||
|
||||
static Fl_Widget *dragging = NULL;
|
||||
|
@ -1201,16 +1281,40 @@ Mixer_Strip::handle ( int m )
|
|||
}
|
||||
|
||||
void
|
||||
Mixer_Strip::send_feedback ( void )
|
||||
Mixer_Strip::send_feedback ( bool force )
|
||||
{
|
||||
if ( _chain )
|
||||
_chain->send_feedback();
|
||||
_chain->send_feedback(force);
|
||||
}
|
||||
|
||||
void
|
||||
Mixer_Strip::schedule_feedback ( void )
|
||||
{
|
||||
if ( _chain )
|
||||
_chain->schedule_feedback();
|
||||
}
|
||||
|
||||
/* called to inform the strip its number has changed. */
|
||||
void
|
||||
Mixer_Strip::number ( int n )
|
||||
{
|
||||
if ( _number != n )
|
||||
{
|
||||
_number = n;
|
||||
char *s =NULL;
|
||||
asprintf( &s,"%i", n+1 );
|
||||
dsp_load_progress->label(s);
|
||||
/* color code groups of eight */
|
||||
dsp_load_progress->color( (n / 8) % 2 == 0 ? FL_BACKGROUND_COLOR : FL_BLACK );
|
||||
/* dsp_load_progress->color( fl_color_average( (Fl_Color)n / 8, FL_BACKGROUND_COLOR, 0.66f )); */
|
||||
dsp_load_progress->labelcolor(fl_contrast( FL_BACKGROUND_COLOR, dsp_load_progress->color() ));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Mixer_Strip::number ( void ) const
|
||||
{
|
||||
return mixer->find_strip( this );
|
||||
return _number;
|
||||
}
|
||||
|
||||
/************/
|
||||
|
|
|
@ -98,6 +98,7 @@ private:
|
|||
int _gain_controller_mode;
|
||||
int _mute_controller_mode;
|
||||
bool _manual_connection;
|
||||
int _number;
|
||||
|
||||
Fl_Menu_Button *output_connection_button;
|
||||
Fl_Flip_Button *width_button;
|
||||
|
@ -125,7 +126,7 @@ private:
|
|||
Fl_Progress *dsp_load_progress;
|
||||
|
||||
Fl_Box *color_box;
|
||||
|
||||
|
||||
nframes_t nframes;
|
||||
|
||||
Fl_Color _color;
|
||||
|
@ -160,6 +161,7 @@ public:
|
|||
|
||||
void manual_connection ( bool b );
|
||||
bool has_group_affinity ( void ) const;
|
||||
void disconnect_auto_inputs ( const char *exclude_pattern );
|
||||
void auto_connect_outputs ( void );
|
||||
bool maybe_auto_connect_output ( Module::Port *p );
|
||||
|
||||
|
@ -169,12 +171,15 @@ public:
|
|||
|
||||
Controller_Module *spatializer ( void );
|
||||
|
||||
Group *group ( void ) { return _group;}
|
||||
Group *group ( void ) { return _group; }
|
||||
void clear_group ( void ) { _group = NULL; }
|
||||
|
||||
// int group ( void ) const;
|
||||
void group ( Group * );
|
||||
void send_feedback ( void );
|
||||
void send_feedback ( bool force );
|
||||
void schedule_feedback ( void );
|
||||
int number ( void ) const;
|
||||
void number ( int );
|
||||
static bool import_strip ( const char *filename );
|
||||
|
||||
void command_toggle_fader_view ( void );
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Module.H"
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/fl_ask.H>
|
||||
#include <FL/Enumerations.H>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -47,6 +48,9 @@
|
|||
|
||||
#include "string_util.h"
|
||||
|
||||
#include "time.h"
|
||||
|
||||
|
||||
|
||||
|
||||
nframes_t Module::_sample_rate = 0;
|
||||
|
@ -104,27 +108,36 @@ Module::~Module ( )
|
|||
if ( control_input[i].connected() )
|
||||
{
|
||||
Module *o = (Module*)control_input[i].connected_port()->module();
|
||||
|
||||
if ( ! o->is_default() )
|
||||
{
|
||||
control_input[i].disconnect();
|
||||
|
||||
DMESSAGE( "Deleting connected module %s", o->label() );
|
||||
|
||||
delete o;
|
||||
}
|
||||
else
|
||||
{
|
||||
control_input[i].disconnect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !o )
|
||||
{
|
||||
DWARNING( "Programming error. Connected port has null module. %s %s",
|
||||
|
||||
label(),
|
||||
control_input[i].connected_port()->name());
|
||||
}
|
||||
|
||||
control_input[i].disconnect();
|
||||
|
||||
if ( o )
|
||||
{
|
||||
if ( ! o->is_default() )
|
||||
{
|
||||
DMESSAGE( "Deleting connected module %s", o->label() );
|
||||
|
||||
delete o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
control_input[i].destroy_osc_port();
|
||||
}
|
||||
for ( unsigned int i = 0; i < control_output.size(); ++i )
|
||||
control_output[i].disconnect();
|
||||
|
||||
aux_audio_output.clear();
|
||||
aux_audio_input.clear();
|
||||
|
||||
audio_input.clear();
|
||||
audio_output.clear();
|
||||
|
||||
|
@ -156,7 +169,9 @@ Module::init ( void )
|
|||
_chain = 0;
|
||||
_instances = 1;
|
||||
_bypass = 0;
|
||||
|
||||
_base_label = NULL;
|
||||
_number = -2; /* magic number indicates old instance, before numbering */
|
||||
|
||||
box( FL_UP_BOX );
|
||||
labeltype( FL_NO_LABEL );
|
||||
align( FL_ALIGN_CENTER | FL_ALIGN_INSIDE );
|
||||
|
@ -164,7 +179,9 @@ Module::init ( void )
|
|||
selection_color( FL_YELLOW );
|
||||
|
||||
labelsize(12);
|
||||
color( fl_rgb_color( 122,190,200 ) );
|
||||
|
||||
color( fl_color_average( fl_rgb_color( 0x3a, 0x99, 0x7c ), FL_BACKGROUND_COLOR, 1.0f ));
|
||||
|
||||
tooltip();
|
||||
}
|
||||
|
||||
|
@ -192,6 +209,8 @@ Module::get ( Log_Entry &e ) const
|
|||
e.add( ":is_default", is_default() );
|
||||
e.add( ":chain", chain() );
|
||||
e.add( ":active", ! bypass() );
|
||||
if ( number() >= 0 )
|
||||
e.add( ":number", number() );
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -222,7 +241,8 @@ Module::copy ( void ) const
|
|||
/* we don't want this module to get added to the current
|
||||
chain... */
|
||||
if ( !( !strcmp( s, ":chain" ) ||
|
||||
!strcmp( s, ":is_default" ) ) )
|
||||
!strcmp( s, ":is_default" ) ||
|
||||
!strcmp( s, ":number" ) ) )
|
||||
{
|
||||
DMESSAGE( "%s = %s", s, v );
|
||||
ne->add_raw( s, v );
|
||||
|
@ -235,6 +255,7 @@ Module::copy ( void ) const
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Module::paste_before ( void )
|
||||
{
|
||||
|
@ -251,6 +272,8 @@ Module::paste_before ( void )
|
|||
|
||||
m->set( le );
|
||||
|
||||
m->number(-1);
|
||||
|
||||
if ( ! chain()->insert( this, m ) )
|
||||
{
|
||||
fl_alert( "Copied module cannot be inserted at this point in the chain" );
|
||||
|
@ -264,22 +287,48 @@ Module::paste_before ( void )
|
|||
m->copy();
|
||||
}
|
||||
|
||||
void
|
||||
Module::number ( int v )
|
||||
{
|
||||
_number = v;
|
||||
|
||||
char s[255];
|
||||
|
||||
if ( v > 0 && !is_default() )
|
||||
snprintf( s, sizeof(s), "%s.%i", base_label(), v );
|
||||
else
|
||||
snprintf( s, sizeof(s), "%s", base_label() );
|
||||
|
||||
copy_label( s );
|
||||
}
|
||||
|
||||
void
|
||||
Module::base_label ( const char *s )
|
||||
{
|
||||
if ( _base_label )
|
||||
free( _base_label );
|
||||
|
||||
_base_label = NULL;
|
||||
|
||||
if ( s )
|
||||
_base_label = strdup(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Module::Port::disconnect_from_strip ( Mixer_Strip *o )
|
||||
{
|
||||
for ( std::list<Port*>::iterator i = _connected.begin(); i != _connected.end(); i++ )
|
||||
for ( std::list<Port*>::iterator i = _connected.begin(); i != _connected.end(); )
|
||||
{
|
||||
Port *p = *i;
|
||||
|
||||
i++; /* iterator trick */
|
||||
|
||||
if ( p->module()->chain()->strip() == o )
|
||||
{
|
||||
/* iterator about to be invalidated... */
|
||||
i = _connected.erase(i);
|
||||
|
||||
disconnect(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,8 +368,11 @@ Module::Port::osc_number_path ( void )
|
|||
}
|
||||
|
||||
void
|
||||
Module::Port::send_feedback ( void )
|
||||
Module::Port::send_feedback ( bool force )
|
||||
{
|
||||
if ( !force && !_pending_feedback )
|
||||
return;
|
||||
|
||||
float f = control_value();
|
||||
|
||||
if ( hints.ranged )
|
||||
|
@ -333,26 +385,53 @@ Module::Port::send_feedback ( void )
|
|||
f = ( f - offset ) / scale;
|
||||
}
|
||||
|
||||
if ( f > 1.0 )
|
||||
f = 1.0;
|
||||
else if ( f < 0.0 )
|
||||
f = 0.0;
|
||||
if ( f > 1.0f )
|
||||
f = 1.0f;
|
||||
else if ( f < 0.0f )
|
||||
f = 0.0f;
|
||||
|
||||
/* struct timespec t; */
|
||||
/* clock_gettime( CLOCK_MONOTONIC, &t ); */
|
||||
|
||||
/* /\* don't send feedback more at more than 30Hz rate. *\/ */
|
||||
/* unsigned long long ms = (t.tv_sec * 1000 + ( t.tv_nsec / 1000000 )); */
|
||||
/* if ( ms - _feedback_milliseconds < 1000 / 30 ) */
|
||||
/* return; */
|
||||
|
||||
/* _feedback_milliseconds = ms; */
|
||||
|
||||
if ( _scaled_signal )
|
||||
{
|
||||
/* send feedback for by_name signal */
|
||||
mixer->osc_endpoint->send_feedback( _scaled_signal->path(), f );
|
||||
|
||||
/* send feedback for by number signal */
|
||||
mixer->osc_endpoint->send_feedback( osc_number_path(), f );
|
||||
/* if ( fabsf( _feedback_value - f ) > (1.0f / 128.0f) ) */
|
||||
{
|
||||
/* only send feedback if value has changed significantly since the last time we sent it. */
|
||||
/* DMESSAGE( "signal value: %f, controL_value: %f", _scaled_signal->value(), f ); */
|
||||
/* send feedback for by_name signal */
|
||||
mixer->osc_endpoint->send_feedback( _scaled_signal->path(), f, force );
|
||||
|
||||
/* send feedback for by number signal */
|
||||
mixer->osc_endpoint->send_feedback( osc_number_path(), f, force );
|
||||
|
||||
/* _feedback_value = f; */
|
||||
|
||||
_pending_feedback = false;
|
||||
/* _scaled_signal->value( f ); */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Module::send_feedback ( void )
|
||||
Module::schedule_feedback ( void )
|
||||
{
|
||||
for ( int i = 0; i < ncontrol_inputs(); i++ )
|
||||
control_input[i].send_feedback();
|
||||
control_input[i].schedule_feedback();
|
||||
}
|
||||
|
||||
void
|
||||
Module::send_feedback ( bool force )
|
||||
{
|
||||
for ( int i = 0; i < ncontrol_inputs(); i++ )
|
||||
control_input[i].send_feedback(force);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -361,7 +440,11 @@ Module::handle_control_changed ( Port *p )
|
|||
if ( _editor )
|
||||
_editor->handle_control_changed ( p );
|
||||
|
||||
p->send_feedback();
|
||||
|
||||
p->schedule_feedback();
|
||||
|
||||
/* DMESSAGE("Control changed"); */
|
||||
/* p->send_feedback(false); */
|
||||
}
|
||||
|
||||
/* bool */
|
||||
|
@ -387,12 +470,7 @@ Module::Port::generate_osc_path ()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int n = module()->chain()->get_module_instance_number( module() );
|
||||
|
||||
if ( n > 0 )
|
||||
asprintf( &path, "/strip/%s/%s.%i/%s", module()->chain()->name(), p->module()->label(), n, p->name() );
|
||||
else
|
||||
asprintf( &path, "/strip/%s/%s/%s", module()->chain()->name(), p->module()->label(), p->name() );
|
||||
asprintf( &path, "/strip/%s/%s/%s", module()->chain()->name(), p->module()->label(), p->name() );
|
||||
|
||||
char *s = escape_url( path );
|
||||
|
||||
|
@ -531,6 +609,24 @@ Module::Port::osc_control_change_cv ( float v, void *user_data )
|
|||
void
|
||||
Module::set ( Log_Entry &e )
|
||||
{
|
||||
/* have to do this before adding to chain... */
|
||||
|
||||
int n = -2;
|
||||
|
||||
for ( int i = 0; i < e.size(); ++i )
|
||||
{
|
||||
const char *s, *v;
|
||||
|
||||
e.get( i, &s, &v );
|
||||
|
||||
if ( ! strcmp(s, ":number" ) )
|
||||
{
|
||||
n = atoi(v);
|
||||
}
|
||||
}
|
||||
|
||||
number(n);
|
||||
|
||||
for ( int i = 0; i < e.size(); ++i )
|
||||
{
|
||||
const char *s, *v;
|
||||
|
@ -614,18 +710,21 @@ Module::chain ( Chain *v )
|
|||
char *
|
||||
Module::get_parameters ( void ) const
|
||||
{
|
||||
char *s = new char[1024];
|
||||
int len = control_input.size() * 50;
|
||||
char *s = new char[ len ];
|
||||
|
||||
s[0] = 0;
|
||||
char *sp = s;
|
||||
|
||||
if ( control_input.size() )
|
||||
{
|
||||
for ( unsigned int i = 0; i < control_input.size(); ++i )
|
||||
sp += snprintf( sp, 1024 - (sp - s),"%f:", control_input[i].control_value() );
|
||||
sp += snprintf( sp, len - (sp - s),"%f:", control_input[i].control_value() );
|
||||
|
||||
*(sp - 1) = '\0';
|
||||
}
|
||||
|
||||
/* DMESSAGE("get_parameters: %s",s); */
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -677,6 +776,9 @@ Module::draw_box ( int tx, int ty, int tw, int th )
|
|||
|
||||
Fl_Color c = color();
|
||||
|
||||
if ( bypass() )
|
||||
c = fl_darker(fl_darker(c));
|
||||
|
||||
if ( ! active_r() )
|
||||
c = fl_inactive( c );
|
||||
|
||||
|
@ -767,8 +869,14 @@ Module::draw_label ( int tx, int ty, int tw, int th )
|
|||
|
||||
Fl_Color c = fl_contrast( FL_FOREGROUND_COLOR, color() );
|
||||
|
||||
fl_color( active_r() && ! bypass() ? c : fl_inactive(c) );
|
||||
if ( bypass() )
|
||||
c = fl_darker(c);
|
||||
|
||||
/* fl_color( active_r() && ! bypass() ? c : fl_inactive(c) ); */
|
||||
|
||||
if ( !active_r() )
|
||||
c = fl_inactive(c);
|
||||
|
||||
fl_font( FL_HELVETICA, labelsize() );
|
||||
|
||||
char *di = strstr( lab, " -" );
|
||||
|
@ -817,15 +925,18 @@ Module::draw_label ( int tx, int ty, int tw, int th )
|
|||
|
||||
}
|
||||
|
||||
|
||||
fl_color( c );
|
||||
|
||||
fl_draw( s ? s : lab, tx, ty, tw, th, align() | FL_ALIGN_CLIP );
|
||||
|
||||
if ( bypass() )
|
||||
{
|
||||
fl_color( fl_color_add_alpha( fl_color(), 127 ) );
|
||||
fl_line_style( FL_SOLID, 2 );
|
||||
fl_line( tx, ty + th * 0.5, tx + tw, ty + th * 0.5 );
|
||||
fl_line_style( FL_SOLID, 0 );
|
||||
}
|
||||
/* if ( bypass() ) */
|
||||
/* { */
|
||||
/* fl_color( fl_color_add_alpha( fl_color(), 127 ) ); */
|
||||
/* fl_line_style( FL_SOLID, 2 ); */
|
||||
/* fl_line( tx, ty + th * 0.5, tx + tw, ty + th * 0.5 ); */
|
||||
/* fl_line_style( FL_SOLID, 0 ); */
|
||||
/* } */
|
||||
|
||||
|
||||
free(lab);
|
||||
|
@ -846,19 +957,7 @@ Module::insert_menu_cb ( const Fl_Menu_ *m )
|
|||
|
||||
if ( !strcmp( picked, "Aux" ) )
|
||||
{
|
||||
int n = 0;
|
||||
for ( int i = 0; i < chain()->modules(); i++ )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -876,9 +975,6 @@ Module::insert_menu_cb ( const Fl_Menu_ *m )
|
|||
Spatializer_Module *jm = new Spatializer_Module();
|
||||
|
||||
jm->chain( chain() );
|
||||
// jm->number( n );
|
||||
// jm->configure_inputs( ninputs() );
|
||||
// jm->configure_outputs( ninputs() );
|
||||
jm->initialize();
|
||||
|
||||
mod = jm;
|
||||
|
@ -886,8 +982,6 @@ Module::insert_menu_cb ( const Fl_Menu_ *m )
|
|||
}
|
||||
else if ( !strcmp( picked, "Gain" ) )
|
||||
mod = new Gain_Module();
|
||||
/* else if ( !strcmp( picked, "Spatializer" ) ) */
|
||||
/* mod = new Spatializer_Module(); */
|
||||
else if ( !strcmp( picked, "Meter" ) )
|
||||
mod = new Meter_Module();
|
||||
else if ( !strcmp( picked, "Mono Pan" ))
|
||||
|
@ -908,6 +1002,8 @@ Module::insert_menu_cb ( const Fl_Menu_ *m )
|
|||
|
||||
if ( mod )
|
||||
{
|
||||
mod->number(-1);
|
||||
|
||||
if ( ! chain()->insert( this, mod ) )
|
||||
{
|
||||
fl_alert( "Cannot insert this module at this point in the chain" );
|
||||
|
@ -1180,7 +1276,19 @@ Module::freeze_ports ( void )
|
|||
for ( int i = 0; i < ncontrol_inputs(); ++i )
|
||||
{
|
||||
if ( control_input[i].connected() )
|
||||
control_input[i].connected_port()->module()->freeze_ports();
|
||||
{
|
||||
if ( ! control_input[i].connected_port()->module() )
|
||||
{
|
||||
DWARNING( "Programming error. Connected port has null module. %s %s",
|
||||
|
||||
name(),
|
||||
control_input[i].connected_port()->name());
|
||||
}
|
||||
else
|
||||
{
|
||||
control_input[i].connected_port()->module()->freeze_ports();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( unsigned int i = 0; i < aux_audio_input.size(); ++i )
|
||||
|
@ -1247,10 +1355,10 @@ Module::auto_disconnect_outputs ( void )
|
|||
{
|
||||
Module::Port *p = &aux_audio_output[i];
|
||||
|
||||
if ( p->connected_port() )
|
||||
while ( p->connected() )
|
||||
{
|
||||
p->connected_port()->jack_port()->disconnect( p->jack_port()->jack_name() );
|
||||
p->disconnect();
|
||||
p->connected_port()->jack_port()->disconnect( p->jack_port()->jack_name() );
|
||||
p->disconnect(p->connected_port());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,14 +46,17 @@ class Module : public Fl_Group, public Loggable {
|
|||
int _ins;
|
||||
int _outs;
|
||||
int _instances;
|
||||
nframes_t _nframes;
|
||||
Chain *_chain;
|
||||
bool _is_default;
|
||||
|
||||
char *_base_label;
|
||||
|
||||
nframes_t _nframes;
|
||||
static nframes_t _sample_rate;
|
||||
static Module *_copied_module_empty;
|
||||
static char *_copied_module_settings;
|
||||
|
||||
int _number;
|
||||
|
||||
void init ( void );
|
||||
|
||||
void insert_menu_cb ( const Fl_Menu_ *m );
|
||||
|
@ -74,6 +77,13 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
|
||||
virtual int number ( void ) const { return _number; }
|
||||
virtual void number ( int v );
|
||||
|
||||
virtual const char * base_label ( void ) const { return _base_label ? _base_label : name(); }
|
||||
virtual void base_label ( const char * );
|
||||
|
||||
virtual nframes_t get_module_latency ( void ) const { return 0; }
|
||||
|
||||
virtual void get_latency ( JACK::Port::direction_e dir, nframes_t *min, nframes_t *max ) const;
|
||||
|
@ -103,6 +113,7 @@ public:
|
|||
connected_port()->_buf = _buf;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum Direction { INPUT, OUTPUT };
|
||||
|
@ -120,7 +131,7 @@ public:
|
|||
float default_value;
|
||||
int dimensions;
|
||||
bool visible;
|
||||
|
||||
|
||||
Hints ( )
|
||||
{
|
||||
type = LINEAR;
|
||||
|
@ -153,6 +164,9 @@ public:
|
|||
_by_number_path = 0;
|
||||
_by_number_number = -1;
|
||||
_jack_port = 0;
|
||||
/* _feedback_value = -2; */
|
||||
_pending_feedback = false;
|
||||
_feedback_milliseconds = 0;
|
||||
}
|
||||
|
||||
Port ( const Port& p )
|
||||
|
@ -169,21 +183,27 @@ public:
|
|||
_by_number_path = 0;
|
||||
_by_number_number = -1;
|
||||
_jack_port = p._jack_port;
|
||||
/* _feedback_value = p._feedback_value; */
|
||||
}
|
||||
|
||||
virtual ~Port ( )
|
||||
{
|
||||
/* FIXME: will this cause problems with cloning an instance? */
|
||||
disconnect();
|
||||
|
||||
if ( _by_number_path )
|
||||
free( _by_number_path );
|
||||
_by_number_path = NULL;
|
||||
}
|
||||
|
||||
|
||||
nframes_t nframes ( void ) const { return _nframes; }
|
||||
void nframes ( nframes_t n) { _nframes = n; }
|
||||
const char *name ( void ) const { return _name; }
|
||||
Type type ( void ) const { return _type; }
|
||||
Direction direction ( void ) const { return _direction; }
|
||||
|
||||
Module * module ( void ) const { return _module; }
|
||||
nframes_t nframes ( void ) const { return _nframes; }
|
||||
|
||||
void buffer ( void *buf, nframes_t nframes ) { _buf = buf; _nframes = nframes; };
|
||||
void *buffer ( void ) const { return _buf; }
|
||||
|
@ -253,14 +273,27 @@ public:
|
|||
/* control and external audio ports belong to a graph */
|
||||
return _connected.size() > 0;
|
||||
}
|
||||
|
||||
unsigned int nconnected ( void ) const { return _connected.size(); }
|
||||
|
||||
bool connected_osc ( void ) const;
|
||||
|
||||
Port *connected_port ( void ) const
|
||||
{
|
||||
ASSERT( _type == Port::CONTROL, "Operation only available for control ports" );
|
||||
return _connected.size() == 0 ? NULL : _connected.front();
|
||||
}
|
||||
|
||||
Port *connected_port ( int n ) const
|
||||
{
|
||||
int j = 0;
|
||||
for ( std::list<Module::Port*>::const_iterator i = _connected.begin();
|
||||
i != _connected.end(); ++i, ++j )
|
||||
if ( j == n )
|
||||
return *i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void connect_to ( Port *to )
|
||||
{
|
||||
if ( _type != Port::AUX_AUDIO )
|
||||
|
@ -295,7 +328,7 @@ public:
|
|||
_buf = buf;
|
||||
}
|
||||
|
||||
void send_feedback ( void );
|
||||
void send_feedback ( bool force );
|
||||
|
||||
bool connected_to ( Port *p )
|
||||
{
|
||||
|
@ -321,23 +354,15 @@ public:
|
|||
/* disconnect from *all* connected ports */
|
||||
void disconnect ( void )
|
||||
{
|
||||
if ( _connected.size() )
|
||||
{
|
||||
for ( std::list<Port*>::iterator i = _connected.begin(); i != _connected.end(); i++ )
|
||||
{
|
||||
Port *p = *i;
|
||||
|
||||
/* iterator about to be invalidated... */
|
||||
i = _connected.erase(i);
|
||||
|
||||
disconnect(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ( _connected.size() )
|
||||
disconnect(_connected.front());
|
||||
}
|
||||
|
||||
void jack_port ( JACK::Port *v ) { _jack_port = v; }
|
||||
JACK::Port *jack_port ( void ) const { return _jack_port; }
|
||||
|
||||
void schedule_feedback ( void ) { _pending_feedback = true; }
|
||||
|
||||
private:
|
||||
|
||||
char *generate_osc_path ( void );
|
||||
|
@ -356,6 +381,10 @@ public:
|
|||
OSC::Signal *_scaled_signal;
|
||||
OSC::Signal *_unscaled_signal;
|
||||
|
||||
/* float _feedback_value; */
|
||||
bool _pending_feedback;
|
||||
unsigned long long _feedback_milliseconds;
|
||||
|
||||
static void handle_signal_connection_state_changed ( OSC::Signal *, void *o );
|
||||
};
|
||||
|
||||
|
@ -375,7 +404,6 @@ public:
|
|||
|
||||
LOG_NAME_FUNC( Module );
|
||||
|
||||
nframes_t nframes ( void ) const { return _nframes; }
|
||||
virtual void resize_buffers ( nframes_t v ) { _nframes = v; }
|
||||
|
||||
|
||||
|
@ -496,7 +524,8 @@ public:
|
|||
|
||||
bool show_analysis_window ( void );
|
||||
|
||||
void send_feedback ( void );
|
||||
void send_feedback ( bool force );
|
||||
void schedule_feedback ( void );
|
||||
virtual bool initialize ( void ) { return true; }
|
||||
|
||||
/* for the given number of inputs, return how many outputs this
|
||||
|
@ -555,7 +584,9 @@ protected:
|
|||
bool add_aux_port ( bool input, const char *prefix, int n , JACK::Port::type_e type );
|
||||
|
||||
public:
|
||||
nframes_t sample_rate ( void ) const { return Module::_sample_rate; }
|
||||
|
||||
static nframes_t sample_rate ( void ) { return Module::_sample_rate; }
|
||||
nframes_t nframes ( void ) { return _nframes; }
|
||||
|
||||
|
||||
void auto_connect_outputs();
|
||||
|
@ -568,7 +599,7 @@ public:
|
|||
bool add_aux_audio_input ( const char *prefix, int n );
|
||||
bool add_aux_cv_input ( const char *prefix, int n );
|
||||
|
||||
static void set_sample_rate ( nframes_t srate ) { _sample_rate = srate; }
|
||||
static void sample_rate ( nframes_t srate ) { _sample_rate = srate; }
|
||||
|
||||
void command_open_parameter_editor();
|
||||
virtual void command_activate ( void );
|
||||
|
|
|
@ -174,8 +174,8 @@ Module_Parameter_Editor::make_controls ( void )
|
|||
|
||||
control_pack->clear();
|
||||
|
||||
{ SpectrumView *o = spectrum_view = new SpectrumView( 25, 40, 300, 240, "Spectrum" );
|
||||
o->labelsize(9);
|
||||
{ SpectrumView *o = spectrum_view = new SpectrumView( 25, 40, 360, 300, "Spectrum" );
|
||||
o->labelsize(14);
|
||||
o->align(FL_ALIGN_TOP);
|
||||
|
||||
|
||||
|
@ -199,7 +199,7 @@ Module_Parameter_Editor::make_controls ( void )
|
|||
float radius_value = 0.0f;
|
||||
|
||||
Fl_Color fc = fl_color_add_alpha( FL_CYAN, 200 );
|
||||
Fl_Color bc = FL_BACKGROUND2_COLOR;
|
||||
Fl_Color bc = FL_BACKGROUND_COLOR;
|
||||
|
||||
controls_by_port.resize( module->control_input.size() );
|
||||
|
||||
|
@ -210,7 +210,7 @@ Module_Parameter_Editor::make_controls ( void )
|
|||
control_pack->flow(true);
|
||||
control_pack->flowdown(true);
|
||||
control_pack->type( FL_HORIZONTAL );
|
||||
control_pack->size( 900, 240 );
|
||||
control_pack->size( 900, 300 );
|
||||
}
|
||||
else if ( mode_choice->value() == 2 )
|
||||
{
|
||||
|
@ -306,11 +306,11 @@ Module_Parameter_Editor::make_controls ( void )
|
|||
o->minimum( p->hints.minimum );
|
||||
o->maximum( p->hints.maximum );
|
||||
}
|
||||
o->color( bc );
|
||||
o->color( FL_BACKGROUND_COLOR );
|
||||
o->selection_color( fc );
|
||||
o->value( p->control_value() );
|
||||
o->align(FL_ALIGN_TOP);
|
||||
o->box( FL_DOWN_BOX );
|
||||
o->box( FL_FLAT_BOX );
|
||||
|
||||
/* a couple of plugins have ridiculously small units */
|
||||
float r = fabs( p->hints.maximum - p->hints.minimum );
|
||||
|
@ -383,11 +383,12 @@ Module_Parameter_Editor::make_controls ( void )
|
|||
o->color( bc );
|
||||
o->selection_color( fc );
|
||||
o->value( p->control_value() );
|
||||
o->box( FL_BORDER_BOX );
|
||||
}
|
||||
|
||||
}
|
||||
// w->align(FL_ALIGN_TOP);
|
||||
w->labelsize( 10 );
|
||||
w->labelsize( 14 );
|
||||
|
||||
controls_by_port[i] = w;
|
||||
|
||||
|
@ -422,7 +423,7 @@ Module_Parameter_Editor::make_controls ( void )
|
|||
o->align(FL_ALIGN_TOP);
|
||||
o->when(FL_WHEN_CHANGED);
|
||||
o->label( "Spatialization" );
|
||||
o->labelsize( 10 );
|
||||
o->labelsize( 14 );
|
||||
|
||||
_callback_data.push_back( callback_data( this, azimuth_port_number, elevation_port_number, radius_port_number ) );
|
||||
o->callback( cb_panner_value_handle, &_callback_data.back() );
|
||||
|
|
|
@ -66,8 +66,22 @@ Mono_Pan_Module::handle_sample_rate_change ( nframes_t n )
|
|||
}
|
||||
|
||||
bool
|
||||
Mono_Pan_Module::configure_inputs ( int )
|
||||
Mono_Pan_Module::configure_inputs ( int n )
|
||||
{
|
||||
THREAD_ASSERT( UI );
|
||||
|
||||
int on = audio_input.size();
|
||||
|
||||
if ( n > on )
|
||||
{
|
||||
add_port( Port( this, Port::INPUT, Port::AUDIO ) );
|
||||
}
|
||||
else if ( n < on )
|
||||
{
|
||||
audio_input.back().disconnect();
|
||||
audio_input.pop_back();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -82,7 +96,10 @@ Mono_Pan_Module::process ( nframes_t nframes )
|
|||
{
|
||||
if ( unlikely( bypass() ) )
|
||||
{
|
||||
buffer_copy( (sample_t*)audio_output[1].buffer(), (sample_t*)audio_input[0].buffer(), nframes );
|
||||
if ( audio_input.size() == 1 )
|
||||
{
|
||||
buffer_copy( (sample_t*)audio_output[1].buffer(), (sample_t*)audio_input[0].buffer(), nframes );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -90,11 +107,18 @@ Mono_Pan_Module::process ( nframes_t nframes )
|
|||
|
||||
sample_t gainbuf[nframes];
|
||||
bool use_gainbuf = smoothing.apply( gainbuf, nframes, gt );
|
||||
|
||||
|
||||
if ( audio_input.size() == 2 )
|
||||
{
|
||||
/* convert stereo to mono */
|
||||
buffer_mix( (sample_t*)audio_input[0].buffer(),
|
||||
(sample_t*)audio_input[1].buffer(),
|
||||
nframes );
|
||||
}
|
||||
|
||||
if ( unlikely( use_gainbuf ) )
|
||||
{
|
||||
/* right channel */
|
||||
|
||||
/* right channel */
|
||||
buffer_copy_and_apply_gain_buffer( (sample_t*)audio_output[1].buffer(),
|
||||
(sample_t*)audio_input[0].buffer(),
|
||||
gainbuf,
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
|
||||
const char *name ( void ) const { return "Mono Pan"; }
|
||||
|
||||
int can_support_inputs ( int n ) { return ( n == 1 ) ? 2 : -1; }
|
||||
int can_support_inputs ( int n ) { return ( n == 1 || n == 2 ) ? 2 : -1; }
|
||||
bool configure_inputs ( int n );
|
||||
|
||||
LOG_CREATE_FUNC( Mono_Pan_Module );
|
||||
|
|
|
@ -56,6 +56,7 @@ Panner::Panner ( int X, int Y, int W, int H, const char *L ) :
|
|||
o->add("5 Meters",0,0,&ranges[2]);
|
||||
o->add("10 Meters",0,0,&ranges[3]);
|
||||
o->add("15 Meters",0,0,&ranges[4]);
|
||||
o->textcolor( fl_contrast( FL_GRAY0, FL_FOREGROUND_COLOR ));
|
||||
o->value(_range_mode);
|
||||
o->callback( cb_mode, this );
|
||||
}
|
||||
|
@ -69,6 +70,7 @@ Panner::Panner ( int X, int Y, int W, int H, const char *L ) :
|
|||
o->add("Spherical");
|
||||
o->add("Planar");
|
||||
o->value(_projection_mode);
|
||||
o->textcolor( fl_contrast( FL_GRAY0, FL_FOREGROUND_COLOR ));
|
||||
o->callback( cb_mode, this );
|
||||
}
|
||||
|
||||
|
@ -378,7 +380,7 @@ Panner::draw ( void )
|
|||
if ( ! p->visible )
|
||||
continue;
|
||||
|
||||
Fl_Color c = fl_color_add_alpha( p->color, 100 );
|
||||
Fl_Color c = fl_color_add_alpha( p->color, 150 );
|
||||
|
||||
fl_color(c);
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ Plugin_Module::Plugin_Module ( ) : Module( 50, 35, name() )
|
|||
{
|
||||
init();
|
||||
|
||||
color( fl_color_average( fl_rgb_color( 0x99, 0x7c, 0x3a ), FL_BACKGROUND_COLOR, 1.0f ));
|
||||
|
||||
end();
|
||||
|
||||
log_create();
|
||||
|
@ -96,6 +98,24 @@ Plugin_Module::get ( Log_Entry &e ) const
|
|||
void
|
||||
Plugin_Module::set ( Log_Entry &e )
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
/* we need to have number() defined before we create the control inputs in load() */
|
||||
for ( int i = 0; i < e.size(); ++i )
|
||||
{
|
||||
const char *s, *v;
|
||||
|
||||
e.get( i, &s, &v );
|
||||
|
||||
if ( ! strcmp(s, ":number" ) )
|
||||
{
|
||||
n = atoi(v);
|
||||
}
|
||||
}
|
||||
|
||||
/* need to call this to set label even for version 0 modules */
|
||||
number(n);
|
||||
|
||||
for ( int i = 0; i < e.size(); ++i )
|
||||
{
|
||||
const char *s, *v;
|
||||
|
@ -441,11 +461,15 @@ Plugin_Module::load ( unsigned long id )
|
|||
{
|
||||
/* unknown plugin ID */
|
||||
WARNING( "Unknown plugin ID: %lu", id );
|
||||
label( "----" );
|
||||
char s[25];
|
||||
|
||||
snprintf( s, 24, "! %lu", id );
|
||||
|
||||
base_label( s );
|
||||
return false;
|
||||
}
|
||||
|
||||
label( _idata->descriptor->Name );
|
||||
base_label( _idata->descriptor->Name );
|
||||
|
||||
if ( _idata->descriptor )
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ char Project::_name[256];
|
|||
char Project::_created_on[40];
|
||||
char Project::_path[512];
|
||||
bool Project::_is_open = false;
|
||||
bool Project::_is_opening = false;
|
||||
bool Project::_is_opening_closing = false;
|
||||
int Project::_lockfd = 0;
|
||||
|
||||
|
||||
|
@ -193,6 +193,8 @@ Project::close ( void )
|
|||
if ( ! save() )
|
||||
return false;
|
||||
|
||||
Project::_is_opening_closing = true;
|
||||
|
||||
Loggable::close();
|
||||
/* // write_info(); */
|
||||
|
||||
|
@ -203,6 +205,8 @@ Project::close ( void )
|
|||
|
||||
release_lock( &_lockfd, ".lock" );
|
||||
|
||||
Project::_is_opening_closing = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -262,7 +266,7 @@ Project::open ( const char *name )
|
|||
if ( version != PROJECT_VERSION )
|
||||
return E_VERSION;
|
||||
|
||||
_is_opening = true;
|
||||
_is_opening_closing = true;
|
||||
|
||||
if ( ! Loggable::replay( "snapshot" ) )
|
||||
return E_INVALID;
|
||||
|
@ -282,7 +286,7 @@ Project::open ( const char *name )
|
|||
|
||||
_is_open = true;
|
||||
|
||||
_is_opening = false;
|
||||
_is_opening_closing = false;
|
||||
// tle->load_timeline_settings();
|
||||
|
||||
// timeline->zoom_fit();
|
||||
|
|
|
@ -27,7 +27,7 @@ class Project
|
|||
|
||||
static int _lockfd;
|
||||
static bool _is_open;
|
||||
static bool _is_opening;
|
||||
static bool _is_opening_closing;
|
||||
static char _name[256];
|
||||
static char _path[512];
|
||||
static char _created_on[40];
|
||||
|
@ -62,5 +62,5 @@ public:
|
|||
|
||||
static const char *path ( void ) { return _path; }
|
||||
static const char *created_on ( void ) { return _created_on; }
|
||||
static const bool is_opening ( void ) { return _is_opening; }
|
||||
static const bool is_opening_closing ( void ) { return _is_opening_closing; }
|
||||
};
|
||||
|
|
|
@ -536,6 +536,8 @@ Spatializer_Module::Spatializer_Module ( ) : JACK_Module ( false )
|
|||
early_gain_smoothing.sample_rate( sample_rate() );
|
||||
delay_smoothing.cutoff( 0.5f );
|
||||
delay_smoothing.sample_rate( sample_rate() );
|
||||
azimuth_smoothing.sample_rate( sample_rate() );
|
||||
elevation_smoothing.sample_rate( sample_rate() );
|
||||
}
|
||||
|
||||
Spatializer_Module::~Spatializer_Module ( )
|
||||
|
@ -557,6 +559,8 @@ Spatializer_Module::handle_sample_rate_change ( nframes_t n )
|
|||
delay_smoothing.sample_rate( n );
|
||||
early_gain_smoothing.sample_rate( n );
|
||||
late_gain_smoothing.sample_rate( n );
|
||||
azimuth_smoothing.sample_rate( n );
|
||||
elevation_smoothing.sample_rate( n );
|
||||
|
||||
for ( unsigned int i = 0; i < audio_input.size(); i++ )
|
||||
{
|
||||
|
@ -626,9 +630,13 @@ Spatializer_Module::process ( nframes_t nframes )
|
|||
|
||||
sample_t gainbuf[nframes];
|
||||
sample_t delaybuf[nframes];
|
||||
|
||||
sample_t azimuthbuf[nframes];
|
||||
sample_t elevationbuf[nframes];
|
||||
|
||||
bool use_gainbuf = false;
|
||||
bool use_delaybuf = delay_smoothing.apply( delaybuf, nframes, delay_seconds );
|
||||
bool use_azimuthbuf = azimuth_smoothing.apply( azimuthbuf, nframes, azimuth );
|
||||
bool use_elevationbuf = elevation_smoothing.apply( elevationbuf, nframes, elevation );
|
||||
|
||||
for ( unsigned int i = 0; i < audio_input.size(); i++ )
|
||||
{
|
||||
|
@ -655,12 +663,30 @@ Spatializer_Module::process ( nframes_t nframes )
|
|||
buffer_apply_gain( (sample_t*)aux_audio_output[0].jack_port()->buffer(nframes), nframes, late_gain );
|
||||
}
|
||||
|
||||
|
||||
float early_angle = azimuth - angle;
|
||||
if ( early_angle > 180.0f )
|
||||
early_angle = -180 - ( early_angle - 180 );
|
||||
else if ( early_angle < -180.0f )
|
||||
early_angle = 180 - ( early_angle + 180 );
|
||||
|
||||
if ( !use_azimuthbuf )
|
||||
{
|
||||
/* for ( nframes_t i = 0; i < nframes; ++i ) */
|
||||
azimuthbuf[0] = azimuth + angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* for ( nframes_t i = 0; i < nframes; ++i ) */
|
||||
azimuthbuf[0] += angle;
|
||||
}
|
||||
|
||||
if ( !use_elevationbuf )
|
||||
elevationbuf[0] = elevation;
|
||||
|
||||
azimuth = azimuthbuf[0];
|
||||
elevation = elevationbuf[0];
|
||||
|
||||
/* send to early reverb */
|
||||
if ( audio_input.size() == 1 )
|
||||
{
|
||||
|
|
|
@ -32,6 +32,8 @@ class Spatializer_Module : public JACK_Module
|
|||
Value_Smoothing_Filter delay_smoothing;
|
||||
Value_Smoothing_Filter late_gain_smoothing;
|
||||
Value_Smoothing_Filter early_gain_smoothing;
|
||||
Value_Smoothing_Filter azimuth_smoothing;
|
||||
Value_Smoothing_Filter elevation_smoothing;
|
||||
|
||||
std::vector<filter*> _lowpass;
|
||||
std::vector<filter*> _highpass;
|
||||
|
|
|
@ -218,10 +218,19 @@ main ( int argc, char **argv )
|
|||
char *name = strdup( argv[0] );
|
||||
char *n = basename( name );
|
||||
|
||||
if ( ! strcmp( n, "non-mixer-noui" ) )
|
||||
if ( ! strcmp( n, "non-mixer-noui" ) )
|
||||
{
|
||||
DMESSAGE("Not running UI: invoked as non-mixer-noui");
|
||||
no_ui = true;
|
||||
|
||||
}
|
||||
|
||||
free( name );
|
||||
|
||||
if ( NULL == getenv("DISPLAY") )
|
||||
{
|
||||
DMESSAGE("Not running UI: $DISPLAY environment variable unset");
|
||||
no_ui = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! no_ui )
|
||||
|
@ -313,7 +322,6 @@ main ( int argc, char **argv )
|
|||
}
|
||||
else
|
||||
{
|
||||
DMESSAGE( "Not Running UI..." );
|
||||
while ( ! got_sigterm )
|
||||
{
|
||||
Fl::wait(2147483.648); /* magic number means forever */
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*******************************************************************************/
|
||||
/* Copyright (C) 2013 Jonathan Moore Liles */
|
||||
/* */
|
||||
|
@ -25,6 +24,7 @@
|
|||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <math.h>
|
||||
|
||||
using namespace MIDI;
|
||||
|
||||
|
@ -48,11 +48,15 @@ const char *APP_NAME = "non-midi-mapper";
|
|||
#undef APP_TITLE
|
||||
const char *APP_TITLE = "Non-MIDI-Mapper";
|
||||
#undef VERSION
|
||||
const char *VERSION = "1.0";
|
||||
const char *VERSION = "1.1";
|
||||
|
||||
const int FILE_VERSION = 1;
|
||||
|
||||
nsm_client_t *nsm;
|
||||
char *instance_name;
|
||||
|
||||
static nframes_t buffers = 0;
|
||||
|
||||
|
||||
OSC::Endpoint *osc = 0;
|
||||
/* const double NSM_CHECK_INTERVAL = 0.25f; */
|
||||
|
@ -121,9 +125,9 @@ public:
|
|||
|
||||
Engine ( )
|
||||
{
|
||||
input_ring_buf = jack_ringbuffer_create( 16 * 16 * sizeof( jack_midi_event_t ));
|
||||
input_ring_buf = jack_ringbuffer_create( 32 * 32 * sizeof( jack_midi_event_t ));
|
||||
jack_ringbuffer_reset( input_ring_buf );
|
||||
output_ring_buf = jack_ringbuffer_create( 16 * 16 * sizeof( jack_midi_event_t ));
|
||||
output_ring_buf = jack_ringbuffer_create( 32 * 32 * sizeof( jack_midi_event_t ));
|
||||
jack_ringbuffer_reset( output_ring_buf );
|
||||
|
||||
midi_input_port = 0;
|
||||
|
@ -134,20 +138,33 @@ public:
|
|||
{
|
||||
deactivate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int process ( nframes_t nframes )
|
||||
{
|
||||
++buffers;
|
||||
|
||||
/* process input */
|
||||
{
|
||||
if ( !midi_input_port )
|
||||
return 0;
|
||||
|
||||
|
||||
/* jack_position_t pos; */
|
||||
|
||||
/* jack_transport_query( this->jack_client(), &pos ); */
|
||||
|
||||
void *buf = midi_input_port->buffer( nframes );
|
||||
|
||||
jack_midi_event_t ev;
|
||||
|
||||
jack_nframes_t count = jack_midi_get_event_count( buf );
|
||||
|
||||
|
||||
/* if ( count > 0 ) */
|
||||
/* { */
|
||||
/* DMESSAGE( "Event count: %lu", count); */
|
||||
/* } */
|
||||
|
||||
/* place MIDI events into ringbuffer for non-RT thread */
|
||||
|
||||
for ( uint i = 0; i < count; ++i )
|
||||
|
@ -155,15 +172,26 @@ public:
|
|||
// MESSAGE( "Got midi input!" );
|
||||
|
||||
jack_midi_event_get( &ev, buf, i );
|
||||
|
||||
|
||||
midievent e;
|
||||
|
||||
/* e.timestamp( pos.frame + ev.time ); */
|
||||
e.timestamp( ev.time );
|
||||
e.status( ev.buffer[0] );
|
||||
e.lsb( ev.buffer[1] );
|
||||
if ( ev.size == 3 )
|
||||
e.msb( ev.buffer[2] );
|
||||
else
|
||||
e.msb( 0 );
|
||||
|
||||
/* /\* time is frame within cycle, convert to absolute tick *\/ */
|
||||
/* e.timestamp( ph + (ev.time / transport.frames_per_tick) ); */
|
||||
/* e.status( ev.buffer[0] ); */
|
||||
/* e.lsb( ev.buffer[1] ); */
|
||||
/* if ( ev.size == 3 ) */
|
||||
/* e.msb( ev.buffer[2] ); */
|
||||
|
||||
if ( jack_ringbuffer_write( input_ring_buf, (char*)&ev, sizeof( jack_midi_event_t ) ) != sizeof( jack_midi_event_t ) )
|
||||
|
||||
if ( jack_ringbuffer_write( input_ring_buf, (char*)&e, sizeof( midievent ) ) != sizeof( midievent ) )
|
||||
WARNING( "input buffer overrun" );
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +257,8 @@ public:
|
|||
|
||||
Engine *engine;
|
||||
|
||||
const float MAX_NRPN = 16383.0f;
|
||||
const unsigned int MAX_14BIT = 16383;
|
||||
const unsigned int MAX_7BIT = 127;
|
||||
|
||||
static char
|
||||
get_lsb( int i )
|
||||
|
@ -243,29 +272,48 @@ get_msb( int i )
|
|||
return ( i >> 7 ) & 0x7F;
|
||||
}
|
||||
|
||||
static int
|
||||
static unsigned int
|
||||
get_14bit ( char msb, char lsb )
|
||||
{
|
||||
return msb * 128 + lsb;
|
||||
}
|
||||
{
|
||||
return msb * (MAX_7BIT + 1) + lsb;
|
||||
}
|
||||
|
||||
class signal_mapping
|
||||
{
|
||||
public:
|
||||
|
||||
bool is_nrpn;
|
||||
// int nrpn;
|
||||
|
||||
bool is_nrpn14;
|
||||
bool is_toggle;
|
||||
|
||||
midievent event;
|
||||
|
||||
std::string signal_name;
|
||||
|
||||
OSC::Signal *signal;
|
||||
|
||||
nframes_t last_midi_tick;
|
||||
nframes_t last_feedback_tick;
|
||||
|
||||
int learning_value_msb;
|
||||
int learning_value_lsb;
|
||||
|
||||
|
||||
bool is_learning ( )
|
||||
{
|
||||
return NULL == signal;
|
||||
}
|
||||
|
||||
signal_mapping ( )
|
||||
{
|
||||
is_nrpn = false;
|
||||
is_nrpn14 = false;
|
||||
is_toggle =- false;
|
||||
signal = NULL;
|
||||
last_midi_tick = 0;
|
||||
last_feedback_tick = 0;
|
||||
learning_value_lsb = 0;
|
||||
learning_value_msb = 0;
|
||||
}
|
||||
|
||||
~signal_mapping ( )
|
||||
|
@ -275,37 +323,37 @@ public:
|
|||
signal = NULL;
|
||||
}
|
||||
|
||||
char *serialize ( void ) const
|
||||
{
|
||||
char *s;
|
||||
const char *opcode = 0;
|
||||
int v1 = 0;
|
||||
/* char *serialize ( void ) const */
|
||||
/* { */
|
||||
/* char *s; */
|
||||
/* const char *opcode = 0; */
|
||||
/* int v1 = 0; */
|
||||
|
||||
if ( is_nrpn )
|
||||
{
|
||||
opcode = "NRPN";
|
||||
v1 = get_14bit( event.msb(), event.lsb() );
|
||||
}
|
||||
else
|
||||
switch ( event.opcode() )
|
||||
{
|
||||
case MIDI::midievent::CONTROL_CHANGE:
|
||||
opcode = "CC";
|
||||
v1 = event.lsb();
|
||||
break;
|
||||
case MIDI::midievent::NOTE_ON:
|
||||
opcode = "NOTE_ON";
|
||||
v1 = event.note();
|
||||
break;
|
||||
default:
|
||||
// unsupported
|
||||
break;
|
||||
}
|
||||
/* if ( is_nrpn ) */
|
||||
/* { */
|
||||
/* opcode = is_nrpn14 ? "NRPN14" : "NRPN"; */
|
||||
/* v1 = get_14bit( event.msb(), event.lsb() ); */
|
||||
/* } */
|
||||
/* else */
|
||||
/* switch ( event.opcode() ) */
|
||||
/* { */
|
||||
/* case MIDI::midievent::CONTROL_CHANGE: */
|
||||
/* opcode = "CC"; */
|
||||
/* v1 = event.lsb(); */
|
||||
/* break; */
|
||||
/* case MIDI::midievent::NOTE_ON: */
|
||||
/* opcode = "NOTE_ON"; */
|
||||
/* v1 = event.note(); */
|
||||
/* break; */
|
||||
/* default: */
|
||||
/* // unsupported */
|
||||
/* break; */
|
||||
/* } */
|
||||
|
||||
asprintf( &s, "%s %d %d", opcode, event.channel(), v1 );
|
||||
/* asprintf( &s, "%s %d %d%s", opcode, event.channel(), v1, is_toggle ? " T" : "" ); */
|
||||
|
||||
return s;
|
||||
}
|
||||
/* return s; */
|
||||
/* } */
|
||||
|
||||
void deserialize ( const char *s )
|
||||
{
|
||||
|
@ -313,16 +361,16 @@ public:
|
|||
char *opcode;
|
||||
int control;
|
||||
|
||||
if ( 3 == sscanf( s, "%ms %d %d", &opcode, &channel, &control ) )
|
||||
if ( 3 == sscanf( s, "%ms %d %d", &opcode, &channel, &control ) )
|
||||
{
|
||||
event.channel( channel );
|
||||
event.opcode( MIDI::midievent::CONTROL_CHANGE );
|
||||
|
||||
is_nrpn = 0;
|
||||
is_nrpn = false;
|
||||
|
||||
if ( !strcmp( opcode, "NRPN" ) )
|
||||
{
|
||||
is_nrpn = 1;
|
||||
is_nrpn = true;
|
||||
|
||||
event.lsb( get_lsb( control ));
|
||||
event.msb( get_msb( control ));
|
||||
|
@ -334,6 +382,10 @@ public:
|
|||
|
||||
free(opcode);
|
||||
}
|
||||
else
|
||||
{
|
||||
DMESSAGE( "Failed to parse midi event descriptor: %s", s );
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -341,7 +393,15 @@ public:
|
|||
int signal_handler ( float value, void *user_data )
|
||||
{
|
||||
signal_mapping *m = (signal_mapping*)user_data;
|
||||
|
||||
|
||||
/* DMESSAGE( "Received value: %f", value ); */
|
||||
|
||||
m->last_feedback_tick = buffers;
|
||||
|
||||
/* magic number to give a release time to prevent thrashing. */
|
||||
/* if ( ! ( m->last_feedback_tick > m->last_midi_tick + 4 )) */
|
||||
/* return 0; */
|
||||
|
||||
if ( m->is_nrpn )
|
||||
{
|
||||
jack_midi_event_t jev[4];
|
||||
|
@ -373,7 +433,7 @@ int signal_handler ( float value, void *user_data )
|
|||
e.opcode( MIDI::midievent::CONTROL_CHANGE );
|
||||
e.channel( m->event.channel() );
|
||||
e.lsb( 6 );
|
||||
e.msb( int(value * MAX_NRPN ) >> 7 );
|
||||
e.msb( (int)(value * (float)MAX_14BIT) >> 7 );
|
||||
jev[2].size = e.size();
|
||||
e.raw( (byte_t*)&jev[2], e.size() );
|
||||
// e.pretty_print();
|
||||
|
@ -384,7 +444,7 @@ int signal_handler ( float value, void *user_data )
|
|||
e.opcode( MIDI::midievent::CONTROL_CHANGE );
|
||||
e.channel( m->event.channel() );
|
||||
e.lsb( 38 );
|
||||
e.msb( int( value * MAX_NRPN ) & 0x7F );
|
||||
e.msb( (int)(value * (float)MAX_14BIT) & 0x7F );
|
||||
jev[3].size = e.size();
|
||||
e.raw( (byte_t*)&jev[3], e.size() );
|
||||
// e.pretty_print();
|
||||
|
@ -401,7 +461,7 @@ int signal_handler ( float value, void *user_data )
|
|||
{
|
||||
jack_midi_event_t ev;
|
||||
|
||||
m->event.msb( value * 127.0f );
|
||||
m->event.msb( value * (float)MAX_7BIT );
|
||||
ev.size = m->event.size();
|
||||
m->event.raw( (byte_t*)&ev, m->event.size() );
|
||||
|
||||
|
@ -416,6 +476,7 @@ int signal_handler ( float value, void *user_data )
|
|||
|
||||
|
||||
std::map<std::string,signal_mapping> sig_map;
|
||||
std::map<int,std::string> sig_map_ordered;
|
||||
|
||||
bool
|
||||
save_settings ( void )
|
||||
|
@ -424,19 +485,38 @@ save_settings ( void )
|
|||
|
||||
if ( !fp )
|
||||
return false;
|
||||
|
||||
fprintf( fp, "# Non-MIDI-Mapper version %i\n", FILE_VERSION );
|
||||
|
||||
for ( std::map<std::string,signal_mapping>::const_iterator i = sig_map.begin();
|
||||
i != sig_map.end();
|
||||
for ( std::map<int,std::string>::const_iterator i = sig_map_ordered.begin();
|
||||
i != sig_map_ordered.end();
|
||||
i++ )
|
||||
{
|
||||
fprintf( fp, "[%s] %s\n", i->first.c_str(), i->second.signal_name.c_str() );
|
||||
signal_mapping &m = sig_map[i->second.c_str()];
|
||||
|
||||
/* char *midi_event = m.serialize(); */
|
||||
|
||||
/* FIXME: instead of T and NRPN14, use 1 7 and 14 (value significant bits).
|
||||
Also, use syntax like so: [NRPN 0 0] 1bit :: /foo/bar */
|
||||
fprintf( fp, "%s\t%s\t%s\n",
|
||||
i->second.c_str(),
|
||||
// midi_event,
|
||||
m.is_toggle ? "1-BIT" :
|
||||
m.is_nrpn && m.is_nrpn14 ? "14-BIT" :
|
||||
"7-BIT",
|
||||
m.signal_name.c_str() );
|
||||
|
||||
/* free(midi_event); */
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int max_signal = 0;
|
||||
|
||||
|
||||
bool
|
||||
load_settings ( void )
|
||||
|
@ -447,23 +527,55 @@ load_settings ( void )
|
|||
return false;
|
||||
|
||||
sig_map.clear();
|
||||
sig_map_ordered.clear();
|
||||
|
||||
char *signal_name;
|
||||
char *midi_event;
|
||||
char *flags = NULL;
|
||||
|
||||
max_signal = 0;
|
||||
|
||||
while ( 2 == fscanf( fp, "[%m[^]]] %m[^\n]\n", &midi_event, &signal_name ) )
|
||||
int version = 0;
|
||||
|
||||
if ( 1 == fscanf( fp, "# Non-MIDI-Mapper version %i\n", &version ) )
|
||||
{
|
||||
DMESSAGE( "%s, %s", midi_event, signal_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
version = 0;
|
||||
rewind(fp);
|
||||
}
|
||||
|
||||
DMESSAGE( "Detected file version %i", version);
|
||||
|
||||
while (
|
||||
( 1 == version &&
|
||||
3 == fscanf( fp, "%m[^\t]\t%m[^\t]\t%m[^\n]\n", &midi_event, &flags, &signal_name ) )
|
||||
||
|
||||
( 0 == version &&
|
||||
2 == fscanf( fp, "[%m[^]]] %m[^\n]\n", &midi_event, &signal_name ) ) )
|
||||
{
|
||||
DMESSAGE( "Read mapping: %s, %s (%s)", midi_event, signal_name, flags );
|
||||
|
||||
if ( sig_map.find( midi_event ) == sig_map.end() )
|
||||
{
|
||||
++max_signal;
|
||||
|
||||
signal_mapping m;
|
||||
|
||||
m.deserialize( midi_event );
|
||||
|
||||
if ( flags )
|
||||
{
|
||||
m.is_toggle = !strcmp( "1-BIT", flags );
|
||||
m.is_nrpn14 = !strcmp( "14-BIT", flags );
|
||||
}
|
||||
|
||||
sig_map[midi_event] = m;
|
||||
sig_map[midi_event].signal_name = signal_name;
|
||||
sig_map[midi_event].signal = osc->add_signal( signal_name, OSC::Signal::Output, 0, 1, 0, signal_handler, &sig_map[midi_event] );
|
||||
|
||||
sig_map_ordered[max_signal] = midi_event;
|
||||
}
|
||||
|
||||
free(signal_name);
|
||||
|
@ -606,47 +718,79 @@ command_broadcast ( const char *path, lo_message msg, void *userdata )
|
|||
|
||||
}
|
||||
|
||||
enum nrpn_awaiting
|
||||
{
|
||||
CONTROL_MSB,
|
||||
CONTROL_LSB,
|
||||
VALUE_MSB,
|
||||
VALUE_LSB,
|
||||
COMPLETE
|
||||
};
|
||||
|
||||
struct nrpn_state
|
||||
{
|
||||
char control_msb;
|
||||
char control_lsb;
|
||||
char value_msb;
|
||||
char value_lsb;
|
||||
bool decending;
|
||||
byte_t control_msb;
|
||||
byte_t control_lsb;
|
||||
byte_t value_msb;
|
||||
byte_t value_lsb;
|
||||
bool value_lsb_exists;
|
||||
bool complete;
|
||||
|
||||
nrpn_awaiting awaiting;
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
struct nrpn_state *
|
||||
decode_nrpn ( nrpn_state *state, midievent e, int *take_action )
|
||||
decode_nrpn ( nrpn_state *state, midievent e, bool *emit_one )
|
||||
{
|
||||
/* use a bit of state machine to allow people to misuse value LSB and value MSB CCs as regular CCs */
|
||||
|
||||
nrpn_state *n = &state[e.channel()];
|
||||
|
||||
*take_action = 0;
|
||||
*emit_one = false;
|
||||
|
||||
switch ( e.lsb() )
|
||||
{
|
||||
case 6:
|
||||
if ( e.msb() < n->value_msb )
|
||||
n->value_lsb = 127;
|
||||
else if ( e.msb() > n->value_msb )
|
||||
n->value_lsb = 0;
|
||||
|
||||
n->value_msb = e.msb();
|
||||
*take_action = 1;
|
||||
return n;
|
||||
if ( VALUE_MSB == n->awaiting )
|
||||
{
|
||||
n->value_msb = e.msb();
|
||||
n->value_lsb = 0 == e.msb() ? 0 : MAX_7BIT;
|
||||
|
||||
n->complete = true;
|
||||
n->awaiting = VALUE_LSB;
|
||||
*emit_one = true;
|
||||
return n;
|
||||
}
|
||||
break;
|
||||
case 38:
|
||||
n->value_lsb = e.msb();
|
||||
*take_action = 1;
|
||||
return n;
|
||||
if ( VALUE_LSB == n->awaiting )
|
||||
{
|
||||
n->value_lsb_exists = true;
|
||||
n->value_lsb = e.msb();
|
||||
*emit_one = true;
|
||||
n->complete = true;
|
||||
n->awaiting = COMPLETE;
|
||||
return n;
|
||||
}
|
||||
break;
|
||||
case 99:
|
||||
n->control_msb = e.msb();
|
||||
n->control_lsb = 0;
|
||||
return n;
|
||||
case 98:
|
||||
n->control_lsb = e.msb();
|
||||
return n;
|
||||
n->complete = false;
|
||||
n->value_lsb_exists = false;
|
||||
n->control_msb = e.msb();
|
||||
n->control_lsb = 0;
|
||||
n->awaiting = CONTROL_LSB;
|
||||
n->value_msb = 0;
|
||||
n->value_lsb = 0;
|
||||
return n;
|
||||
case 98:
|
||||
n->awaiting = VALUE_MSB;
|
||||
n->complete = false;
|
||||
n->control_lsb = e.msb();
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -659,11 +803,209 @@ sigterm_handler ( int )
|
|||
got_sigterm = 1;
|
||||
}
|
||||
|
||||
void emit_signal_for_event ( const char *midi_event, midievent &e, struct nrpn_state *st )
|
||||
{
|
||||
bool is_nrpn = st != NULL;
|
||||
|
||||
if ( sig_map.find( midi_event ) == sig_map.end() )
|
||||
{
|
||||
|
||||
/* first time seeing this control. */
|
||||
|
||||
signal_mapping m;
|
||||
|
||||
m.event.lsb( e.lsb() );
|
||||
m.event.msb( e.msb() );
|
||||
|
||||
m.event.opcode( e.opcode() );
|
||||
m.event.channel( e.channel() );
|
||||
|
||||
m.is_nrpn = is_nrpn;
|
||||
|
||||
if ( is_nrpn )
|
||||
{
|
||||
m.event.lsb( st->control_lsb );
|
||||
m.event.msb( st->control_msb );
|
||||
|
||||
if ( st->value_lsb_exists )
|
||||
m.learning_value_lsb = st->value_lsb;
|
||||
|
||||
m.learning_value_msb = st->value_msb;
|
||||
}
|
||||
else
|
||||
m.learning_value_msb = e.msb();
|
||||
|
||||
/* wait until we see it again to remember it */
|
||||
DMESSAGE("First time seeing control %s, will map on next event instance.", midi_event );
|
||||
|
||||
sig_map[midi_event] = m;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we got this far, it means we are on the second event for a the event type being learned */
|
||||
signal_mapping *m = &sig_map[midi_event];
|
||||
|
||||
if ( m->is_learning() )
|
||||
{
|
||||
/* FIXME: need to gather NRPN LSB value that (maybe) arrives between first and second event for this NRPN controller.
|
||||
14-bit flag is set if there was an LSB, otherwise, 7 or 1 bit mode is applied.
|
||||
|
||||
In normal operation, 14-bit NRPN controls should await the LSB before sending signal, 7 and 1 bit can send on MSB.
|
||||
*/
|
||||
|
||||
DMESSAGE( "Going to learn event %s now", midi_event );
|
||||
|
||||
char *s;
|
||||
|
||||
asprintf( &s, "/control/%i", ++max_signal );
|
||||
|
||||
DMESSAGE( "Creating signal %s for event %s.", s, midi_event );
|
||||
|
||||
bool is_toggle = false;
|
||||
bool is_14bit_nrpn = false;
|
||||
|
||||
if ( !is_nrpn )
|
||||
{
|
||||
DMESSAGE( "Learning value msb: %u, msb: %u", m->learning_value_msb, e.msb() );
|
||||
|
||||
is_toggle = ( m->learning_value_msb == 0 && e.msb() == MAX_7BIT ) ||
|
||||
( m->learning_value_msb == MAX_7BIT && e.msb() == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
is_14bit_nrpn = m->learning_value_lsb != -1;
|
||||
|
||||
unsigned int val1 = get_14bit( m->learning_value_msb, m->learning_value_lsb );
|
||||
unsigned int val2 = get_14bit( st->value_msb, st->value_lsb );
|
||||
|
||||
is_toggle = !is_14bit_nrpn
|
||||
? ( m->learning_value_msb == 0 && st->value_msb == MAX_7BIT ) ||
|
||||
( m->learning_value_msb == MAX_7BIT && st->value_msb == 0 )
|
||||
: ( val1 == 0 && val2 == MAX_14BIT ) ||
|
||||
( val1 == MAX_14BIT && val2 == 0);
|
||||
}
|
||||
|
||||
DMESSAGE( "is toggle %i", is_toggle );
|
||||
|
||||
m->is_toggle = is_toggle;
|
||||
m->is_nrpn14 = is_14bit_nrpn;
|
||||
|
||||
m->learning_value_msb = m->learning_value_lsb = 0;
|
||||
|
||||
m->signal_name = s;
|
||||
m->signal =
|
||||
osc->add_signal( s, OSC::Signal::Output, 0, 1, 0,
|
||||
signal_handler,
|
||||
m );
|
||||
|
||||
sig_map_ordered[max_signal] = midi_event;
|
||||
|
||||
nsm_send_is_dirty( nsm );
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
float val = 0;
|
||||
|
||||
if ( is_nrpn )
|
||||
{
|
||||
unsigned int fbv = get_14bit( st->value_msb, st->value_lsb );
|
||||
|
||||
if ( m->is_nrpn14 )
|
||||
val = fbv / (float)MAX_14BIT;
|
||||
else /* also covers toggles */
|
||||
val = st->value_msb / (float)MAX_7BIT;
|
||||
}
|
||||
else if ( e.opcode() == MIDI::midievent::CONTROL_CHANGE )
|
||||
val = e.msb() / (float)MAX_7BIT;
|
||||
else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL )
|
||||
val = e.pitch() / (float)MAX_14BIT;
|
||||
|
||||
/* DMESSAGE( "Val: %f, sigval %f", val, m->signal->value() ); */
|
||||
|
||||
/* wait for values to sync for continuous controls (faders and knobs) before emitting signal. For toggles, just send it immediately. */
|
||||
if (
|
||||
/* magic number to give a release time to prevent thrashing. */
|
||||
m->last_feedback_tick > m->last_midi_tick + 100
|
||||
&&
|
||||
!m->is_toggle )
|
||||
{
|
||||
float percent_off = fabs( val - m->signal->value() ) * 100.0f;
|
||||
|
||||
if ( percent_off > 5 )
|
||||
{
|
||||
DMESSAGE( "Wating for controls to sync. %s: %f percent off target (must be < 5%) [ M:%f S:%f ] ",
|
||||
m->signal_name.c_str(),
|
||||
percent_off,
|
||||
val,
|
||||
m->signal->value()
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m->last_midi_tick = buffers;
|
||||
|
||||
/* DMESSAGE( "Sent value: %f", val ); */
|
||||
|
||||
m->signal->value( val );
|
||||
}
|
||||
|
||||
void handle_control_change ( nrpn_state *nrpn_state, midievent &e )
|
||||
{
|
||||
bool emit_one = false;
|
||||
|
||||
char midi_event[51];
|
||||
|
||||
struct nrpn_state *st = decode_nrpn( nrpn_state, e, &emit_one );
|
||||
|
||||
if ( st != NULL &&
|
||||
( VALUE_LSB == st->awaiting ||
|
||||
COMPLETE == st->awaiting ) )
|
||||
{
|
||||
|
||||
snprintf( midi_event, 50, "NRPN %d %d", e.channel(), get_14bit( st->control_msb, st->control_lsb ));
|
||||
|
||||
if ( VALUE_LSB == st->awaiting )
|
||||
{
|
||||
if ( sig_map.find(midi_event) != sig_map.end() )
|
||||
{
|
||||
signal_mapping &m = sig_map[midi_event];
|
||||
|
||||
if ( m.is_nrpn14 )
|
||||
{
|
||||
/* we know there's an LSB coming, so hold off on emitting until we get it */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit_signal_for_event(midi_event, e, st);
|
||||
}
|
||||
|
||||
if ( st == NULL )
|
||||
{
|
||||
if ( e.opcode() == MIDI::midievent::CONTROL_CHANGE )
|
||||
{
|
||||
snprintf( midi_event, 50, "CC %d %d", e.channel(), e.lsb() );
|
||||
|
||||
emit_signal_for_event( midi_event, e, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL ) */
|
||||
/* asprintf( &s, "/midi/%i/PB", e.channel() ); */
|
||||
|
||||
|
||||
int
|
||||
main ( int argc, char **argv )
|
||||
{
|
||||
nrpn_state nrpn_state[16];
|
||||
|
||||
memset( &nrpn_state, 0, sizeof(struct nrpn_state) * 16 );
|
||||
|
||||
signal( SIGTERM, sigterm_handler );
|
||||
signal( SIGHUP, sigterm_handler );
|
||||
signal( SIGINT, sigterm_handler );
|
||||
|
@ -700,10 +1042,8 @@ main ( int argc, char **argv )
|
|||
|
||||
DMESSAGE( "waiting for events" );
|
||||
|
||||
static int max_signal = 1;
|
||||
|
||||
jack_midi_event_t ev;
|
||||
midievent e;
|
||||
/* jack_midi_event_t ev; */
|
||||
|
||||
while ( ! got_sigterm )
|
||||
{
|
||||
osc->wait(20);
|
||||
|
@ -712,92 +1052,28 @@ main ( int argc, char **argv )
|
|||
if ( ! engine )
|
||||
continue;
|
||||
|
||||
while ( jack_ringbuffer_read( engine->input_ring_buf, (char *)&ev, sizeof( jack_midi_event_t ) ) )
|
||||
{
|
||||
e.timestamp( ev.time );
|
||||
e.status( ev.buffer[0] );
|
||||
e.lsb( ev.buffer[1] );
|
||||
if ( ev.size == 3 )
|
||||
e.msb( ev.buffer[2] );
|
||||
midievent e;
|
||||
|
||||
while ( jack_ringbuffer_read( engine->input_ring_buf, (char *)&e, sizeof( midievent ) ) )
|
||||
{
|
||||
/* midievent e; */
|
||||
|
||||
/* e.timestamp( ev.time ); */
|
||||
/* e.status( ev.buffer[0] ); */
|
||||
/* e.lsb( ev.buffer[1] ); */
|
||||
/* if ( ev.size == 3 ) */
|
||||
/* e.msb( ev.buffer[2] ); */
|
||||
/* else */
|
||||
/* e.msb( 0 ); */
|
||||
|
||||
/* DMESSAGE( "[%lu] %u %u %u", e.timestamp(), e.status(), e.lsb(), e.msb() ); */
|
||||
|
||||
switch ( e.opcode() )
|
||||
{
|
||||
case MIDI::midievent::CONTROL_CHANGE:
|
||||
case MIDI::midievent::PITCH_WHEEL:
|
||||
{
|
||||
int is_nrpn = 0;
|
||||
|
||||
struct nrpn_state *st = decode_nrpn( nrpn_state, e, &is_nrpn );
|
||||
|
||||
if ( st != NULL && !is_nrpn )
|
||||
continue;
|
||||
|
||||
char *midi_event;
|
||||
|
||||
if ( is_nrpn )
|
||||
{
|
||||
asprintf( &midi_event, "NRPN %d %d", e.channel(), get_14bit( st->control_msb, st->control_lsb ));
|
||||
}
|
||||
else if ( e.opcode() == MIDI::midievent::CONTROL_CHANGE )
|
||||
asprintf( &midi_event, "CC %d %d", e.channel(), e.lsb() );
|
||||
/* else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL ) */
|
||||
/* asprintf( &s, "/midi/%i/PB", e.channel() ); */
|
||||
else
|
||||
break;
|
||||
|
||||
if ( sig_map.find( midi_event ) == sig_map.end() )
|
||||
{
|
||||
char *s;
|
||||
|
||||
asprintf( &s, "/control/%i", max_signal++ );
|
||||
|
||||
signal_mapping m;
|
||||
|
||||
m.event.opcode( e.opcode() );
|
||||
m.event.channel( e.channel() );
|
||||
|
||||
m.event.lsb( e.lsb() );
|
||||
m.event.msb( e.msb() );
|
||||
|
||||
m.is_nrpn = is_nrpn;
|
||||
|
||||
if ( is_nrpn )
|
||||
{
|
||||
m.event.lsb( st->control_lsb );
|
||||
m.event.msb( st->control_msb );
|
||||
}
|
||||
|
||||
/* if ( is_nrpn ) */
|
||||
/* m.nrpn = nrpnc_msb * 127 + nrpnc_lsb; */
|
||||
|
||||
MESSAGE( "creating signal %s", s );
|
||||
sig_map[midi_event] = m;
|
||||
sig_map[midi_event].signal_name = s;
|
||||
sig_map[midi_event].signal = osc->add_signal( s, OSC::Signal::Output, 0, 1, 0, signal_handler, &sig_map[midi_event] );
|
||||
|
||||
nsm_send_is_dirty( nsm );
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
float val = 0;
|
||||
|
||||
if ( is_nrpn )
|
||||
{
|
||||
val = get_14bit( st->value_msb, st->value_lsb ) / MAX_NRPN;
|
||||
|
||||
}
|
||||
else if ( e.opcode() == MIDI::midievent::CONTROL_CHANGE )
|
||||
val = e.msb() / 127.0f;
|
||||
else if ( e.opcode() == MIDI::midievent::PITCH_WHEEL )
|
||||
val = e.pitch() / MAX_NRPN;
|
||||
|
||||
// MESSAGE( "sending signal for %s = %f", s, val );
|
||||
|
||||
sig_map[midi_event].signal->value( val );
|
||||
|
||||
free( midi_event );
|
||||
|
||||
handle_control_change(nrpn_state,e);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -806,7 +1082,6 @@ main ( int argc, char **argv )
|
|||
// e.pretty_print();
|
||||
}
|
||||
|
||||
|
||||
// usleep( 500 );
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import string
|
|||
import os
|
||||
|
||||
# Version of this package (even if built as a child)
|
||||
PACKAGE_VERSION = '1.2.0'
|
||||
PACKAGE_VERSION = '1.3.0'
|
||||
|
||||
# Variables for 'waf dist'
|
||||
APPNAME = 'non-mixer'
|
||||
|
|
|
@ -94,7 +94,6 @@ unescape ( char *s )
|
|||
char *
|
||||
Log_Entry::print ( void ) const
|
||||
{
|
||||
/* FIXME: gross over-allocation */
|
||||
char *r = (char*)malloc( 1024 );
|
||||
|
||||
r[0] = 0;
|
||||
|
@ -105,20 +104,17 @@ Log_Entry::print ( void ) const
|
|||
|
||||
get( i, &s, &v );
|
||||
|
||||
/* FIXME: arbitrary limit */
|
||||
char t[1024];
|
||||
snprintf( t, sizeof( t ), "%s %s%s", s, v, size() == i + 1 ? "" : " " );
|
||||
char *t;
|
||||
asprintf( &t, "%s %s%s", s, v, size() == i + 1 ? "" : " " );
|
||||
|
||||
r = (char*)realloc( r, strlen(r) + strlen(t) + 1 );
|
||||
|
||||
strcat( r, t );
|
||||
|
||||
free(t);
|
||||
}
|
||||
|
||||
char *r2 = (char*)malloc( strlen( r ) + 1 );
|
||||
|
||||
strcpy( r2, r );
|
||||
|
||||
free( r );
|
||||
|
||||
return r2;
|
||||
return r;
|
||||
}
|
||||
|
||||
/** sigh. parse a string of ":name value :name value" pairs into an
|
||||
|
|
|
@ -346,10 +346,18 @@ Loggable::update_id ( unsigned int id )
|
|||
const char *
|
||||
Loggable::escape ( const char *s )
|
||||
{
|
||||
static char r[512];
|
||||
static size_t rl = 256;
|
||||
static char *r = new char[rl + 1];
|
||||
|
||||
if ( strlen(s) * 2 > rl )
|
||||
{
|
||||
delete []r;
|
||||
rl = strlen(s) * 2;
|
||||
r = new char[ rl + 1 ];
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for ( ; *s && i < sizeof( r ); ++i, ++s )
|
||||
for ( ; *s && i < rl; ++i, ++s )
|
||||
{
|
||||
if ( '\n' == *s )
|
||||
{
|
||||
|
@ -590,20 +598,30 @@ Loggable::snapshot ( const char *name )
|
|||
{
|
||||
FILE *fp;
|
||||
|
||||
char *tmpname;
|
||||
char *tmp = NULL;
|
||||
|
||||
{
|
||||
const char *filename = basename(name);
|
||||
char *dir = (char*)malloc( (strlen(name) - strlen(filename)) + 1 );
|
||||
strncpy( dir, name, strlen(name) - strlen(filename) );
|
||||
|
||||
asprintf( &tmp, "%s#%s", dir, filename );
|
||||
free(dir);
|
||||
}
|
||||
|
||||
asprintf( &tmpname, ".#%s", name );
|
||||
|
||||
if ( ! ( fp = fopen( tmpname, "w" ) ))
|
||||
if ( ! ( fp = fopen( tmp, "w" ) ))
|
||||
{
|
||||
DWARNING( "Could not open file for writing: %s", tmp );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool r = snapshot( fp );
|
||||
|
||||
fclose( fp );
|
||||
|
||||
rename( tmpname, name );
|
||||
rename( tmp, name );
|
||||
|
||||
free(tmpname);
|
||||
free(tmp);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -87,19 +87,19 @@ namespace MIDI
|
|||
memcpy( p, &_data, l );
|
||||
}
|
||||
|
||||
int
|
||||
byte_t
|
||||
midievent::size ( void ) const
|
||||
{
|
||||
return midievent::event_size( opcode() );
|
||||
}
|
||||
|
||||
void
|
||||
midievent::note_velocity ( int vel )
|
||||
midievent::note_velocity ( byte_t vel )
|
||||
{
|
||||
_data.msb = vel & 0x7F;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
byte_t
|
||||
midievent::note ( void ) const
|
||||
{
|
||||
return _data.lsb;
|
||||
|
@ -111,7 +111,7 @@ namespace MIDI
|
|||
_data.lsb = note & 0x7F;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
byte_t
|
||||
midievent::note_velocity ( void ) const
|
||||
{
|
||||
return _data.msb;
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace MIDI
|
|||
|
||||
public:
|
||||
|
||||
static inline int
|
||||
static inline byte_t
|
||||
event_size ( byte_t op )
|
||||
{
|
||||
switch ( op )
|
||||
|
@ -104,15 +104,15 @@ namespace MIDI
|
|||
void opcode ( byte_t o );
|
||||
void lsb ( byte_t n );
|
||||
void msb ( byte_t n );
|
||||
int lsb ( void ) const;
|
||||
int msb ( void ) const;
|
||||
byte_t lsb ( void ) const;
|
||||
byte_t msb ( void ) const;
|
||||
int pitch ( void ) const;
|
||||
void pitch ( int n );
|
||||
void data ( byte_t D1, byte_t D2 );
|
||||
void data ( byte_t *D1, byte_t *D2 ) const;
|
||||
void raw ( byte_t *p, int l) const;
|
||||
int size ( void ) const;
|
||||
void note_velocity ( int vel );
|
||||
byte_t size ( void ) const;
|
||||
void note_velocity ( byte_t vel );
|
||||
bool is_note_on ( void ) const;
|
||||
bool is_note_off ( void ) const;
|
||||
virtual unsigned char note ( void ) const;
|
||||
|
@ -198,13 +198,13 @@ namespace MIDI
|
|||
_data.msb = n & 0x7F;
|
||||
}
|
||||
|
||||
inline int
|
||||
inline byte_t
|
||||
midievent::lsb ( void ) const
|
||||
{
|
||||
return _data.lsb;
|
||||
}
|
||||
|
||||
inline int
|
||||
inline byte_t
|
||||
midievent::msb ( void ) const
|
||||
{
|
||||
return _data.msb;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "Endpoint.H"
|
||||
|
||||
|
@ -30,6 +32,8 @@
|
|||
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
static int SCAN_BATCH_SIZE = 100;
|
||||
|
||||
namespace OSC
|
||||
{
|
||||
|
||||
|
@ -187,6 +191,7 @@ namespace OSC
|
|||
Endpoint::Endpoint ( )
|
||||
{
|
||||
_learning_path = NULL;
|
||||
_learning_callback = NULL;
|
||||
_peer_signal_notification_callback = 0;
|
||||
_peer_signal_notification_userdata = 0;
|
||||
_peer_scan_complete_callback = 0;
|
||||
|
@ -685,8 +690,13 @@ namespace OSC
|
|||
DMESSAGE( "Learned translation \"%s\" -> \"%s\"", path, ep->_learning_path );
|
||||
|
||||
free(ep->_learning_path);
|
||||
|
||||
ep->_learning_callback(ep->_learning_userdata);
|
||||
|
||||
ep->_learning_userdata = NULL;
|
||||
ep->_learning_callback = NULL;
|
||||
ep->_learning_path = NULL;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -705,7 +715,9 @@ namespace OSC
|
|||
i->second.current_value = argv[0]->f;
|
||||
}
|
||||
|
||||
i->second.suppress_feedback = true;
|
||||
/* FIXME: this was intended to break feedback cycles, but it actually
|
||||
results in some feedback values not being sent at all */
|
||||
/* i->second.suppress_feedback = true; */
|
||||
|
||||
lo_send_message(ep->_addr, dpath, msg );
|
||||
return 0;
|
||||
|
@ -738,34 +750,122 @@ namespace OSC
|
|||
{
|
||||
// OSC_DMSG();
|
||||
|
||||
DMESSAGE( "Listing signals." );
|
||||
|
||||
const char *prefix = NULL;
|
||||
int skip = 0;
|
||||
bool batch_mode = true;
|
||||
int start;
|
||||
|
||||
if ( argc )
|
||||
const int count = SCAN_BATCH_SIZE;
|
||||
|
||||
if ( 's' == types[0] )
|
||||
{
|
||||
prefix = &argv[0]->s;
|
||||
DMESSAGE( "Listing signals for prefix \"%s\"", prefix );
|
||||
skip++;
|
||||
batch_mode = 2 == argc;
|
||||
}
|
||||
else
|
||||
{
|
||||
DMESSAGE( "Listing all signals." );
|
||||
}
|
||||
|
||||
if ( 0 == argc || 's' == types[0] )
|
||||
{
|
||||
/* obsolete unbatched mode left for backwards compatibility... */
|
||||
WARNING("Peer asked for unbatched signal list... will incur delays!");
|
||||
batch_mode = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we have to list these in batches, otherwise they the UDP packets overrun and get dropped... Probably
|
||||
wouldn't be an issue with TCP transport. */
|
||||
batch_mode = true;
|
||||
start = argv[0+skip]->i;
|
||||
/* count = argv[1+skip]->i; */
|
||||
}
|
||||
|
||||
Endpoint *ep = (Endpoint*)user_data;
|
||||
|
||||
|
||||
int sent = 0;
|
||||
|
||||
int s = 0;
|
||||
bool more = false;
|
||||
|
||||
lo_bundle b;
|
||||
if ( batch_mode )
|
||||
{
|
||||
b = lo_bundle_new(LO_TT_IMMEDIATE);
|
||||
}
|
||||
|
||||
for ( std::list<Signal*>::const_iterator i = ep->_signals.begin(); i != ep->_signals.end(); ++i )
|
||||
{
|
||||
Signal *o = *i;
|
||||
|
||||
if ( ! prefix || ! strncmp( o->path(), prefix, strlen(prefix) ) )
|
||||
{
|
||||
ep->send( lo_message_get_source( msg ),
|
||||
"/reply",
|
||||
path,
|
||||
o->path(),
|
||||
o->_direction == Signal::Input ? "in" : "out",
|
||||
o->parameter_limits().min,
|
||||
o->parameter_limits().max,
|
||||
o->parameter_limits().default_value
|
||||
if ( s++ < start )
|
||||
continue;
|
||||
|
||||
/* DMESSAGE( "Listing signal %s", o->path() ); */
|
||||
|
||||
if ( batch_mode )
|
||||
{
|
||||
lo_message m = lo_message_new();
|
||||
|
||||
lo_message_add_string( m, path );
|
||||
lo_message_add_string( m, o->path() );
|
||||
lo_message_add_string( m, o->_direction == Signal::Input ? "in" : "out" );
|
||||
lo_message_add_float( m, o->parameter_limits().min );
|
||||
lo_message_add_float( m, o->parameter_limits().max );
|
||||
lo_message_add_float( m, o->parameter_limits().default_value );
|
||||
|
||||
lo_bundle_add_message( b, "/reply", m );
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->send( lo_message_get_source( msg ),
|
||||
"/reply",
|
||||
path,
|
||||
o->path(),
|
||||
o->_direction == Signal::Input ? "in" : "out",
|
||||
o->parameter_limits().min,
|
||||
o->parameter_limits().max,
|
||||
o->parameter_limits().default_value
|
||||
);
|
||||
}
|
||||
|
||||
if ( batch_mode )
|
||||
{
|
||||
if ( ++sent == count )
|
||||
{
|
||||
more = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ep->send( lo_message_get_source( msg ), "/reply", path );
|
||||
|
||||
if ( batch_mode )
|
||||
{
|
||||
lo_message m = lo_message_new();
|
||||
|
||||
lo_message_add_string(m, path);
|
||||
lo_message_add_int32( m, sent );
|
||||
lo_message_add_int32( m, more );
|
||||
|
||||
lo_bundle_add_message( b, "/reply", m );
|
||||
|
||||
lo_send_bundle_from( lo_message_get_source( msg ), ep->_server, b );
|
||||
/* ep->send( lo_message_get_source( msg ), "/reply", path, sent, more ); */
|
||||
}
|
||||
else
|
||||
ep->send( lo_message_get_source( msg ), "/reply", path );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -900,13 +1000,38 @@ namespace OSC
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ( argc == 1 )
|
||||
if ( argc == 1 )
|
||||
{
|
||||
/* old handler for backwards compatibility */
|
||||
p->_scanning = false;
|
||||
DMESSAGE( "Done scanning %s", p->name );
|
||||
|
||||
if ( ep->_peer_scan_complete_callback )
|
||||
ep->_peer_scan_complete_callback(ep->_peer_scan_complete_userdata);
|
||||
}
|
||||
else
|
||||
if ( argc == 3 )
|
||||
{
|
||||
p->_scanning = false;
|
||||
DMESSAGE( "Done scanning %s", p->name );
|
||||
const int sent = argv[1]->i;
|
||||
const int more = argv[2]->i;
|
||||
|
||||
if ( !more )
|
||||
{
|
||||
p->_scanning = false;
|
||||
DMESSAGE( "Done scanning %s", p->name );
|
||||
|
||||
if ( ep->_peer_scan_complete_callback )
|
||||
ep->_peer_scan_complete_callback(ep->_peer_scan_complete_userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
DMESSAGE( "Scanning next batch %s", p->name );
|
||||
|
||||
if ( ep->_peer_scan_complete_callback )
|
||||
ep->_peer_scan_complete_callback(ep->_peer_scan_complete_userdata);
|
||||
p->_scanning_current += sent;
|
||||
|
||||
ep->send( p->addr, "/signal/list", p->_scanning_current );
|
||||
}
|
||||
|
||||
}
|
||||
else if ( argc == 6 && p->_scanning )
|
||||
{
|
||||
|
@ -915,7 +1040,7 @@ namespace OSC
|
|||
if ( s )
|
||||
return 0;
|
||||
|
||||
DMESSAGE( "Peer %s has signal %s (%s)", p->name, &argv[1]->s, &argv[2]->s );
|
||||
/* DMESSAGE( "Peer %s has signal %s (%s)", p->name, &argv[1]->s, &argv[2]->s ); */
|
||||
|
||||
int dir = 0;
|
||||
|
||||
|
@ -1066,29 +1191,32 @@ namespace OSC
|
|||
|
||||
/* prepare to learn a translation for /path/. The next unhandled message to come through will be mapped to /path/ */
|
||||
void
|
||||
Endpoint::learn ( const char *path )
|
||||
Endpoint::learn ( const char *path, void (*callback)(void*), void *userdata )
|
||||
{
|
||||
if ( _learning_path )
|
||||
free( _learning_path );
|
||||
|
||||
_learning_path = NULL;
|
||||
|
||||
_learning_callback = callback;
|
||||
_learning_userdata = userdata;
|
||||
|
||||
if ( path )
|
||||
_learning_path = strdup( path );
|
||||
}
|
||||
|
||||
/** if there's a translation with a destination of 'path', then send feedback for it */
|
||||
void
|
||||
Endpoint::send_feedback ( const char *path, float v )
|
||||
Endpoint::send_feedback ( const char *path, float v, bool force )
|
||||
{
|
||||
for ( std::map<std::string,TranslationDestination>::iterator i = _translations.begin();
|
||||
i != _translations.end();
|
||||
i++ )
|
||||
{
|
||||
if ( ! strcmp( i->second.path.c_str(), path ) )
|
||||
if ( path && ! strcmp( i->second.path.c_str(), path ) )
|
||||
{
|
||||
/* found it */
|
||||
if ( !i->second.suppress_feedback && i->second.current_value != v )
|
||||
if ( !i->second.suppress_feedback && ( force || fabsf(i->second.current_value - v ) > 0.001f ))
|
||||
{
|
||||
const char *spath = i->first.c_str();
|
||||
|
||||
|
@ -1134,10 +1262,11 @@ namespace OSC
|
|||
Peer *p = add_peer(name,url);
|
||||
|
||||
p->_scanning = true;
|
||||
|
||||
p->_scanning_current = 0;
|
||||
|
||||
DMESSAGE( "Scanning peer %s", name );
|
||||
|
||||
send( p->addr, "/signal/list" );
|
||||
send( p->addr, "/signal/list", p->_scanning_current );
|
||||
}
|
||||
|
||||
void *
|
||||
|
|
|
@ -120,6 +120,7 @@ namespace OSC
|
|||
struct Peer
|
||||
{
|
||||
bool _scanning;
|
||||
int _scanning_current;
|
||||
|
||||
char *name;
|
||||
lo_address addr;
|
||||
|
@ -241,6 +242,8 @@ namespace OSC
|
|||
std::list<Method*> _methods;
|
||||
|
||||
char *_learning_path;
|
||||
void (*_learning_callback)(void *);
|
||||
void *_learning_userdata;
|
||||
|
||||
class TranslationDestination {
|
||||
|
||||
|
@ -304,8 +307,8 @@ namespace OSC
|
|||
|
||||
public:
|
||||
|
||||
void send_feedback ( const char *path, float v );
|
||||
void learn ( const char *path );
|
||||
void send_feedback ( const char *path, float v, bool force );
|
||||
void learn ( const char *path, void (*callback)(void*), void *userdata );
|
||||
|
||||
lo_address address ( void )
|
||||
{
|
||||
|
|
57
nonlib/dsp.C
57
nonlib/dsp.C
|
@ -48,9 +48,9 @@ buffer_apply_gain ( sample_t * __restrict__ buf, nframes_t nframes, float g )
|
|||
|
||||
if ( g == 1.0f )
|
||||
return;
|
||||
|
||||
for ( nframes_t i = 0; i < nframes; i++ )
|
||||
buf_[i] *= g;
|
||||
|
||||
while ( nframes-- )
|
||||
*buf_++ *= g;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -58,9 +58,9 @@ buffer_apply_gain_unaligned ( sample_t * __restrict__ buf, nframes_t nframes, fl
|
|||
{
|
||||
if ( g == 1.0f )
|
||||
return;
|
||||
|
||||
for ( nframes_t i = 0; i < nframes; i++ )
|
||||
buf[i] *= g;
|
||||
|
||||
while ( nframes-- )
|
||||
*buf++ *= g;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -69,8 +69,8 @@ buffer_apply_gain_buffer ( sample_t * __restrict__ buf, const sample_t * __restr
|
|||
sample_t * buf_ = (sample_t*) assume_aligned(buf);
|
||||
const sample_t * gainbuf_ = (const sample_t*) assume_aligned(gainbuf);
|
||||
|
||||
for ( nframes_t i = 0; i < nframes; i++ )
|
||||
buf_[i] *= gainbuf_[i];
|
||||
while ( nframes-- )
|
||||
*buf_++ *= *gainbuf_++;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -79,9 +79,9 @@ buffer_copy_and_apply_gain_buffer ( sample_t * __restrict__ dst, const sample_t
|
|||
sample_t * dst_ = (sample_t*) assume_aligned(dst);
|
||||
const sample_t * src_ = (const sample_t*) assume_aligned(src);
|
||||
const sample_t * gainbuf_ = (const sample_t*) assume_aligned(gainbuf);
|
||||
|
||||
for ( nframes_t i = 0; i < nframes; i++ )
|
||||
dst_[i] = src_[i] * gainbuf_[i];
|
||||
|
||||
while ( nframes-- )
|
||||
*dst_++ = *src_++ * *gainbuf_++;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -90,8 +90,8 @@ buffer_mix ( sample_t * __restrict__ dst, const sample_t * __restrict__ src, nfr
|
|||
sample_t * dst_ = (sample_t*) assume_aligned(dst);
|
||||
const sample_t * src_ = (const sample_t*) assume_aligned(src);
|
||||
|
||||
for ( nframes_t i = 0; i < nframes; i++ )
|
||||
dst_[i] += src_[i];
|
||||
while ( nframes-- )
|
||||
*dst_++ += *src_++;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -100,8 +100,8 @@ buffer_mix_with_gain ( sample_t * __restrict__ dst, const sample_t * __restrict_
|
|||
sample_t * dst_ = (sample_t*) assume_aligned(dst);
|
||||
const sample_t * src_ = (const sample_t*) assume_aligned(src);
|
||||
|
||||
for ( nframes_t i = 0; i < nframes; i++ )
|
||||
dst_[i] += src_[i] * g;
|
||||
while ( nframes-- )
|
||||
*dst_++ = *src_++ * g;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -199,19 +199,17 @@ buffer_get_peak ( const sample_t * __restrict__ buf, nframes_t nframes )
|
|||
{
|
||||
const sample_t * buf_ = (const sample_t*) assume_aligned(buf);
|
||||
|
||||
float pmax = 0.0f;
|
||||
float pmin = 0.0f;
|
||||
|
||||
for ( nframes_t i = 0; i < nframes; i++ )
|
||||
float p = 0.0f;
|
||||
|
||||
while (nframes--)
|
||||
{
|
||||
pmax = buf_[i] > pmax ? buf_[i] : pmax;
|
||||
pmin = buf_[i] < pmin ? buf_[i] : pmin;
|
||||
const float v = fabsf( *buf_++ );
|
||||
|
||||
if ( v > p )
|
||||
p = v;
|
||||
}
|
||||
|
||||
pmax = fabsf(pmax);
|
||||
pmin = fabsf(pmin);
|
||||
|
||||
return pmax > pmin ? pmax : pmin;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -237,9 +235,13 @@ Value_Smoothing_Filter::sample_rate ( nframes_t n )
|
|||
w = _cutoff / (FS * T);
|
||||
}
|
||||
|
||||
/* FIXME: need a method that just returns a single value, skipping the within-buffer interpolation */
|
||||
bool
|
||||
Value_Smoothing_Filter::apply( sample_t * __restrict__ dst, nframes_t nframes, float gt )
|
||||
{
|
||||
if ( target_reached(gt) )
|
||||
return false;
|
||||
|
||||
sample_t * dst_ = (sample_t*) assume_aligned(dst);
|
||||
|
||||
const float a = 0.07f;
|
||||
|
@ -250,9 +252,6 @@ Value_Smoothing_Filter::apply( sample_t * __restrict__ dst, nframes_t nframes, f
|
|||
float g1 = this->g1;
|
||||
float g2 = this->g2;
|
||||
|
||||
if ( target_reached(gt) )
|
||||
return false;
|
||||
|
||||
for (nframes_t i = 0; i < nframes; i++)
|
||||
{
|
||||
g1 += w * (gm - g1 - a * g2);
|
||||
|
@ -260,6 +259,8 @@ Value_Smoothing_Filter::apply( sample_t * __restrict__ dst, nframes_t nframes, f
|
|||
dst_[i] = g2;
|
||||
}
|
||||
|
||||
g2 += 1e-10f; /* denormal protection */
|
||||
|
||||
if ( fabsf( gt - g2 ) < 0.0001f )
|
||||
g2 = gt;
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@ public:
|
|||
|
||||
void cutoff ( float v ) { _cutoff = v; }
|
||||
|
||||
void reset ( float v ) { g2 = g1 = v; }
|
||||
|
||||
void sample_rate ( nframes_t v );
|
||||
|
||||
inline bool target_reached ( float gt ) const { return gt == g2; }
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"Accoustic Bass Drum", 35, 100
|
||||
"Bass Drum 1", 36, 100
|
||||
"Side Stick", 37, 80
|
||||
"Acoustic Snare", 38, 100
|
||||
|
@ -20,6 +21,8 @@
|
|||
"Splash Cymbal", 55, 64
|
||||
"Cowbell", 56, 64
|
||||
"Crash Cymbal 2", 57, 64
|
||||
"Vibraslap", 58, 65
|
||||
"Ride Cymbal 2", 59, 80
|
||||
"Hi Bongo", 60, 100
|
||||
"Low Bongo", 61, 100
|
||||
"Mute Hi Conga", 62, 80
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[Desktop Entry]
|
||||
Name=Non Sequencer
|
||||
Comment=Realtime MIDI sequencer for JACK MIDI
|
||||
Comment[fr]=Séquenceur MIDI temps-réel pour JACK MIDI
|
||||
Exec=@BIN_PATH@/non-sequencer
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
|
|
@ -167,7 +167,8 @@ Canvas::Canvas ( int X, int Y, int W, int H, const char *L ) : Fl_Group( X,Y,W,H
|
|||
o->canvas = this;
|
||||
o->box( FL_FLAT_BOX );
|
||||
// o->color(fl_color_average( FL_BLACK, FL_WHITE, 0.90 ));
|
||||
o->color( FL_BLACK );
|
||||
/* o->color( FL_BLACK ); */
|
||||
o->color(fl_darker(FL_BACKGROUND_COLOR));
|
||||
// o->color(FL_BACKGROUND_COLOR);
|
||||
// o->type( FL_HORIZONTAL );
|
||||
o->callback( cb_scroll, this );
|
||||
|
@ -291,7 +292,7 @@ Canvas::_update_row_mapping ( void )
|
|||
else
|
||||
m.maxh = 128;
|
||||
|
||||
m.vp->h = min( m.vp->h, m.maxh );
|
||||
m.vp->h = max( m.vp->h, m.maxh );
|
||||
|
||||
resize_grid();
|
||||
}
|
||||
|
@ -488,10 +489,12 @@ gui_draw_string ( int x, int y, int w, int h, int color, const char *s, bool dra
|
|||
{
|
||||
// fl_rectf( x,y,w,h, FL_BACKGROUND_COLOR );
|
||||
|
||||
if ( color )
|
||||
fl_color( velocity_colors[ color ] );
|
||||
else
|
||||
fl_color( FL_DARK_CYAN );
|
||||
fl_color( FL_FOREGROUND_COLOR );
|
||||
|
||||
/* if ( color ) */
|
||||
/* fl_color( velocity_colors[ color ] ); */
|
||||
/* else */
|
||||
/* fl_color( FL_DARK_CYAN ); */
|
||||
|
||||
fl_draw( s, x, y + h / 2 + fl_descent() );
|
||||
}
|
||||
|
@ -519,13 +522,13 @@ Canvas::draw_row_name ( int y, const char *name, int color )
|
|||
|
||||
if ( draw && name )
|
||||
{
|
||||
fl_rectf( bx, by, bw, bh, index(name, '#') ? FL_GRAY : FL_BLACK );
|
||||
fl_rect( bx, by, bw, bh, FL_BLACK );
|
||||
fl_rectf( bx, by, bw, bh, index(name, '#') ? FL_GRAY : FL_BACKGROUND_COLOR );
|
||||
fl_rect( bx, by, bw, bh, FL_BACKGROUND_COLOR );
|
||||
}
|
||||
|
||||
m.margin_left = max( m.margin_left, gui_draw_string( bx + 1, by + 2,
|
||||
bw - 1, bh - 4,
|
||||
color,
|
||||
color,
|
||||
name,
|
||||
draw ) );
|
||||
}
|
||||
|
@ -617,14 +620,14 @@ Canvas::draw_dash ( tick_t x, int y, tick_t w, int color, int selected ) const
|
|||
|
||||
if ( w > 4 )
|
||||
{
|
||||
fl_draw_box( FL_ROUNDED_BOX, x, y + 1, w, m.div_h - 1, color );
|
||||
fl_draw_box( FL_UP_BOX, x, y + 1, w, m.div_h - 1, color );
|
||||
|
||||
if ( selected )
|
||||
{
|
||||
cairo_set_operator( Fl::cairo_cc(),CAIRO_OPERATOR_HSL_COLOR );
|
||||
|
||||
fl_draw_box( FL_ROUNDED_BOX, x, y + 1, w, m.div_h - 1, FL_MAGENTA );
|
||||
|
||||
fl_rectf( x, y + 1, w, m.div_h - 1, FL_MAGENTA );
|
||||
|
||||
cairo_set_operator( Fl::cairo_cc(),CAIRO_OPERATOR_OVER);
|
||||
}
|
||||
/* if ( selected ) */
|
||||
|
@ -767,7 +770,7 @@ Canvas::draw_clip ( int X, int Y, int W, int H )
|
|||
w() - m.margin_left,
|
||||
h() - m.margin_top - panzoomer->h() );
|
||||
|
||||
fl_rectf( m.origin_x + m.margin_left, m.origin_y + m.margin_top, w(), h(), FL_BLACK );
|
||||
fl_rectf( m.origin_x + m.margin_left, m.origin_y + m.margin_top, w(), h(), this->color() );
|
||||
|
||||
/* draw bar/beat lines */
|
||||
|
||||
|
@ -800,7 +803,7 @@ Canvas::draw_clip ( int X, int Y, int W, int H )
|
|||
ghost_note->velocity,
|
||||
1 );
|
||||
|
||||
fl_color( fl_color_add_alpha( fl_rgb_color( 127,127,127 ), 50 ));
|
||||
fl_color( fl_color_add_alpha( fl_rgb_color( 127,127,127 ), 25 ));
|
||||
|
||||
/* draw grid */
|
||||
|
||||
|
@ -1585,12 +1588,12 @@ Canvas::handle ( int m )
|
|||
|
||||
ghost_note->start = this->m.grid->x_to_ts( dx );
|
||||
ghost_note->note = dy;
|
||||
ghost_note->duration = this->m.grid->default_length();
|
||||
ghost_note->duration = this->m.grid->default_length() - 1;
|
||||
ghost_note->velocity = 64;
|
||||
|
||||
drag_note->start = this->m.grid->x_to_ts( dx );
|
||||
drag_note->note = dy;
|
||||
drag_note->duration = this->m.grid->default_length();
|
||||
drag_note->duration = this->m.grid->default_length() - 1;
|
||||
drag_note->velocity = 64;
|
||||
|
||||
|
||||
|
|
|
@ -38,4 +38,3 @@ const char COPYRIGHT[] = "Copyright (c) 2007-2013 Jonathan Moore Liles";
|
|||
/* directories */
|
||||
|
||||
#define USER_CONFIG_DIR ".non/"
|
||||
#define INSTRUMENT_DIR "instruments/"
|
||||
|
|
|
@ -314,6 +314,7 @@ name->value( e->selected() );
|
|||
// display the proper subtype
|
||||
switch ( e->opcode() )
|
||||
{
|
||||
|
||||
\#define TWO d1 = (Fl_Valuator*)tab->child( 0 ); d2 = (Fl_Valuator*)tab->child( 1 )
|
||||
\#define ONE d1 = (Fl_Valuator*)tab->child( 0 ); d2 = NULL
|
||||
|
||||
|
@ -354,11 +355,16 @@ switch ( e->opcode() )
|
|||
case midievent::PITCH_WHEEL:
|
||||
tab = pitch_tab;
|
||||
name->color( pitch_color );
|
||||
|
||||
|
||||
ONE;
|
||||
d1->value( e->pitch() );
|
||||
goto pitch;
|
||||
break;
|
||||
default:
|
||||
WARNING("Encountered unknown opcode");
|
||||
return;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -98,14 +98,21 @@ Function {init_colors()} {open private C return_type {static void}
|
|||
} {
|
||||
code {unsigned int i;
|
||||
/* velocity colors */
|
||||
|
||||
|
||||
|
||||
Fl_Color lo = fl_color_average( FL_CYAN, FL_BLACK, 0.10 );
|
||||
Fl_Color hi = fl_color_average( FL_CYAN, FL_WHITE, 0.80 );
|
||||
Fl_Color c[] = { FL_BLUE, FL_GREEN, FL_RED };
|
||||
int b[] = {0, 64, 127 };
|
||||
int nbreaks = 3;
|
||||
|
||||
for ( int i = 0; i < nbreaks - 1; i++ )
|
||||
{
|
||||
int k = 0;
|
||||
for ( int j = b[i]; j <= b[i+1]; j++, k++ )
|
||||
velocity_colors[ j ] = fl_color_average( c[i+1], c[i], ( k ) / (float)(b[i+1] - b[i] ));
|
||||
}
|
||||
|
||||
for ( i = 128; i--; )
|
||||
{
|
||||
velocity_colors[i] = fl_color_average( hi, lo, 1.0 * ((float)i / 128) );
|
||||
}} {}
|
||||
} {}
|
||||
}
|
||||
|
||||
widget_class Visual_Metronome {open
|
||||
|
@ -847,6 +854,12 @@ o->maximum( pattern::patterns() );}
|
|||
char picked[80];
|
||||
mapping_menu->item_pathname(picked, sizeof(picked)-1 );
|
||||
|
||||
const char *text = o->text();
|
||||
|
||||
if ( ! strcmp( text, picked ) )
|
||||
// nothing picked...
|
||||
return;
|
||||
|
||||
if ( 0 == strncmp( picked, "Instrument", strlen( "Instrument" ) ) )
|
||||
{
|
||||
((pattern*)pattern_canvas_widget->grid())->mapping.open( Mapping::INSTRUMENT, o->text() );
|
||||
|
|
|
@ -160,7 +160,7 @@ Instrument::read ( const char *s )
|
|||
if ( ! ( fp = fopen( pat, "r" ) ) )
|
||||
{
|
||||
|
||||
sprintf( pat, "%s/%s/%s.inst", SYSTEM_PATH, INSTRUMENT_DIR, s );
|
||||
sprintf( pat, "%s/%s.inst", INSTRUMENTS_PATH, s );
|
||||
|
||||
if ( ! ( fp = fopen( pat, "r" ) ) )
|
||||
return false;
|
||||
|
@ -261,7 +261,7 @@ get_listing( const char *dir )
|
|||
|
||||
if ( 0 > ( n = scandir( dir, &names, instrument_filter, alphasort ) ) )
|
||||
{
|
||||
WARNING( "couldn't open instrument directory" );
|
||||
WARNING( "couldn't open instrument directory: %s", dir );
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
|
@ -291,7 +291,7 @@ get_listing( const char *dir )
|
|||
char **
|
||||
Instrument::listing ( void )
|
||||
{
|
||||
list <string> *sys = get_listing( SYSTEM_PATH "/" INSTRUMENT_DIR );
|
||||
list <string> *sys = get_listing( INSTRUMENTS_PATH );
|
||||
list <string> *usr = get_listing( config.user_config_dir );
|
||||
|
||||
if ( ! ( usr || sys ) )
|
||||
|
|
|
@ -371,51 +371,69 @@ sequence::load ( const char *name )
|
|||
void
|
||||
sequence::save ( const char *name ) const
|
||||
{
|
||||
smf f;
|
||||
|
||||
char *tmp = NULL;
|
||||
|
||||
/* open for writing */
|
||||
f.open( name, smf::WRITE );
|
||||
|
||||
f.write_header( 2 );
|
||||
|
||||
DMESSAGE( "saving playlist" );
|
||||
|
||||
f.open_track( NULL, -1 );
|
||||
|
||||
DMESSAGE( "saving song info" );
|
||||
|
||||
f.write_song_info( song.play_mode, phrase::phrases(), pattern::patterns(), this->name(), notes() );
|
||||
|
||||
for ( int i = 0; i < _rd->num; ++i )
|
||||
{
|
||||
char pat[256];
|
||||
const char *filename = basename(name);
|
||||
char *dir = (char*)malloc( (strlen(name) - strlen(filename)) + 1 );
|
||||
strncpy( dir, name, strlen(name) - strlen(filename) );
|
||||
|
||||
asprintf( &tmp, "%s#%s", dir, filename );
|
||||
free(dir);
|
||||
}
|
||||
|
||||
{
|
||||
smf f;
|
||||
|
||||
phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] );
|
||||
/* open for writing */
|
||||
f.open( tmp, smf::WRITE );
|
||||
|
||||
snprintf( pat, 256, "%d: %s", p->number(), p->name() );
|
||||
f.write_header( 2 );
|
||||
|
||||
f.write_meta_event( smf::CUEPOINT, pat );
|
||||
DMESSAGE( "saving playlist" );
|
||||
|
||||
f.open_track( NULL, -1 );
|
||||
|
||||
DMESSAGE( "saving song info" );
|
||||
|
||||
f.write_song_info( song.play_mode, phrase::phrases(), pattern::patterns(), this->name(), notes() );
|
||||
|
||||
for ( int i = 0; i < _rd->num; ++i )
|
||||
{
|
||||
char pat[256];
|
||||
|
||||
phrase *p = phrase::phrase_by_number( _rd->phrases[ i ] );
|
||||
|
||||
snprintf( pat, 256, "%d: %s", p->number(), p->name() );
|
||||
|
||||
f.write_meta_event( smf::CUEPOINT, pat );
|
||||
}
|
||||
|
||||
f.close_track( 0 );
|
||||
|
||||
DMESSAGE( "saving phrases" );
|
||||
|
||||
for ( int i = 0; i < phrase::phrases(); i++ )
|
||||
{
|
||||
phrase *p = phrase::phrase_by_number( i + 1 );
|
||||
|
||||
p->dump( &f );
|
||||
}
|
||||
|
||||
DMESSAGE( "saving patterns" );
|
||||
|
||||
for ( int i = 0; i < pattern::patterns(); i++ )
|
||||
{
|
||||
pattern *p = pattern::pattern_by_number( i + 1 );
|
||||
|
||||
p->dump( &f );
|
||||
}
|
||||
}
|
||||
|
||||
f.close_track( 0 );
|
||||
rename(tmp,name);
|
||||
|
||||
DMESSAGE( "saving phrases" );
|
||||
|
||||
for ( int i = 0; i < phrase::phrases(); i++ )
|
||||
{
|
||||
phrase *p = phrase::phrase_by_number( i + 1 );
|
||||
|
||||
p->dump( &f );
|
||||
}
|
||||
|
||||
DMESSAGE( "saving patterns" );
|
||||
|
||||
for ( int i = 0; i < pattern::patterns(); i++ )
|
||||
{
|
||||
pattern *p = pattern::pattern_by_number( i + 1 );
|
||||
|
||||
p->dump( &f );
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "smf.H"
|
||||
#include "phrase.H"
|
||||
#include "pattern.H"
|
||||
#include <math.h>
|
||||
|
||||
using namespace MIDI;
|
||||
|
||||
|
@ -143,11 +144,11 @@ smf::read_byte ( void )
|
|||
}
|
||||
|
||||
void
|
||||
smf::write_var ( long var )
|
||||
smf::write_var ( unsigned long var )
|
||||
{
|
||||
long buffer;
|
||||
buffer = var & 0x7F;
|
||||
|
||||
unsigned long buffer = var & 0x7F;
|
||||
byte_t buf[4];
|
||||
|
||||
/* we shift it right 7, if there is
|
||||
still set bits, encode into buffer
|
||||
in reverse order */
|
||||
|
@ -157,15 +158,19 @@ smf::write_var ( long var )
|
|||
buffer |= ( var & 0x7F ) | 0x80;
|
||||
}
|
||||
|
||||
for ( ;; )
|
||||
int i = 0;
|
||||
|
||||
while ( i < 4 )
|
||||
{
|
||||
write_byte( buffer );
|
||||
|
||||
buf[i++] = buffer;
|
||||
|
||||
if ( buffer & 0x80 )
|
||||
buffer >>= 8;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
write_bytes( buf, i );
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,15 +187,6 @@ smf::write_long ( unsigned long x )
|
|||
write_bytes( buf, 4 );
|
||||
}
|
||||
|
||||
void
|
||||
smf::write_ascii ( const char *buf )
|
||||
{
|
||||
if ( strlen( buf ) != 4 )
|
||||
ASSERTION( "invalid MIDI value" );
|
||||
|
||||
write_bytes( (void *)buf, 4 );
|
||||
}
|
||||
|
||||
void
|
||||
smf::write_short ( unsigned short x )
|
||||
{
|
||||
|
@ -208,6 +204,15 @@ smf::write_byte ( byte_t b )
|
|||
write_bytes( &b, 1 );
|
||||
}
|
||||
|
||||
void
|
||||
smf::write_ascii ( const char *buf )
|
||||
{
|
||||
if ( strlen( buf ) != 4 )
|
||||
ASSERTION( "invalid MIDI value" );
|
||||
|
||||
write_bytes( (void *)buf, 4 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
smf::write_bytes ( const void *p, size_t l )
|
||||
|
@ -231,7 +236,7 @@ smf::write_event ( const midievent *e )
|
|||
tick_t delta = ts - _time;
|
||||
_time = ts;
|
||||
|
||||
write_var( delta );
|
||||
write_var( floor(delta) );
|
||||
|
||||
if ( _cue && (e->is_note_off() || e->is_note_on() ) )
|
||||
{
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
void read_bytes ( void *p, int l );
|
||||
byte_t read_byte ( void );
|
||||
|
||||
void write_var ( long var );
|
||||
void write_var ( unsigned long var );
|
||||
void write_long ( unsigned long x );
|
||||
void write_ascii ( const char *buf );
|
||||
void write_short ( unsigned short x );
|
||||
|
|
|
@ -5,7 +5,7 @@ import string
|
|||
import os
|
||||
|
||||
# Version of this package (even if built as a child)
|
||||
PACKAGE_VERSION = '1.9.5'
|
||||
PACKAGE_VERSION = '1.10.0'
|
||||
|
||||
# Variables for 'waf dist'
|
||||
APPNAME = 'non-sequencer'
|
||||
|
@ -32,6 +32,7 @@ def configure(conf):
|
|||
conf.define('SYSTEM_PATH', '/'.join( [ conf.env.DATADIR, APPNAME ] ) )
|
||||
conf.define('DOCUMENT_PATH', '/'.join( [ conf.env.DATADIR, 'doc' ] ) )
|
||||
conf.define('PIXMAP_PATH', '/'.join( [ conf.env.DATADIR, 'pixmaps' ] ) )
|
||||
conf.define('INSTRUMENTS_PATH', '/'.join( [ conf.env.DATADIR, APPNAME, 'instruments' ] ) )
|
||||
|
||||
conf.write_config_header('config.h', remove=False)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[Desktop Entry]
|
||||
Name=Non Session Manager
|
||||
Comment=Audio session manager from the land of Non
|
||||
Comment[fr]=Gestionnaire de session audio pour les terres de Non
|
||||
Exec=@BIN_PATH@/non-session-manager
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
|
|
@ -138,7 +138,10 @@ class NSM_Client : public Fl_Group
|
|||
|
||||
if ( img )
|
||||
{
|
||||
icon_box->image( img );
|
||||
if ( img->w() > 32 || img->h() > 32 )
|
||||
WARNING("Client %s has stupidly large icon (%ix%i), ignoring.", _client_name, img->w(), img->h() );
|
||||
else
|
||||
icon_box->image( img );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import string
|
|||
import os
|
||||
|
||||
# Version of this package (even if built as a child)
|
||||
PACKAGE_VERSION = '1.2.0'
|
||||
PACKAGE_VERSION = '1.3.0'
|
||||
|
||||
# Variables for 'waf dist'
|
||||
APPNAME = 'non-session-manager'
|
||||
|
|
|
@ -74,7 +74,7 @@ PROJECT="$1"
|
|||
|
||||
cd "$PROJECT" || fatal "No such project"
|
||||
|
||||
[ -f history ] && [ -f info ] || fatal "Not a Non-DAW project?"
|
||||
[ -f history ] && [ -f info ] || fatal "Not a Non-Timeline project?"
|
||||
|
||||
[ -f .lock ] && fatal "Project appears to be in use"
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[Desktop Entry]
|
||||
Name=Non Timeline
|
||||
Comment=Modular Digital Audio Workstation - Timeline Editor
|
||||
Comment[fr]=Station de travail audio-numérique modulaire - Éditeur à ligne temporelle
|
||||
Exec=@BIN_PATH@/non-timeline
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
|
|
@ -224,6 +224,8 @@ Audio_Region::menu_cb ( const Fl_Menu_ *m )
|
|||
_fade_in.type = Fade::Logarithmic;
|
||||
else if ( ! strcmp( picked, "Fade/In/Parabolic" ) )
|
||||
_fade_in.type = Fade::Parabolic;
|
||||
else if ( ! strcmp( picked, "Fade/In/Disabled" ) )
|
||||
_fade_in.type = Fade::Disabled;
|
||||
else if ( ! strcmp( picked, "Fade/Out/Linear" ) )
|
||||
_fade_out.type = Fade::Linear;
|
||||
else if ( ! strcmp( picked, "Fade/Out/Sigmoid" ) )
|
||||
|
@ -232,6 +234,8 @@ Audio_Region::menu_cb ( const Fl_Menu_ *m )
|
|||
_fade_out.type = Fade::Logarithmic;
|
||||
else if ( ! strcmp( picked, "Fade/Out/Parabolic" ) )
|
||||
_fade_out.type = Fade::Parabolic;
|
||||
else if ( ! strcmp( picked, "Fade/Out/Disabled" ) )
|
||||
_fade_out.type = Fade::Disabled;
|
||||
else if ( ! strcmp( picked, "/Color" ) )
|
||||
box_color( fl_show_colormap( box_color() ) );
|
||||
else if ( ! strcmp( picked, "/Split at mouse" ) )
|
||||
|
@ -351,12 +355,16 @@ Audio_Region::menu ( void )
|
|||
{ "Sigmoid", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Sigmoid ? FL_MENU_VALUE : 0 ) },
|
||||
{ "Logarithmic", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Logarithmic ? FL_MENU_VALUE : 0 ) },
|
||||
{ "Parabolic", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Parabolic ? FL_MENU_VALUE : 0 ) },
|
||||
{ "Disabled", 0, 0, 0, FL_MENU_RADIO | ( it == Fade::Disabled ? FL_MENU_VALUE : 0 ) },
|
||||
|
||||
{ 0 },
|
||||
{ "Out", 0, 0, 0, FL_SUBMENU },
|
||||
{ "Linear", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Linear ? FL_MENU_VALUE : 0 ) },
|
||||
{ "Sigmoid", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Sigmoid ? FL_MENU_VALUE : 0 ) },
|
||||
{ "Logarithmic", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Logarithmic ? FL_MENU_VALUE : 0 ) },
|
||||
{ "Parabolic", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Parabolic ? FL_MENU_VALUE : 0 ) },
|
||||
{ "Disabled", 0, 0, 0, FL_MENU_RADIO | ( ot == Fade::Disabled ? FL_MENU_VALUE : 0 ) },
|
||||
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ "Color", 0, 0, 0, inherit_track_color ? FL_MENU_INACTIVE : 0 },
|
||||
|
@ -398,6 +406,9 @@ Audio_Region::draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool line, int
|
|||
const int height = dh;
|
||||
const int width = timeline->ts_to_x( fade.length );
|
||||
|
||||
if ( Fade::Disabled == fade.type )
|
||||
return;
|
||||
|
||||
if ( width < 4 )
|
||||
/* too small to draw */
|
||||
return;
|
||||
|
@ -409,7 +420,7 @@ Audio_Region::draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool line, int
|
|||
fx = curve_x();
|
||||
|
||||
if ( fx + width < X ||
|
||||
fx > X + W )
|
||||
fx > X + W )
|
||||
/* clipped */
|
||||
return;
|
||||
}
|
||||
|
@ -477,7 +488,7 @@ Audio_Region::draw_box( void )
|
|||
}
|
||||
|
||||
Fl_Boxtype b;
|
||||
Fl_Color c = selected() ? fl_color_average( color, fl_rgb_color(10,10,10), 0.4f ) : color;
|
||||
Fl_Color c = color;// selected() ? fl_color_average( color, fl_rgb_color(10,10,10), 0.4f ) : color;
|
||||
|
||||
if ( Audio_Region::show_box )
|
||||
{
|
||||
|
@ -566,7 +577,7 @@ Audio_Region::draw ( void )
|
|||
/* Audio_Region::inherit_track_color ? sequence()->track()->color() : _box_color, */
|
||||
/* 0.75f ); */
|
||||
|
||||
fl_color( fl_color_add_alpha( FL_DARK1, 127 ) );
|
||||
fl_color( fl_color_add_alpha( fl_rgb_color( 20,20,20 ), 127 ) );
|
||||
|
||||
draw_fade( _fade_in, Fade::In, false, X, W );
|
||||
draw_fade( _fade_out, Fade::Out, false, X, W );
|
||||
|
@ -665,21 +676,8 @@ Audio_Region::draw ( void )
|
|||
;
|
||||
// WARNING( "Pbuf == %p, peaks = %lu", pbuf, (unsigned long)peaks );
|
||||
|
||||
|
||||
|
||||
if ( _loop )
|
||||
{
|
||||
const int lx = sequence()->drawable_x() + timeline->ts_to_x( ( this->start() + _loop ) - timeline->xoffset );
|
||||
|
||||
if ( lx < X + W )
|
||||
{
|
||||
fl_color( fl_darker( FL_CYAN ) );
|
||||
fl_line( lx, y(), lx, y() + h() );
|
||||
fl_line( lx - 3, y(), lx + 3, y() );
|
||||
fl_line( lx - 3, y() + h() - 1, lx + 3, y() + h() - 1 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ( peaks < loop_peaks_needed )
|
||||
{
|
||||
|
@ -691,6 +689,31 @@ Audio_Region::draw ( void )
|
|||
}
|
||||
while ( _loop && fo < total_frames_needed );
|
||||
|
||||
if ( _loop )
|
||||
{
|
||||
/* draw loop point indicator */
|
||||
const int lx = sequence()->drawable_x() + timeline->ts_to_x( ( this->start() + _loop ) - timeline->xoffset );
|
||||
|
||||
const int pw = 8;
|
||||
|
||||
fl_color( fl_color_add_alpha( fl_color_average( FL_CYAN, FL_WHITE, 0.80f ), 127 ) );
|
||||
|
||||
fl_begin_polygon();
|
||||
|
||||
fl_vertex( lx + Fl::box_dx(box()),
|
||||
y() + Fl::box_dy(box()) );
|
||||
|
||||
fl_vertex( pw + lx + Fl::box_dx(box()),
|
||||
y() + Fl::box_dy(box()) );
|
||||
|
||||
fl_vertex( lx + Fl::box_dx(box()),
|
||||
pw + y() + Fl::box_dy(box()) );
|
||||
|
||||
fl_end_polygon();
|
||||
|
||||
|
||||
fl_line( lx, y() + Fl::box_dy(box()), lx, y() + h() - Fl::box_dy(box()) * 2 );
|
||||
}
|
||||
|
||||
|
||||
if ( _adjusting_gain > 0.0f )
|
||||
|
@ -713,6 +736,29 @@ Audio_Region::draw ( void )
|
|||
fl_line_style( FL_SOLID, 0 );
|
||||
}
|
||||
|
||||
|
||||
/* draw dog ear */
|
||||
{
|
||||
const int pw = 8;
|
||||
|
||||
/* fl_color( fl_color_add_alpha( FL_WHITE, 127 ) ); */
|
||||
/* fl_color( FL_BACKGROUND_COLOR ); */
|
||||
fl_color( fl_color_add_alpha( FL_WHITE, 127 ) );
|
||||
|
||||
fl_begin_polygon();
|
||||
|
||||
fl_vertex( line_x() + Fl::box_dx(box()),
|
||||
y() + Fl::box_dy(box()) );
|
||||
|
||||
fl_vertex( pw + line_x() + Fl::box_dx(box()),
|
||||
y() + Fl::box_dy(box()) );
|
||||
|
||||
fl_vertex( line_x() + Fl::box_dx(box()),
|
||||
pw + y() + Fl::box_dy(box()) );
|
||||
|
||||
fl_end_polygon();
|
||||
}
|
||||
|
||||
if ( selected() )
|
||||
draw_selection_frame( line_x() + Fl::box_dx(box()),
|
||||
y() + Fl::box_dy(box()),
|
||||
|
@ -738,7 +784,7 @@ Audio_Region::draw ( void )
|
|||
void
|
||||
Audio_Region::draw_label ( void )
|
||||
{
|
||||
if ( _clip->dummy() )
|
||||
if ( _clip->dummy() )
|
||||
{
|
||||
char pat[256];
|
||||
snprintf( pat, sizeof( pat ), "Missing Source!: %s", _clip->name() );
|
||||
|
@ -760,6 +806,8 @@ Audio_Region::split ( nframes_t where )
|
|||
|
||||
Audio_Region *copy = new Audio_Region( *this );
|
||||
|
||||
timeline->sequence_lock.wrlock();
|
||||
|
||||
{
|
||||
Logger _log( copy );
|
||||
|
||||
|
@ -769,6 +817,8 @@ Audio_Region::split ( nframes_t where )
|
|||
Sequence_Region::split( copy, where );
|
||||
}
|
||||
|
||||
timeline->sequence_lock.unlock();
|
||||
|
||||
log_end();
|
||||
|
||||
block_end();
|
||||
|
@ -784,6 +834,10 @@ Audio_Region::handle ( int m )
|
|||
static bool copied = false;
|
||||
static nframes_t os;
|
||||
|
||||
if ( !active_r() )
|
||||
/* don't mess with anything while recording... */
|
||||
return 0;
|
||||
|
||||
int X = Fl::event_x();
|
||||
int Y = Fl::event_y();
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
struct Fade
|
||||
{
|
||||
enum fade_type_e { Linear = 0, Sigmoid, Logarithmic, Parabolic };
|
||||
enum fade_type_e { Linear = 0, Sigmoid, Logarithmic, Parabolic, Disabled };
|
||||
enum fade_dir_e { In, Out };
|
||||
|
||||
fade_type_e type;
|
||||
|
|
|
@ -177,7 +177,8 @@ Audio_Sequence::set ( Log_Entry &e )
|
|||
|
||||
assert( t );
|
||||
|
||||
t->sequence( this );
|
||||
/* FIXME: this causes the sequences to be set twice in the replay logic, first when the sequence is created, then when track sequence is assigned. */
|
||||
t->sequence( this );
|
||||
}
|
||||
else if ( ! strcmp( ":name", s ) )
|
||||
name( v );
|
||||
|
|
|
@ -164,7 +164,7 @@ public:
|
|||
|
||||
fl_font( FL_COURIER_BOLD, 24 );
|
||||
|
||||
Fl_Color c = fl_color_average( FL_WHITE, FL_GRAY, 0.60 );
|
||||
Fl_Color c = fl_color_average( fl_contrast(FL_WHITE, FL_BACKGROUND_COLOR) , FL_GRAY, 0.60 );
|
||||
|
||||
fl_color( c );
|
||||
|
||||
|
|
|
@ -601,7 +601,7 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m )
|
|||
void
|
||||
Control_Sequence::connect_osc ( void )
|
||||
{
|
||||
timeline->osc_thread->lock();
|
||||
timeline->osc_receive_thread->lock();
|
||||
|
||||
if ( _persistent_osc_connections.size() )
|
||||
{
|
||||
|
@ -623,7 +623,7 @@ Control_Sequence::connect_osc ( void )
|
|||
|
||||
/* header()->outputs_indicator->value( _osc_output() && _osc_output()->connected() ); */
|
||||
|
||||
timeline->osc_thread->unlock();
|
||||
timeline->osc_receive_thread->unlock();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -634,12 +634,15 @@ Control_Sequence::process_osc ( void )
|
|||
|
||||
if ( _osc_output() )
|
||||
{
|
||||
sample_t buf[1];
|
||||
sample_t buf = 0;
|
||||
|
||||
play( &buf, (nframes_t)transport->frame, (nframes_t) 1 );
|
||||
|
||||
*buf = 0;
|
||||
|
||||
play( buf, (nframes_t)transport->frame, (nframes_t) 1 );
|
||||
_osc_output()->value( (float)buf[0] );
|
||||
/* only send value if it is significantly different from the last value sent */
|
||||
if ( fabsf( _osc_output()->value() - (float)buf ) > 0.001 )
|
||||
{
|
||||
_osc_output()->value( (float)buf );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,10 @@ Audio_File_SF::create ( const char *filename, nframes_t samplerate, int channels
|
|||
const Audio_File::format_desc *fd = Audio_File::find_format( Audio_File_SF::supported_formats, format );
|
||||
|
||||
if ( ! fd )
|
||||
{
|
||||
DMESSAGE( "Unsupported capture format: %s", format );
|
||||
return (Audio_File_SF *)1;
|
||||
}
|
||||
|
||||
si.samplerate = samplerate;
|
||||
si.channels = channels;
|
||||
|
@ -125,7 +128,7 @@ Audio_File_SF::create ( const char *filename, nframes_t samplerate, int channels
|
|||
|
||||
if ( ! ( out = sf_open( filepath, SFM_WRITE, &si ) ) )
|
||||
{
|
||||
printf( "couldn't create soundfile.\n" );
|
||||
WARNING( "couldn't create soundfile \"%s\": libsndfile says: %s", filepath, sf_strerror(NULL) );
|
||||
free( name );
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -118,10 +118,12 @@ Audio_Region::read ( sample_t *buf, bool buf_is_empty, nframes_t pos, nframes_t
|
|||
|
||||
const Range r = _range;
|
||||
|
||||
/* ASSERT( r.legnth > 0, "Region has zero length!" ); */
|
||||
|
||||
const nframes_t rS = r.start;
|
||||
const nframes_t rE = r.start + r.length;
|
||||
const nframes_t rE = r.start + r.length; /* one more than the last frame of the region! */
|
||||
const nframes_t bS = pos;
|
||||
const nframes_t bE = pos + nframes;
|
||||
const nframes_t bE = pos + nframes; /* one more than the last frame of the buffer! */
|
||||
|
||||
/* do nothing if region isn't inside buffer */
|
||||
if ( bS > rE || bE < rS )
|
||||
|
@ -188,20 +190,42 @@ Audio_Region::read ( sample_t *buf, bool buf_is_empty, nframes_t pos, nframes_t
|
|||
WARNING("Loop size (%lu) is smaller than buffer size (%lu). Behavior undefined.", _loop, nframes );
|
||||
}
|
||||
|
||||
const nframes_t lO = sO % _loop; /* how far we are into the loop */
|
||||
const nframes_t nthloop = sO / _loop; /* which loop iteration */
|
||||
const nframes_t seam_L = rS + ( nthloop * _loop ); /* receding seam */
|
||||
const nframes_t seam_R = rS + ( (nthloop + 1 ) * _loop ); /* upcoming seam */
|
||||
|
||||
/* read interleaved channels */
|
||||
if ( seam_R > bS && seam_R < bE )
|
||||
{
|
||||
/* this buffer covers a loop boundary */
|
||||
const nframes_t lO = sO % _loop, /* how far we are into the loop */
|
||||
nthloop = sO / _loop, /* which loop iteration */
|
||||
seam_L = rS + ( nthloop * _loop ), /* receding seam */
|
||||
seam_R = rS + ( ( nthloop + 1 ) * _loop ); /* upcoming seam */
|
||||
|
||||
/* read interleaved channels */
|
||||
if (
|
||||
/* this buffer contains a loop boundary, which lies on neither the first or the last frame, and therefore requires a splice of two reads from separate parts of the region. */
|
||||
seam_R > bS && seam_R < bE
|
||||
&&
|
||||
/* but if the end seam of the loop is also the end seam of the region, we only need one read */
|
||||
seam_R != rE
|
||||
&&
|
||||
/* also, if the seam is within the buffer, but beyond the end of the region (as in last loop iteration), do the simpler read in the else clause */
|
||||
seam_R <= rE
|
||||
)
|
||||
{
|
||||
/* this buffer covers a loop boundary */
|
||||
|
||||
/* read the first part */
|
||||
cnt = _clip->read( cbuf + ( _clip->channels() * bO ), -1, r.offset + lO, ( seam_R - bS ) - bO );
|
||||
cnt = _clip->read(
|
||||
cbuf + ( _clip->channels() * bO ), /* buf */
|
||||
-1, /* chan */
|
||||
r.offset + lO, /* start */
|
||||
( seam_R - bS ) - bO /* len */
|
||||
);
|
||||
|
||||
/* ASSERT( len > cnt, "Error in region looping calculations" ); */
|
||||
|
||||
/* read the second part */
|
||||
cnt += _clip->read( cbuf + ( _clip->channels() * ( bO + cnt ) ), -1, r.offset + 0, ( len - cnt ) - bO );
|
||||
cnt += _clip->read(
|
||||
cbuf + ( _clip->channels() * ( bO + cnt ) ), /* buf */
|
||||
-1, /* chan */
|
||||
r.offset + 0, /* start */
|
||||
( len - cnt ) - bO /* len */
|
||||
);
|
||||
|
||||
/* assert( cnt == len ); */
|
||||
}
|
||||
|
@ -247,17 +271,21 @@ Audio_Region::read ( sample_t *buf, bool buf_is_empty, nframes_t pos, nframes_t
|
|||
|
||||
Fade fade;
|
||||
|
||||
fade = declick < _fade_in ? _fade_in : declick;
|
||||
|
||||
/* do fade in if necessary */
|
||||
if ( sO < fade.length )
|
||||
apply_fade( cbuf, _clip->channels(), fade, bS, bE, rS, Fade::In );
|
||||
|
||||
fade = declick < _fade_out ? _fade_out : declick;
|
||||
|
||||
/* do fade out if necessary */
|
||||
if ( sO + cnt + fade.length > r.length )
|
||||
apply_fade( cbuf, _clip->channels(), fade, bS, bE, rE, Fade::Out );
|
||||
/* disabling fade also disables de-clicking for perfectly abutted edits. */
|
||||
if ( fade.type != Fade::Disabled )
|
||||
{
|
||||
fade = declick < _fade_in ? _fade_in : declick;
|
||||
|
||||
/* do fade in if necessary */
|
||||
if ( sO < fade.length )
|
||||
apply_fade( cbuf, _clip->channels(), fade, bS, bE, rS, Fade::In );
|
||||
|
||||
fade = declick < _fade_out ? _fade_out : declick;
|
||||
|
||||
/* do fade out if necessary */
|
||||
if ( sO + cnt + fade.length > r.length )
|
||||
apply_fade( cbuf, _clip->channels(), fade, bS, bE, rE, Fade::Out );
|
||||
}
|
||||
}
|
||||
|
||||
if ( buf != cbuf )
|
||||
|
|
|
@ -188,7 +188,10 @@ public:
|
|||
}
|
||||
|
||||
if ( ! blocks.size() )
|
||||
FATAL( "Peak file contains no blocks!" );
|
||||
{
|
||||
DWARNING( "Peak file contains no blocks, maybe it's still being generated?");
|
||||
return;
|
||||
}
|
||||
|
||||
blocks.sort();
|
||||
|
||||
|
@ -258,9 +261,19 @@ public:
|
|||
|
||||
scan( chunksize );
|
||||
|
||||
assert( _chunksize );
|
||||
/* assert( _chunksize ); */
|
||||
|
||||
return true;
|
||||
if ( blocks.size() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWARNING( "Peak file could not be opened: no blocks" );
|
||||
fclose(_fp);
|
||||
_fp = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -287,7 +287,7 @@ Track::record ( Capture *c, nframes_t frame )
|
|||
free( pat );
|
||||
|
||||
if ( ! c->audio_file )
|
||||
FATAL( "Could not create file for new capture!" );
|
||||
FATAL( "Could not create file for new capture! (%s)", pat );
|
||||
|
||||
/* open it again for reading in the GUI thread */
|
||||
// Audio_File *af = Audio_File::from_file( c->audio_file->name() );
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
/*******************************************************************************/
|
||||
/* Copyright (C) 2012 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 "OSC_Receive_Thread.H"
|
||||
|
||||
#include "Timeline.H"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "OSC/Endpoint.H"
|
||||
|
||||
extern Timeline *timeline;
|
||||
|
||||
OSC_Receive_Thread::OSC_Receive_Thread ( )
|
||||
{
|
||||
// _thread.init();
|
||||
_shutdown = false;
|
||||
}
|
||||
|
||||
OSC_Receive_Thread::~OSC_Receive_Thread ( )
|
||||
{
|
||||
lock();
|
||||
if ( _shutdown == false )
|
||||
{
|
||||
_shutdown = true;
|
||||
_thread.join();
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OSC_Receive_Thread::start ( )
|
||||
{
|
||||
_thread.clone( &OSC_Receive_Thread::process, this );
|
||||
}
|
||||
|
||||
void
|
||||
OSC_Receive_Thread::join ( )
|
||||
{
|
||||
_thread.join();
|
||||
}
|
||||
|
||||
void
|
||||
OSC_Receive_Thread::process ( void )
|
||||
{
|
||||
_thread.name( "OSC_Receive" );
|
||||
|
||||
DMESSAGE( "OSC Thread starting" );
|
||||
|
||||
while ( !_shutdown )
|
||||
{
|
||||
timeline->osc->wait(20);
|
||||
}
|
||||
|
||||
DMESSAGE( "OSC Thread stopping." );
|
||||
}
|
||||
|
||||
void *
|
||||
OSC_Receive_Thread::process ( void *v )
|
||||
{
|
||||
OSC_Receive_Thread *t = (OSC_Receive_Thread*)v;
|
||||
|
||||
t->process();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
#include "Thread.H"
|
||||
#include "Mutex.H"
|
||||
|
||||
class OSC_Thread : public Mutex
|
||||
class OSC_Receive_Thread : public Mutex
|
||||
{
|
||||
Thread _thread; /* io thread */
|
||||
|
||||
|
@ -30,9 +30,9 @@ class OSC_Thread : public Mutex
|
|||
|
||||
public:
|
||||
|
||||
OSC_Thread ( );
|
||||
OSC_Receive_Thread ( );
|
||||
|
||||
virtual ~OSC_Thread ( );
|
||||
virtual ~OSC_Receive_Thread ( );
|
||||
|
||||
void join ( void );
|
||||
void shutdown ( void ) { _shutdown = true; }
|
|
@ -17,7 +17,7 @@
|
|||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
/*******************************************************************************/
|
||||
|
||||
#include "OSC_Thread.H"
|
||||
#include "OSC_Transmit_Thread.H"
|
||||
|
||||
#include "Timeline.H"
|
||||
|
||||
|
@ -30,13 +30,13 @@
|
|||
|
||||
extern Timeline *timeline;
|
||||
|
||||
OSC_Thread::OSC_Thread ( )
|
||||
OSC_Transmit_Thread::OSC_Transmit_Thread ( )
|
||||
{
|
||||
// _thread.init();
|
||||
_shutdown = false;
|
||||
}
|
||||
|
||||
OSC_Thread::~OSC_Thread ( )
|
||||
OSC_Transmit_Thread::~OSC_Transmit_Thread ( )
|
||||
{
|
||||
lock();
|
||||
if ( _shutdown == false )
|
||||
|
@ -49,29 +49,29 @@ OSC_Thread::~OSC_Thread ( )
|
|||
|
||||
|
||||
void
|
||||
OSC_Thread::start ( )
|
||||
OSC_Transmit_Thread::start ( )
|
||||
{
|
||||
_thread.clone( &OSC_Thread::process, this );
|
||||
_thread.clone( &OSC_Transmit_Thread::process, this );
|
||||
}
|
||||
|
||||
void
|
||||
OSC_Thread::join ( )
|
||||
OSC_Transmit_Thread::join ( )
|
||||
{
|
||||
_thread.join();
|
||||
}
|
||||
|
||||
void
|
||||
OSC_Thread::process ( void )
|
||||
OSC_Transmit_Thread::process ( void )
|
||||
{
|
||||
_thread.name( "OSC" );
|
||||
_thread.name( "OSC_Transmit" );
|
||||
|
||||
DMESSAGE( "OSC Thread starting" );
|
||||
|
||||
while ( !_shutdown )
|
||||
{
|
||||
|
||||
if ( trylock() )
|
||||
{
|
||||
timeline->osc->check();
|
||||
timeline->process_osc();
|
||||
unlock();
|
||||
}
|
||||
|
@ -83,9 +83,9 @@ OSC_Thread::process ( void )
|
|||
}
|
||||
|
||||
void *
|
||||
OSC_Thread::process ( void *v )
|
||||
OSC_Transmit_Thread::process ( void *v )
|
||||
{
|
||||
OSC_Thread *t = (OSC_Thread*)v;
|
||||
OSC_Transmit_Thread *t = (OSC_Transmit_Thread*)v;
|
||||
|
||||
t->process();
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
/*******************************************************************************/
|
||||
/* Copyright (C) 2012 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 "Thread.H"
|
||||
#include "Mutex.H"
|
||||
|
||||
class OSC_Transmit_Thread : public Mutex
|
||||
{
|
||||
Thread _thread; /* io thread */
|
||||
|
||||
volatile bool _shutdown;
|
||||
|
||||
public:
|
||||
|
||||
OSC_Transmit_Thread ( );
|
||||
|
||||
virtual ~OSC_Transmit_Thread ( );
|
||||
|
||||
void join ( void );
|
||||
void shutdown ( void ) { _shutdown = true; }
|
||||
void start ( void );
|
||||
void process ( void );
|
||||
static void *process ( void * );
|
||||
};
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "Sequence_Region.H"
|
||||
#include "Track.H"
|
||||
#include "debug.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -128,6 +129,7 @@ Sequence_Region::split ( Sequence_Region * copy, nframes_t where )
|
|||
trim_right( where );
|
||||
copy->trim_left( where );
|
||||
sequence()->add( copy );
|
||||
copy->redraw();
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,6 +143,10 @@ Sequence_Region::handle ( int m )
|
|||
int X = Fl::event_x();
|
||||
int Y = Fl::event_y();
|
||||
|
||||
if ( !active_r() )
|
||||
/* don't mess with anything while recording... */
|
||||
return 0;
|
||||
|
||||
Logger _log( this );
|
||||
|
||||
switch ( m )
|
||||
|
|
|
@ -391,6 +391,10 @@ Sequence_Widget::handle ( int m )
|
|||
int X = Fl::event_x();
|
||||
int Y = Fl::event_y();
|
||||
|
||||
if ( !active_r() )
|
||||
/* don't mess with anything while recording... */
|
||||
return 0;
|
||||
|
||||
Logger _log( this );
|
||||
|
||||
switch ( m )
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
#include "TLE.H"
|
||||
/* */
|
||||
|
||||
#include "OSC_Thread.H"
|
||||
|
||||
#include "OSC/Endpoint.H"
|
||||
|
||||
#include <unistd.h>
|
||||
|
@ -612,8 +612,10 @@ Timeline::ntracks ( void ) const
|
|||
|
||||
Timeline::~Timeline ( )
|
||||
{
|
||||
delete osc_thread;
|
||||
osc_thread = 0;
|
||||
delete osc_transmit_thread;
|
||||
osc_transmit_thread = 0;
|
||||
delete osc_receive_thread;
|
||||
osc_receive_thread = 0;
|
||||
delete osc;
|
||||
osc = 0;
|
||||
}
|
||||
|
@ -627,7 +629,8 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
|
|||
play_cursor_track = NULL;
|
||||
|
||||
_created_new_takes = 0;
|
||||
osc_thread = 0;
|
||||
osc_transmit_thread = 0;
|
||||
osc_receive_thread = 0;
|
||||
_sample_rate = 44100;
|
||||
|
||||
box( FL_FLAT_BOX );
|
||||
|
@ -997,20 +1000,32 @@ Timeline::draw_measure_cb ( nframes_t frame, const BBT &bbt, void *v )
|
|||
{
|
||||
Timeline *o = (Timeline*)v;
|
||||
|
||||
Fl_Color c = FL_LIGHT3;
|
||||
|
||||
if ( o->panzoomer->zoom() >= 15 )
|
||||
return;
|
||||
|
||||
Fl_Color mc = FL_LIGHT3;
|
||||
Fl_Color bc = FL_LIGHT2;
|
||||
Fl_Color c;
|
||||
Fl_Color ct = fl_contrast( mc, FL_BACKGROUND_COLOR );
|
||||
|
||||
if ( FL_BLACK == ct )
|
||||
{
|
||||
/* in a light color scheme mode */
|
||||
mc = fl_rgb_color(30,30,30);
|
||||
bc = FL_DARK3;
|
||||
}
|
||||
|
||||
if ( bbt.beat )
|
||||
{
|
||||
if ( o->panzoomer->zoom() > 12 )
|
||||
return;
|
||||
else
|
||||
c = FL_DARK1;
|
||||
c = bc;
|
||||
}
|
||||
else
|
||||
c = mc;
|
||||
|
||||
fl_color( fl_color_add_alpha( c, 64 ) );
|
||||
fl_color( fl_color_add_alpha( c, 127 ) );
|
||||
|
||||
const int x = timeline->ts_to_x( frame - timeline->xoffset ) + Track::width();
|
||||
|
||||
|
@ -2167,11 +2182,18 @@ Timeline::init_osc ( const char *osc_port )
|
|||
|
||||
// osc->start();
|
||||
|
||||
if ( ! osc_thread )
|
||||
if ( ! osc_transmit_thread )
|
||||
{
|
||||
osc_thread = new OSC_Thread();
|
||||
osc_transmit_thread = new OSC_Transmit_Thread();
|
||||
|
||||
osc_thread->start();
|
||||
osc_transmit_thread->start();
|
||||
}
|
||||
|
||||
if ( ! osc_receive_thread )
|
||||
{
|
||||
osc_receive_thread = new OSC_Receive_Thread();
|
||||
|
||||
osc_receive_thread->start();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2250,7 +2272,7 @@ Timeline::update_osc_connection_state ( void )
|
|||
void
|
||||
Timeline::process_osc ( void )
|
||||
{
|
||||
THREAD_ASSERT( OSC );
|
||||
THREAD_ASSERT( OSC_Transmit );
|
||||
|
||||
sequence_lock.rdlock();
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
#include <assert.h>
|
||||
#include <list>
|
||||
|
||||
#include "OSC_Thread.H"
|
||||
#include "OSC_Transmit_Thread.H"
|
||||
#include "OSC_Receive_Thread.H"
|
||||
|
||||
class Fl_Scroll;
|
||||
class Fl_Pack;
|
||||
|
@ -136,7 +137,8 @@ public:
|
|||
void damage_sequence ( void );
|
||||
|
||||
OSC::Endpoint *osc;
|
||||
OSC_Thread *osc_thread;
|
||||
OSC_Transmit_Thread *osc_transmit_thread;
|
||||
OSC_Receive_Thread *osc_receive_thread;
|
||||
|
||||
void process_osc ( void );
|
||||
#undef Bars
|
||||
|
|
|
@ -134,7 +134,7 @@ Track::init ( void )
|
|||
_name = NULL;
|
||||
_selected = false;
|
||||
_size = 1;
|
||||
|
||||
|
||||
record_ds = NULL;
|
||||
playback_ds = NULL;
|
||||
|
||||
|
@ -604,6 +604,10 @@ Track::remove ( Audio_Sequence *t )
|
|||
if ( ! takes )
|
||||
return;
|
||||
|
||||
Loggable::block_start();
|
||||
|
||||
Logger log(this);
|
||||
|
||||
if ( sequence() == t )
|
||||
{
|
||||
pack->remove( t );
|
||||
|
@ -617,8 +621,11 @@ Track::remove ( Audio_Sequence *t )
|
|||
else
|
||||
takes->remove( t );
|
||||
|
||||
/* delete t; */
|
||||
/* doing this here creates a cycle */
|
||||
/* delete t; */
|
||||
|
||||
Loggable::block_end();
|
||||
|
||||
adjust_size();
|
||||
}
|
||||
|
||||
|
@ -647,9 +654,12 @@ Track::remove ( Control_Sequence *t )
|
|||
void
|
||||
Track::sequence ( Audio_Sequence * t )
|
||||
{
|
||||
Logger log(this);
|
||||
|
||||
if ( sequence() == t )
|
||||
{
|
||||
DMESSAGE( "Attempt to set sequence twice" );
|
||||
/* ASSERT( false, "Attempt to set same sequence twice" ); */
|
||||
DMESSAGE( "Attempt to set same sequence twice, %p == %p", t, sequence() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -873,8 +883,13 @@ Track::menu_cb ( const Fl_Menu_ *m )
|
|||
else if ( !strcmp( picked, "Takes/New" ) )
|
||||
{
|
||||
timeline->track_lock.wrlock();
|
||||
|
||||
Loggable::block_start();
|
||||
|
||||
sequence( (Audio_Sequence*)sequence()->clone_empty() );
|
||||
timeline->track_lock.unlock();
|
||||
|
||||
Loggable::block_end();
|
||||
}
|
||||
else if ( !strcmp( picked, "Takes/Remove" ) )
|
||||
{
|
||||
|
@ -909,7 +924,7 @@ Track::menu_cb ( const Fl_Menu_ *m )
|
|||
else if ( !strncmp( picked, "Takes/", sizeof( "Takes/" ) - 1 ) )
|
||||
{
|
||||
Audio_Sequence* s = (Audio_Sequence*)m->mvalue()->user_data();
|
||||
|
||||
|
||||
timeline->track_lock.wrlock();
|
||||
sequence( s );
|
||||
timeline->track_lock.unlock();
|
||||
|
@ -1044,7 +1059,10 @@ Track::draw ( void )
|
|||
int
|
||||
Track::handle ( int m )
|
||||
{
|
||||
|
||||
if ( !active_r() )
|
||||
/* don't mess with anything while recording... */
|
||||
return 0;
|
||||
|
||||
/* if ( m != FL_NO_EVENT ) */
|
||||
/* DMESSAGE( "%s", event_name( m ) ); */
|
||||
static Fl_Widget *dragging = NULL;
|
||||
|
@ -1056,7 +1074,8 @@ Track::handle ( int m )
|
|||
case FL_DND_DRAG:
|
||||
case FL_DND_RELEASE:
|
||||
case FL_PASTE:
|
||||
if ( Fl::event_x() > Track::width() )
|
||||
if ( dragging != ((Track_Header*)child(0))->output_connector_handle &&
|
||||
Fl::event_x() > Track::width() )
|
||||
return sequence()->handle(m);
|
||||
default:
|
||||
break;
|
||||
|
@ -1097,6 +1116,7 @@ Track::handle ( int m )
|
|||
if ( Fl::event_button1() && Fl::event_inside( ((Track_Header*)child(0))->color_box ) )
|
||||
{
|
||||
dragging = this;
|
||||
fl_cursor( FL_CURSOR_MOVE );
|
||||
return 1;
|
||||
}
|
||||
if ( Fl::event_button1() && Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) )
|
||||
|
@ -1119,32 +1139,50 @@ Track::handle ( int m )
|
|||
case FL_ENTER:
|
||||
case FL_LEAVE:
|
||||
case FL_MOVE:
|
||||
if ( Fl::event_x() >= Track::width() )
|
||||
|
||||
if ( dragging != ((Track_Header*)child(0))->output_connector_handle &&
|
||||
Fl::event_x() >= Track::width() )
|
||||
{
|
||||
return Fl_Group::handle(m);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) ||
|
||||
Fl::event_inside( ((Track_Header*)child(0))->input_connector_handle ) ||
|
||||
Fl::event_inside( ((Track_Header*)child(0))->color_box ) )
|
||||
fl_cursor( FL_CURSOR_HAND );
|
||||
}
|
||||
return 1;
|
||||
case FL_DND_ENTER:
|
||||
return 1;
|
||||
case FL_DND_LEAVE:
|
||||
|
||||
if ( ! Fl::event_inside(this) && this == receptive_to_drop )
|
||||
{
|
||||
/* if ( ! Fl::event_inside(this) )// && this == receptive_to_drop ) */
|
||||
/* { */
|
||||
receptive_to_drop = 0;
|
||||
redraw();
|
||||
Fl::selection_owner(0);
|
||||
}
|
||||
/* } */
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if ( dragging == this )
|
||||
{
|
||||
dragging = NULL;
|
||||
timeline->insert_track( this, timeline->event_inside() );
|
||||
return 1;
|
||||
fl_cursor( FL_CURSOR_DEFAULT );
|
||||
return 1;
|
||||
}
|
||||
else if ( dragging == ((Track_Header*)child(0))->output_connector_handle )
|
||||
{
|
||||
dragging = NULL;
|
||||
fl_cursor( FL_CURSOR_DEFAULT );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Fl_Group::handle( m );
|
||||
break;
|
||||
case FL_DND_RELEASE:
|
||||
dragging = NULL;
|
||||
receptive_to_drop = 0;
|
||||
redraw();
|
||||
Fl::selection_owner(0);
|
||||
|
@ -1228,6 +1266,9 @@ Track::handle ( int m )
|
|||
}
|
||||
case FL_DRAG:
|
||||
{
|
||||
if ( Fl::event_is_click() )
|
||||
return 1;
|
||||
|
||||
if ( this != Fl::selection_owner() &&
|
||||
Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) )
|
||||
{
|
||||
|
@ -1237,8 +1278,9 @@ Track::handle ( int m )
|
|||
for ( unsigned int i = 0; i < output.size(); ++i )
|
||||
{
|
||||
char *s2;
|
||||
asprintf(&s2, "jack.port://%s:%s\r\n", instance_name, output[i].name() );
|
||||
|
||||
asprintf(&s2, "jack.port://%s\r\n",
|
||||
output[i].jack_name() );
|
||||
|
||||
s = (char*)realloc( s, strlen( s ) + strlen( s2 ) + 1 );
|
||||
strcat( s, s2 );
|
||||
|
||||
|
@ -1250,14 +1292,12 @@ Track::handle ( int m )
|
|||
|
||||
free( s );
|
||||
|
||||
dragging = ((Track_Header*)child(0))->output_connector_handle;
|
||||
|
||||
Fl::dnd();
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return Fl_Group::handle( m );
|
||||
|
|
|
@ -5,7 +5,7 @@ import string
|
|||
import os;
|
||||
|
||||
# Version of this package (even if built as a child)
|
||||
PACKAGE_VERSION = '1.2.0'
|
||||
PACKAGE_VERSION = '1.3.0'
|
||||
|
||||
# Variables for 'waf dist'
|
||||
APPNAME = 'non-timeline'
|
||||
|
@ -76,7 +76,8 @@ src/Engine/Record_DS.C
|
|||
src/Engine/Timeline.C
|
||||
src/Engine/Track.C
|
||||
src/NSM.C
|
||||
src/OSC_Thread.C
|
||||
src/OSC_Transmit_Thread.C
|
||||
src/OSC_Receive_Thread.C
|
||||
src/Project.C
|
||||
src/Sequence.C
|
||||
src/Sequence_Point.C
|
||||
|
@ -108,8 +109,8 @@ src/main.C
|
|||
## use = [ 'fl_widgets', 'nonlib'],
|
||||
install_path = '${BINDIR}')
|
||||
|
||||
bld.install_files('${BINDIR}', 'import-ardour-session', chmod=0o0555,
|
||||
cwd=bld.path.find_dir('bin'), relative_trick=True)
|
||||
bld.install_files('${BINDIR}', 'bin/import-ardour-session', chmod=0o0555,
|
||||
relative_trick=True)
|
||||
|
||||
bld( features = 'subst',
|
||||
source = 'non-timeline.desktop.in',
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
from waflib import Task
|
||||
from waflib.TaskGen import extension
|
||||
|
||||
class ntk_fluid(Task.Task):
|
||||
color = 'BLUE'
|
||||
ext_out = ['.h']
|
||||
run_str = '${NTK_FLUID} -c -o ${TGT[0].abspath()} -h ${TGT[1].abspath()} ${SRC}'
|
||||
|
||||
@extension('.fl')
|
||||
def fluid(self, node):
|
||||
"""add the .fl to the source list; the cxx file generated will be compiled when possible"""
|
||||
cpp = node.change_ext('.C')
|
||||
hpp = node.change_ext('.H')
|
||||
self.create_task('ntk_fluid', node, [cpp, hpp])
|
||||
|
||||
if 'cxx' in self.features:
|
||||
self.source.append(cpp)
|
||||
|
11
wscript
11
wscript
|
@ -21,6 +21,8 @@ def options(opt):
|
|||
help='Build for debugging')
|
||||
opt.add_option('--disable-sse', action='store_false', default=True, dest='sse',
|
||||
help='Disable SSE optimization')
|
||||
opt.add_option('--disable-native-cpu-optimization', action='store_false', default=True, dest='native',
|
||||
help='Disable native CPU optimziation (e.g. for generic binary packaging)')
|
||||
opt.add_option('--project', action='store', default=False, dest='project',
|
||||
help='Limit build to a single project (' + ', '.join( projects ) + ')')
|
||||
|
||||
|
@ -31,7 +33,7 @@ def configure(conf):
|
|||
conf.load('compiler_c')
|
||||
conf.load('compiler_cxx')
|
||||
conf.load('gnu_dirs')
|
||||
conf.load('ntk_fluid')
|
||||
conf.load('ntk_fluid',tooldir='tools.waf')
|
||||
conf.load('gccdeps')
|
||||
conf.line_just = 52
|
||||
|
||||
|
@ -94,6 +96,13 @@ def configure(conf):
|
|||
"-ffast-math",
|
||||
"-pipe"
|
||||
]
|
||||
|
||||
if Options.options.native:
|
||||
print('Using native CPU optimization')
|
||||
optimization_flags.extend( [
|
||||
"-march=native",
|
||||
"-mtune=native", # ~200% DSP performance increase on AMD bulldozer...
|
||||
]);
|
||||
|
||||
if Options.options.sse:
|
||||
print('Using SSE optimization')
|
||||
|
|
Loading…
Reference in New Issue