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:
parent
59e6694405
commit
3131ab8bbd
@ -1882,12 +1882,25 @@ ARDOUR_UI::transport_roll ()
|
||||
bool rolling = _session->transport_rolling();
|
||||
|
||||
if (_session->get_play_loop()) {
|
||||
|
||||
/* 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_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);
|
||||
|
||||
} else {
|
||||
_session->request_play_loop (false);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
} else {
|
||||
_session->request_play_loop (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);
|
||||
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);
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -1358,6 +1358,16 @@ 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));
|
||||
|
||||
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 (
|
||||
|
@ -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)
|
||||
|
@ -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 ();
|
||||
|
@ -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:
|
||||
|
@ -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,15 +172,45 @@ 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()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -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,9 +620,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
||||
*/
|
||||
|
||||
if (ptw & PostTransportClearSubstate) {
|
||||
_play_range = false;
|
||||
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,13 +817,25 @@ 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
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user