How to Add Pause Functionality?
Chris Ahlstrom
2016-02-13 to 2016-03-20

We would like to be able to pause the playback, and have it resume where
it left off.  This feature would have to include the ability to have
Sequencer64 set the new position in JACK when running as JACK Master.

We also want to be able to page the seqedit/seqroll view as the bar progresses,
for sequences that are longer than can be seen whole in the window.

First, let us survey how the Stop functionality works.

In mainwnd::stop_playing(), the important code is a call to
perform.stop_playing().  Those functions ultimately call
jack_assistant::stop() and, if jack is NOT running, inner_stop().

The perform::inner_stop() function calls reset_sequences(), which calls
sequence::reset() for each sequence.  That calls zero_markers(), which
just sets m_last_tick = 0 by calling sequence::set_last_tick(0).

    -   If we are pausing, then we should skip this call to
        zero_markers(), or pass sequence::m_last_tick to it.

In sequence::play(), the starting tick is set to m_last_tick.  The
triggers::play() function also bases the starting tick on
sequence::m_last_tick.

So one idea is to add a pause flag to inner_stop(), reset_sequences(), and
reset(), to avoid changing m_last_tick.

    Wrinkle:  In perform::input(), MIDI clock is supported, and we want to
    make sure that we do not break MIDI Start, Continue, and Stop.  Also,
    we need to test these and Song Position before we start monkeying with
    a pause functionality.

    We will add a pause button and pause functions to isolate the pause
    functionality from the stop and play functionality somewhat.

In mainwid::draw_sequences_on_pixmap(), the m_last_tick_x[] values are
set to 0.

    -   They should set it to the sequence m_last_tick value, as returned
        by function xxxxxx().

Now, in jack_assistant::stop(), all that is done is call
jack_transport_stop().  Not much we can do there, unless we need to add
code to preserve the JACK transport position. (We do no need to.)

The perfroll::stop_playing() function calls perfrom::stop_playing(),
already covered.  Same for perfedit::stop_playing().

A VERY IMPORTANT point to note is that, when Sequencer64 is JACK Master,
the pause functionality ALREADY exists.  Stopping the song, even using the
Stop button, preserves the position, which resumes when the song
continues.  Do not mess that up!  (However, the cursor still disappears
once stopped, would be nice to see it where it paused.)

BUG:  In the main window, when paused, the progress bars sit near the end
      of each pattern.

BUG:  When resetting position to 1:1:0 in qjackctr, Sequencer24 should
      reset its progress bars in the main and song windows, and in the
      maintime area.

BUG:  The song window progress bar disappears when JACK transport pauses.

WARNING:

    triggers::copy() optimized, watch for programmer error :-D

BUG? seqedit for program-change only sequence, the cursor for sequences
     imported from b4uacuse.mid having only one program change moves
     wildly, until the sequence is open in the sequence editor, which
     makes one important change, as noted below:

    zoom: 2 to 2
    snap: 48 to 48
    note length: 48 to 48
    beat/bar: no change (4)
    measures: 0 to 1              ***

    Why does seqedit call set_data_type(EVENT_NOTE_ON)???

And do not forget about paging horizontally in the sequence editor to
follow the progress bar.

	void test::setView(int iH, int iV)
	{
		 m_adjh.set_value(iH);
		 m_adjv.set_value(iV);
		 m_scrW.set_vadjustment(m_adjh, m_adjv); 	// EXTRANEOUS
		 repaintEverything();
	}

	void Gtk::Adjustment::clamp_page(double	lower, double upper)

    Updates the Adjustment value to ensure that the range between the
    parameters lower and upper is in the current page (i.e. between value
    and value + page_size).  If this range is larger than the page size,
    then only the start of it will be in the current page. A "changed"
    signal will be emitted if the value is changed.

    double Gtk::Adjustment::get_value () const
    void Gtk::Adjustment::set_page_size (double page_size)   
    double Gtk::Adjustment::get_page_size () const
    double Gtk::Adjustment::get_step_increment () const

    seqedit/seqroll horizontal values (never changes):

        L:   scroll value = 0; step = 96; page = 1392; upper = 66816
        R:   scroll value = 65424; step = 96; page = 1392; upper = 66816

    With --ppqn 384 option:

        scroll value = 0; step = 192; page = 1392; upper = 133632

    Again, with progress-x shown in the leftmost position, just as the bar
    hits the right edge of the window:

        seqroll scroll progress=650; value=0; step=96; page=1388; upper=66816
        seqroll scroll progress=657; value=0; step=96; page=1388; upper=66816
        seqroll scroll progress=665; value=0; step=96; page=1388; upper=66816
        seqroll scroll progress=673; value=0; step=96; page=1388; upper=66816
        seqroll scroll progress=681; value=0; step=96; page=1388; upper=66816
        seqroll scroll progress=688; value=0; step=96; page=1388; upper=66816
        seqroll scroll progress=696; value=0; step=96; page=1388; upper=66816

    Note that the default zoom is 2, so that the maximum tick value for
    the window is one/half the windows size, by default.

    With --ppqn 384 option:

		seqroll scroll progress=648; value=0; step=192; page=1388; upper=133632
		seqroll scroll progress=664; value=0; step=192; page=1388; upper=133632
		seqroll scroll progress=679; value=0; step=192; page=1388; upper=133632
		seqroll scroll progress=695; value=0; step=192; page=1388; upper=133632
		seqroll scroll progress=711; value=0; step=192; page=1388; upper=133632
		seqroll scroll progress=725; value=0; step=192; page=1388; upper=133632

# vim: sw=4 ts=4 wm=8 et ft=sh
