13
0

new transport option, "loop-is-mode" which optionally changes the role of the "play loop" button.

If enabled, then the button simply changes the behaviour of the "play" button rather than actually starting playback. If disabled
transport behaviour should be unchanged from before.
This commit is contained in:
Paul Davis 2014-04-17 09:47:06 -04:00
parent 59e6694405
commit 3131ab8bbd
7 changed files with 145 additions and 36 deletions

View File

@ -1882,12 +1882,25 @@ ARDOUR_UI::transport_roll ()
bool rolling = _session->transport_rolling();
if (_session->get_play_loop()) {
/* XXX it is not possible to just leave seamless loop and keep
playing at present (nov 4th 2009)
/* If loop playback is not a mode, then we should cancel
it when this action is requested. If it is a mode
we just leave it in place.
*/
if (!Config->get_seamless_loop()) {
_session->request_play_loop (false, true);
}
if (!Config->get_loop_is_mode()) {
/* XXX it is not possible to just leave seamless loop and keep
playing at present (nov 4th 2009)
*/
if (!Config->get_seamless_loop()) {
/* stop loop playback and stop rolling */
_session->request_play_loop (false, true);
} else if (rolling) {
/* stop loop playback but keep rolling */
_session->request_play_loop (false, false);
}
}
} else if (_session->get_play_range () && !Config->get_always_play_range()) {
/* stop playing a range if we currently are */
_session->request_play_range (0, true);
@ -1944,7 +1957,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
/* disk buffers are normal, so we can keep playing */
affect_transport = false;
}
_session->request_play_loop (false, true);
_session->request_play_loop (false, affect_transport);
} else if (_session->get_play_range ()) {
affect_transport = false;
_session->request_play_range (0, true);
@ -1975,16 +1988,23 @@ ARDOUR_UI::toggle_session_auto_loop ()
if (_session->get_play_loop()) {
if (_session->transport_rolling()) {
/* looping enabled, our job is to disable it */
_session->request_locate (looploc->start(), true);
_session->request_play_loop (false);
_session->request_play_loop (false);
} else {
_session->request_play_loop (false);
}
} else {
_session->request_play_loop (true);
/* looping not enabled, our job is to enable it.
loop-is-NOT-mode: this action always starts the transport rolling.
loop-IS-mode: this action simply sets the loop play mechanism, but
does not start transport.
*/
if (Config->get_loop_is_mode()) {
_session->request_play_loop (true, false);
} else {
_session->request_play_loop (true, true);
}
}
//show the loop markers
@ -2112,7 +2132,11 @@ ARDOUR_UI::map_transport_state ()
auto_loop_button.set_active (true);
play_selection_button.set_active (false);
roll_button.set_active (false);
if (Config->get_loop_is_mode()) {
roll_button.set_active (true);
} else {
roll_button.set_active (false);
}
} else {
@ -2134,7 +2158,11 @@ ARDOUR_UI::map_transport_state ()
stop_button.set_active (true);
roll_button.set_active (false);
play_selection_button.set_active (false);
auto_loop_button.set_active (false);
if (Config->get_loop_is_mode ()) {
auto_loop_button.set_active (_session->get_play_loop());
} else {
auto_loop_button.set_active (false);
}
update_disk_space ();
}
}

View File

@ -1434,6 +1434,12 @@ AudioRegionView::set_one_waveform_color (ArdourCanvas::WaveView* wave)
ArdourCanvas::color_to_rgba (fill, r, g, b, a);
fill = ArdourCanvas::rgba_to_color (r, g, b, 0.85); /* magic number, not user controllable */
outline = ARDOUR_UI::config()->get_canvasvar_WaveForm();
if (!Config->get_show_name_highlight()) {
/* recolor name text because it needs to contrast with
the waveform background, not the name highlight.
*/
}
}
wave->set_fill_color (fill);

View File

@ -1358,8 +1358,18 @@ RCOptionEditor::RCOptionEditor ()
Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
PROGRAM_NAME));
add_option (_("Transport"), tsf);
tsf = new BoolOption (
"loop-is-mode",
_("Play loop is a transport mode"),
sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
);
Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
(_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
"<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
add_option (_("Transport"), tsf);
tsf = new BoolOption (
"create-xrun-marker",
_("Create markers where xruns occur"),

View File

@ -133,6 +133,7 @@ CONFIG_VARIABLE (bool, stop_recording_on_xrun, "stop-recording-on-xrun", false)
CONFIG_VARIABLE (bool, create_xrun_marker, "create-xrun-marker", true)
CONFIG_VARIABLE (bool, stop_at_session_end, "stop-at-session-end", false)
CONFIG_VARIABLE (bool, seamless_loop, "seamless-loop", false)
CONFIG_VARIABLE (bool, loop_is_mode, "loop-is-mode", false)
CONFIG_VARIABLE (framecnt_t, preroll, "preroll", 0)
CONFIG_VARIABLE (framecnt_t, postroll, "postroll", 0)
CONFIG_VARIABLE (float, rf_speed, "rf-speed", 2.0f)

View File

@ -1262,7 +1262,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
int start_midi_thread ();
void set_play_loop (bool yn);
void set_play_loop (bool yn, double speed);
void unset_play_loop ();
void overwrite_some_buffers (Track *);
void flush_all_inserts ();

View File

@ -1010,7 +1010,7 @@ Session::process_event (SessionEvent* ev)
switch (ev->type) {
case SessionEvent::SetLoop:
set_play_loop (ev->yes_or_no);
set_play_loop (ev->yes_or_no, ev->speed);
break;
case SessionEvent::AutoLoop:

View File

@ -30,6 +30,7 @@
#include "pbd/enumwriter.h"
#include "pbd/pthread_utils.h"
#include "pbd/memento_command.h"
#include "pbd/stacktrace.h"
#include "midi++/mmc.h"
#include "midi++/port.h"
@ -40,6 +41,7 @@
#include "ardour/click.h"
#include "ardour/debug.h"
#include "ardour/location.h"
#include "ardour/profile.h"
#include "ardour/session.h"
#include "ardour/slave.h"
#include "ardour/operations.h"
@ -158,10 +160,11 @@ Session::force_locate (framepos_t target_frame, bool with_roll)
}
void
Session::request_play_loop (bool yn, bool leave_rolling)
Session::request_play_loop (bool yn, bool change_transport_roll)
{
SessionEvent* ev;
Location *location = _locations->auto_loop_location();
double target_speed;
if (location == 0 && yn) {
error << _("Cannot loop - no loop range defined")
@ -169,14 +172,44 @@ Session::request_play_loop (bool yn, bool leave_rolling)
return;
}
ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
if (change_transport_roll) {
if (transport_rolling()) {
/* start looping at current speed */
target_speed = transport_speed ();
} else {
/* currently stopped */
if (yn) {
/* start looping at normal speed */
target_speed = 1.0;
} else {
target_speed = 0.0;
}
}
} else {
/* leave the speed alone */
target_speed = transport_speed ();
}
ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
queue_event (ev);
if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
// request an immediate locate to refresh the tracks
// after disabling looping
request_locate (_transport_frame-1, false);
if (yn) {
if (!change_transport_roll) {
if (!transport_rolling()) {
/* we're not changing transport state, but we do want
to set up position for the new loop. Don't
do this if we're rolling already.
*/
request_locate (location->start(), false);
}
}
} else {
if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
// request an immediate locate to refresh the tracks
// after disabling looping
request_locate (_transport_frame-1, false);
}
}
}
@ -531,8 +564,6 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
/* explicit return request pre-queued in event list. overrides everything else */
cerr << "explicit auto-return to " << _requested_return_frame << endl;
_transport_frame = _requested_return_frame;
do_locate = true;
@ -589,8 +620,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
*/
if (ptw & PostTransportClearSubstate) {
_play_range = false;
unset_play_loop ();
unset_play_range ();
if (!Config->get_loop_is_mode()) {
unset_play_loop ();
}
}
/* this for() block can be put inside the previous if() and has the effect of ... ??? what */
@ -657,8 +690,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
}
if (ptw & PostTransportStop) {
_play_range = false;
play_loop = false;
unset_play_range ();
if (!Config->get_loop_is_mode()) {
unset_play_loop ();
}
}
PositionChanged (_transport_frame); /* EMIT SIGNAL */
@ -723,7 +758,7 @@ Session::unset_play_loop ()
}
void
Session::set_play_loop (bool yn)
Session::set_play_loop (bool yn, double speed)
{
/* Called from event-handling context */
@ -782,12 +817,24 @@ Session::set_play_loop (bool yn)
merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
/* locate to start of loop and roll.
/* if requested to roll, locate to start of loop and
* roll but ONLY if we're not already rolling.
args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
*/
start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
if (Config->get_loop_is_mode()) {
/* loop IS a transport mode: if already
rolling, do not locate to loop start.
*/
if (!transport_rolling() && (speed != 0.0)) {
start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
}
} else {
if (speed != 0.0) {
start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
}
}
}
} else {
@ -983,7 +1030,9 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
// located outside the loop: cancel looping directly, this is called from event handling context
set_play_loop (false);
if (!Config->get_loop_is_mode()) {
set_play_loop (false, _transport_speed);
}
} else if (_transport_frame == al->start()) {
@ -1080,12 +1129,27 @@ Session::set_transport_speed (double speed, bool abort, bool clear_state, bool a
stop_transport (abort);
}
unset_play_loop ();
if (!Config->get_loop_is_mode()) {
unset_play_loop ();
}
} else if (transport_stopped() && speed == 1.0) {
/* we are stopped and we want to start rolling at speed 1 */
if (Config->get_loop_is_mode() && play_loop) {
Location *location = _locations->auto_loop_location();
if (location != 0) {
if (_transport_frame != location->start()) {
/* jump to start and then roll from there */
request_locate (location->start(), true);
return;
}
}
}
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
set_track_monitor_input_status (false);
}