Implement Queue playback mode.
Pattern muteing/unmuteing (via GUI or MIDI) takes effect the next time the pattern loops.
This commit is contained in:
parent
802f4c572f
commit
17e32e0282
|
@ -822,7 +822,8 @@ Grid::mode ( int m )
|
|||
{
|
||||
_mode = m;
|
||||
|
||||
signal_settings_change();
|
||||
/* can't do this in RT thread, sorry. */
|
||||
/// signal_settings_change();
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -122,7 +122,7 @@ protected:
|
|||
volatile mutable tick_t _index; /* playhead, relative to start -- primarily used to draw the playhead */
|
||||
volatile mutable bool _playing; /* true if currently playing */
|
||||
|
||||
volatile int _mode; /* mute, solo */
|
||||
mutable volatile int _mode; /* mute, solo */
|
||||
|
||||
// FIXME: shouldn't this be "volatile"?
|
||||
// const volatile data *_rd; /* read only data used by RT thread */
|
||||
|
|
|
@ -185,7 +185,7 @@ if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape )
|
|||
|
||||
if ( maybe_save_song() )
|
||||
quit();} open
|
||||
xywh {209 100 865 800} type Double box PLASTIC_UP_BOX color 37 resizable xclass non size_range {600 420 0 0} visible
|
||||
xywh {856 305 865 800} type Double box PLASTIC_UP_BOX color 37 resizable xclass non size_range {600 420 0 0} visible
|
||||
} {
|
||||
Fl_Menu_Bar menu_bar {open
|
||||
xywh {0 0 869 30} color 37
|
||||
|
@ -983,7 +983,7 @@ else
|
|||
} {
|
||||
MenuItem {} {
|
||||
label Pattern
|
||||
callback {song.play_mode = PATTERN;}
|
||||
callback {song.play_mode = PATTERN;} selected
|
||||
xywh {5 5 40 25}
|
||||
}
|
||||
MenuItem {} {
|
||||
|
@ -996,6 +996,11 @@ else
|
|||
callback {song.play_mode = TRIGGER;}
|
||||
xywh {25 25 40 25}
|
||||
}
|
||||
MenuItem {} {
|
||||
label Queue
|
||||
callback {song.play_mode = QUEUE;}
|
||||
xywh {0 0 40 24}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group {} {open
|
||||
|
|
31
src/jack.C
31
src/jack.C
|
@ -307,6 +307,7 @@ process ( jack_nframes_t nframes, void *arg )
|
|||
{
|
||||
case PATTERN:
|
||||
case TRIGGER:
|
||||
case QUEUE:
|
||||
DMESSAGE( "Stopping all patterns" );
|
||||
stop_all_patterns();
|
||||
break;
|
||||
|
@ -343,41 +344,55 @@ process ( jack_nframes_t nframes, void *arg )
|
|||
|
||||
/* no need to pass it to the GUI, we can trigger patterns here */
|
||||
|
||||
|
||||
if ( e.channel() == 0 && e.is_note_on() )
|
||||
{
|
||||
if ( e.note() < pattern::patterns() )
|
||||
{
|
||||
|
||||
pattern *p = pattern::pattern_by_number( e.note() + 1 );
|
||||
|
||||
if ( p->playing() )
|
||||
if ( TRIGGER == song.play_mode )
|
||||
{
|
||||
DMESSAGE( "Untriggering pattern %i", e.note() );
|
||||
|
||||
if ( e.note() < pattern::patterns() )
|
||||
if ( p->playing() )
|
||||
{
|
||||
pattern *p = pattern::pattern_by_number( e.note() + 1 );
|
||||
|
||||
DMESSAGE( "Untriggering pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
||||
|
||||
p->trigger( ph, e.timestamp() );
|
||||
}
|
||||
else
|
||||
{
|
||||
DMESSAGE( "Triggering pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
||||
|
||||
p->trigger( e.timestamp(), -1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DMESSAGE( "Triggering pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
||||
if ( p->mode() == PLAY )
|
||||
{
|
||||
DMESSAGE( "Dequeuing pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
||||
p->mode( MUTE );
|
||||
}
|
||||
else
|
||||
{
|
||||
DMESSAGE( "Queuing pattern %i ph=%lu, ts=%lu", e.note(), ph, e.timestamp() );
|
||||
|
||||
p->trigger( e.timestamp(), -1 );
|
||||
p->mode( PLAY );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch ( song.play_mode )
|
||||
{
|
||||
case SEQUENCE:
|
||||
playlist->play( ph, nph );
|
||||
break;
|
||||
case QUEUE:
|
||||
case PATTERN:
|
||||
{
|
||||
for ( uint i = pattern::patterns(); i--; )
|
||||
|
|
|
@ -51,7 +51,8 @@ bool save_song ( const char *name );
|
|||
enum play_mode_e {
|
||||
PATTERN,
|
||||
SEQUENCE,
|
||||
TRIGGER
|
||||
TRIGGER,
|
||||
QUEUE
|
||||
// PHRASE,
|
||||
};
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ pattern::pattern ( void )
|
|||
_ppqn = 4;
|
||||
_bpb = 4;
|
||||
_note = 8;
|
||||
|
||||
_queued = -1;
|
||||
|
||||
int _bars = 2;
|
||||
|
||||
// we need to reinitalize this.
|
||||
|
@ -325,6 +328,12 @@ pattern::stop ( void ) const
|
|||
void
|
||||
pattern::mode ( int n )
|
||||
{
|
||||
if ( QUEUE == song.play_mode )
|
||||
{
|
||||
queue( n );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( n == SOLO )
|
||||
{
|
||||
if ( pattern::_solo )
|
||||
|
@ -355,6 +364,19 @@ pattern::mode ( void ) const
|
|||
return Grid::mode();
|
||||
}
|
||||
|
||||
/* queue a mode change for the next loop */
|
||||
void
|
||||
pattern::queue ( int m )
|
||||
{
|
||||
_queued = m;
|
||||
}
|
||||
|
||||
int
|
||||
pattern::queue ( void ) const
|
||||
{
|
||||
return _queued;
|
||||
}
|
||||
|
||||
/* WARNING: runs in the RT thread! */
|
||||
// output notes from /start/ to /end/ (absolute)
|
||||
void
|
||||
|
@ -389,11 +411,33 @@ pattern::play ( tick_t start, tick_t end ) const
|
|||
|
||||
_index = tick % d->length;
|
||||
|
||||
bool reset_queued = false;
|
||||
|
||||
if ( _index < end - start )
|
||||
{
|
||||
/* period covers the beginning of the loop */
|
||||
DMESSAGE( "%s pattern %d at tick %lu (ls: %lu, le: %lu, o: %lu)", _playing ? "Looped" : "Triggered", number(), start, _start, _end, offset );
|
||||
|
||||
_cleared = false;
|
||||
|
||||
if ( PLAY == _queued )
|
||||
{
|
||||
/* set the start point to loop boundary */
|
||||
start = start - _index;
|
||||
_mode = PLAY;
|
||||
|
||||
reset_queued = true;
|
||||
}
|
||||
}
|
||||
else if ( _index >= d->length - ( end - start ) )
|
||||
{
|
||||
if ( MUTE == _queued )
|
||||
{
|
||||
/* set the end point to loop boundary */
|
||||
end = end - _index;
|
||||
|
||||
reset_queued = true;
|
||||
}
|
||||
}
|
||||
|
||||
_playing = true;
|
||||
|
@ -455,6 +499,12 @@ try_again:
|
|||
|
||||
done:
|
||||
|
||||
if ( _queued >= 0 && reset_queued )
|
||||
{
|
||||
_mode = _queued;
|
||||
_queued = -1;
|
||||
}
|
||||
|
||||
if ( _end == end )
|
||||
{
|
||||
/* we're done playing this trigger */
|
||||
|
|
|
@ -43,13 +43,12 @@ class pattern : public Grid
|
|||
bool _recording;
|
||||
mutable volatile bool _cleared;
|
||||
|
||||
volatile bool _triggered;
|
||||
mutable volatile int _queued;
|
||||
|
||||
// int _key;
|
||||
|
||||
int _note;
|
||||
|
||||
|
||||
void _add ( void );
|
||||
|
||||
|
||||
|
@ -88,8 +87,8 @@ public:
|
|||
void record( int mode );
|
||||
void record_stop ( void );
|
||||
|
||||
void toggle_trigger ( void );
|
||||
bool triggered ( void ) const;
|
||||
void queue ( int mode );
|
||||
int queue ( void ) const;
|
||||
|
||||
void randomize_row ( int y, int feel, float probability );
|
||||
|
||||
|
|
Loading…
Reference in New Issue