Improve queue playback mode. Flash pattern trigger with color of queued state.
Also, use Channel 0 CC 20 0-127 for pattern triggering instead of NOTE ONs.
This commit is contained in:
parent
0d62b91605
commit
71e0583696
|
@ -1750,7 +1750,9 @@ widget_class Triggers {open
|
||||||
} {}
|
} {}
|
||||||
Function {populate( void )} {open private return_type void
|
Function {populate( void )} {open private return_type void
|
||||||
} {
|
} {
|
||||||
code {int bw = (w() / 16);
|
code {_timer = 0;
|
||||||
|
|
||||||
|
int bw = (w() / 16);
|
||||||
int bh = h() / (128/ 16);
|
int bh = h() / (128/ 16);
|
||||||
|
|
||||||
begin();
|
begin();
|
||||||
|
@ -1799,13 +1801,21 @@ redraw();} {}
|
||||||
}
|
}
|
||||||
Function {update( void )} {open return_type void
|
Function {update( void )} {open return_type void
|
||||||
} {
|
} {
|
||||||
code {if ( ! takesevents() )
|
code {++_timer;
|
||||||
|
|
||||||
|
if ( ! takesevents() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for ( i = 0; i < MAX_PATTERN; i++ )
|
for ( i = 0; i < MAX_PATTERN; i++ )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Fl_Color mode_color[3];
|
||||||
|
|
||||||
|
mode_color[PLAY] = FL_GREEN;
|
||||||
|
mode_color[MUTE] = FL_GRAY;
|
||||||
|
mode_color[SOLO] = FL_RED;
|
||||||
|
|
||||||
Trigger *b = (Trigger*)(((Fl_Pack*)rows->child( i / 16 ))->child( i % 16 ));
|
Trigger *b = (Trigger*)(((Fl_Pack*)rows->child( i / 16 ))->child( i % 16 ));
|
||||||
|
|
||||||
if ( i >= pattern::patterns() )
|
if ( i >= pattern::patterns() )
|
||||||
|
@ -1821,22 +1831,15 @@ for ( i = 0; i < MAX_PATTERN; i++ )
|
||||||
{
|
{
|
||||||
b->color( fl_lighter( FL_GRAY ) );
|
b->color( fl_lighter( FL_GRAY ) );
|
||||||
|
|
||||||
Fl_Color c = FL_BLUE;
|
b->selection_color( mode_color[ p->mode() ] );
|
||||||
|
|
||||||
switch ( p->mode() )
|
if ( p->queue() >= 0 )
|
||||||
{
|
{
|
||||||
case MUTE:
|
if ( _timer % 16 < 8 )
|
||||||
c = FL_GRAY;
|
{
|
||||||
break;
|
b->color( mode_color[ p->queue() ] );
|
||||||
case SOLO:
|
}
|
||||||
c = FL_RED;
|
}
|
||||||
break;
|
|
||||||
case PLAY:
|
|
||||||
c = FL_GREEN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
b->selection_color( c );
|
|
||||||
|
|
||||||
b->value( (double)p->index() / p->length() );
|
b->value( (double)p->index() / p->length() );
|
||||||
}
|
}
|
||||||
|
@ -1845,7 +1848,8 @@ for ( i = 0; i < MAX_PATTERN; i++ )
|
||||||
b->value( 0 );
|
b->value( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
}} {}
|
}} {selected
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Function {resize( int X, int Y, int W, int H )} {open return_type void
|
Function {resize( int X, int Y, int W, int H )} {open return_type void
|
||||||
} {
|
} {
|
||||||
|
@ -1866,4 +1870,6 @@ for ( i = 0; i < MAX_PATTERN; i++ )
|
||||||
|
|
||||||
Fl_Group::resize( X, Y, W, H );} {}
|
Fl_Group::resize( X, Y, W, H );} {}
|
||||||
}
|
}
|
||||||
|
decl {unsigned long _timer;} {private local
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
24
src/jack.C
24
src/jack.C
|
@ -43,6 +43,13 @@
|
||||||
#define jack_midi_event_write( b, f, d, s ) jack_midi_event_write( b, f, d, s, nframes )
|
#define jack_midi_event_write( b, f, d, s ) jack_midi_event_write( b, f, d, s, nframes )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* MIDI channel to listen for pattern control changes on */
|
||||||
|
int pattern_control_channel = 0;
|
||||||
|
|
||||||
|
/* which control change number to use for pattern control */
|
||||||
|
int pattern_control_cc = 20;
|
||||||
|
|
||||||
jack_client_t *client;
|
jack_client_t *client;
|
||||||
|
|
||||||
int sample_rate;
|
int sample_rate;
|
||||||
|
@ -345,25 +352,26 @@ process ( jack_nframes_t nframes, void *arg )
|
||||||
|
|
||||||
/* no need to pass it to the GUI, we can trigger patterns here */
|
/* no need to pass it to the GUI, we can trigger patterns here */
|
||||||
|
|
||||||
|
if ( e.channel() == pattern_control_channel &&
|
||||||
if ( e.channel() == 0 && e.is_note_on() )
|
e.opcode() == midievent::CONTROL_CHANGE &&
|
||||||
|
e.lsb() == pattern_control_cc )
|
||||||
{
|
{
|
||||||
if ( e.note() < pattern::patterns() )
|
if ( e.msb() < pattern::patterns() )
|
||||||
{
|
{
|
||||||
|
|
||||||
pattern *p = pattern::pattern_by_number( e.note() + 1 );
|
pattern *p = pattern::pattern_by_number( e.msb() + 1 );
|
||||||
|
|
||||||
if ( TRIGGER == song.play_mode )
|
if ( TRIGGER == song.play_mode )
|
||||||
{
|
{
|
||||||
if ( p->playing() )
|
if ( p->playing() )
|
||||||
{
|
{
|
||||||
DMESSAGE( "Untriggering pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
DMESSAGE( "Untriggering pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() );
|
||||||
|
|
||||||
p->trigger( ph, e.timestamp() );
|
p->trigger( ph, e.timestamp() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMESSAGE( "Triggering pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
DMESSAGE( "Triggering pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() );
|
||||||
|
|
||||||
p->trigger( e.timestamp(), -1 );
|
p->trigger( e.timestamp(), -1 );
|
||||||
}
|
}
|
||||||
|
@ -372,12 +380,12 @@ process ( jack_nframes_t nframes, void *arg )
|
||||||
{
|
{
|
||||||
if ( p->mode() == PLAY )
|
if ( p->mode() == PLAY )
|
||||||
{
|
{
|
||||||
DMESSAGE( "Dequeuing pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
DMESSAGE( "Dequeuing pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() );
|
||||||
p->mode( MUTE );
|
p->mode( MUTE );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DMESSAGE( "Queuing pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
DMESSAGE( "Queuing pattern %i ph=%lu, ts=%lu", e.msb(), ph, e.timestamp() );
|
||||||
|
|
||||||
p->mode( PLAY );
|
p->mode( PLAY );
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,12 +420,25 @@ pattern::play ( tick_t start, tick_t end ) const
|
||||||
|
|
||||||
_cleared = false;
|
_cleared = false;
|
||||||
|
|
||||||
if ( PLAY == _queued )
|
if ( PLAY == _queued || SOLO == _queued )
|
||||||
{
|
{
|
||||||
/* set the start point to loop boundary */
|
/* set the start point to loop boundary */
|
||||||
start = start - _index;
|
start = start - _index;
|
||||||
_mode = PLAY;
|
_mode = _queued;
|
||||||
|
|
||||||
|
if ( SOLO == _mode )
|
||||||
|
{
|
||||||
|
if ( pattern::_solo )
|
||||||
|
((Grid*)pattern::pattern_by_number( pattern::_solo ))->mode( PLAY );
|
||||||
|
|
||||||
|
pattern::_solo = _number;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( pattern::_solo == _number )
|
||||||
|
pattern::_solo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
reset_queued = true;
|
reset_queued = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue