Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
Paul Davis | 71b378e06a | |
Paul Davis | 90e1e37c31 | |
Paul Davis | c1a12a7efd | |
Paul Davis | 594f453093 | |
Paul Davis | f1151118cc | |
Paul Davis | ef3a9daa72 | |
Paul Davis | f11d919c3b | |
Paul Davis | a257fb6602 | |
Paul Davis | e40635b4b9 | |
Paul Davis | fc685ceb2b | |
Paul Davis | 98743d510e | |
Paul Davis | 18d9ee69ca | |
Paul Davis | 7041b04c69 |
|
@ -2080,17 +2080,26 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
|
|||
if (rolling && roll_out_of_bounded_mode) {
|
||||
/* drop out of loop/range playback but leave transport rolling */
|
||||
if (_session->get_play_loop()) {
|
||||
if (Config->get_seamless_loop()) {
|
||||
/* the disk buffers contain copies of the loop - we can't
|
||||
just keep playing, so stop the transport. the user
|
||||
can restart as they wish.
|
||||
*/
|
||||
affect_transport = true;
|
||||
if (_session->actively_recording()) {
|
||||
|
||||
/* just stop using the loop, then actually stop
|
||||
* below
|
||||
*/
|
||||
_session->request_play_loop (false, affect_transport);
|
||||
|
||||
} else {
|
||||
/* disk buffers are normal, so we can keep playing */
|
||||
affect_transport = false;
|
||||
if (Config->get_seamless_loop()) {
|
||||
/* the disk buffers contain copies of the loop - we can't
|
||||
just keep playing, so stop the transport. the user
|
||||
can restart as they wish.
|
||||
*/
|
||||
affect_transport = true;
|
||||
} else {
|
||||
/* disk buffers are normal, so we can keep playing */
|
||||
affect_transport = false;
|
||||
}
|
||||
_session->request_play_loop (false, affect_transport);
|
||||
}
|
||||
_session->request_play_loop (false, affect_transport);
|
||||
} else if (_session->get_play_range ()) {
|
||||
affect_transport = false;
|
||||
_session->request_play_range (0, true);
|
||||
|
|
|
@ -197,6 +197,7 @@ AudioClock::set_font (Pango::FontDescription font)
|
|||
|
||||
tmp->set_text ("8");
|
||||
tmp->get_pixel_size (em_width, ignore_height);
|
||||
|
||||
|
||||
/* force redraw of markup with new font-size */
|
||||
set (last_when, true);
|
||||
|
@ -312,15 +313,80 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
|
|||
double lw = layout_width * xscale;
|
||||
double lh = layout_height * yscale;
|
||||
|
||||
cairo_move_to (cr, (get_width() - lw) / 2.0, (upper_height - lh) / 2.0);
|
||||
double layout_x_offset;
|
||||
double layout_y_offset = (upper_height - lh) / 2.0;
|
||||
|
||||
if (lw >= get_width()) {
|
||||
layout_x_offset = 0.0;
|
||||
} else {
|
||||
layout_x_offset = get_width() - lw;
|
||||
}
|
||||
|
||||
/* convert these back to unscaled units since we're going to use cairo
|
||||
scaling for a bit.
|
||||
*/
|
||||
|
||||
layout_x_offset /= xscale;
|
||||
layout_y_offset /= xscale;
|
||||
|
||||
if (xscale != 1.0 || yscale != 1.0) {
|
||||
cairo_save (cr);
|
||||
cairo_scale (cr, xscale, yscale);
|
||||
}
|
||||
|
||||
|
||||
/* show the actual clock layout */
|
||||
|
||||
cairo_move_to (cr, layout_x_offset, layout_y_offset);
|
||||
pango_cairo_show_layout (cr, _layout->gobj());
|
||||
|
||||
if (editing) {
|
||||
Pango::Rectangle cursor;
|
||||
const double scaled_x_half_pixel = 0.5/xscale;
|
||||
const double scaled_y_half_pixel = 0.5/yscale;
|
||||
|
||||
if (!insert_map.empty()) {
|
||||
|
||||
if (input_string.length() < insert_map.size()) {
|
||||
|
||||
cursor = _layout->get_cursor_strong_pos (edit_string.length() - 1);
|
||||
|
||||
cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
|
||||
cairo_set_line_width (cr, (1.0/xscale));
|
||||
|
||||
cairo_rectangle (cr,
|
||||
layout_x_offset + (cursor.get_x()/PANGO_SCALE) + scaled_x_half_pixel,
|
||||
layout_y_offset + scaled_y_half_pixel,
|
||||
em_width,
|
||||
layout_height - (1.0/yscale));
|
||||
cairo_stroke (cr);
|
||||
|
||||
} else {
|
||||
/* we've entered all possible digits, no cursor */
|
||||
}
|
||||
|
||||
} else {
|
||||
cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
|
||||
|
||||
if (edit_string.empty()) {
|
||||
cairo_rectangle (cr,
|
||||
layout_x_offset + get_width() - em_width + scaled_x_half_pixel,
|
||||
layout_y_offset + scaled_y_half_pixel,
|
||||
em_width,
|
||||
upper_height - layout_y_offset - (1.0/yscale));
|
||||
} else {
|
||||
cursor = _layout->get_cursor_strong_pos (edit_string.length() - 1);
|
||||
cairo_rectangle (cr,
|
||||
layout_x_offset + (cursor.get_x()/PANGO_SCALE) + scaled_x_half_pixel,
|
||||
layout_y_offset + scaled_y_half_pixel,
|
||||
em_width,
|
||||
upper_height - layout_y_offset - (1.0/yscale));
|
||||
}
|
||||
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (xscale != 1.0 || yscale != 1.0) {
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
@ -400,45 +466,6 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
|
|||
}
|
||||
}
|
||||
|
||||
if (editing) {
|
||||
if (!insert_map.empty()) {
|
||||
|
||||
int xcenter = (get_width() - layout_width) /2;
|
||||
|
||||
if (input_string.length() < insert_map.size()) {
|
||||
Pango::Rectangle cursor;
|
||||
|
||||
if (input_string.empty()) {
|
||||
/* nothing entered yet, put cursor at the end
|
||||
of string
|
||||
*/
|
||||
cursor = _layout->get_cursor_strong_pos (edit_string.length() - 1);
|
||||
} else {
|
||||
cursor = _layout->get_cursor_strong_pos (insert_map[input_string.length()]);
|
||||
}
|
||||
|
||||
cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
|
||||
cairo_rectangle (cr,
|
||||
min (get_width() - 2.0,
|
||||
(double) xcenter + cursor.get_x()/PANGO_SCALE + em_width),
|
||||
(upper_height - layout_height)/2.0,
|
||||
2.0, cursor.get_height()/PANGO_SCALE);
|
||||
cairo_fill (cr);
|
||||
} else {
|
||||
/* we've entered all possible digits, no cursor */
|
||||
}
|
||||
|
||||
} else {
|
||||
if (input_string.empty()) {
|
||||
cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
|
||||
cairo_rectangle (cr,
|
||||
(get_width()/2.0),
|
||||
(upper_height - layout_height)/2.0,
|
||||
2.0, upper_height);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -471,14 +498,21 @@ AudioClock::set_clock_dimensions (Gtk::Requisition& req)
|
|||
tmp->set_font_description (font);
|
||||
|
||||
/* this string is the longest thing we will ever display */
|
||||
if (_mode == MinSec)
|
||||
tmp->set_text (" 88:88:88,888 ");
|
||||
else
|
||||
tmp->set_text (" 88:88:88,88 ");
|
||||
tmp->set_text (" 88:88:88,888 ");
|
||||
tmp->get_pixel_size (req.width, req.height);
|
||||
|
||||
layout_height = req.height;
|
||||
layout_width = req.width;
|
||||
|
||||
/* get the figure width for the font. This doesn't have to super
|
||||
* accurate since we only use it to measure the (roughly 1 character)
|
||||
* offset from the position Pango tells us for the "cursor"
|
||||
*/
|
||||
|
||||
int ignore_height;
|
||||
|
||||
tmp->set_text ("8");
|
||||
tmp->get_pixel_size (em_width, ignore_height);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1419,7 +1453,10 @@ AudioClock::on_key_press_event (GdkEventKey* ev)
|
|||
goto use_input_string;
|
||||
|
||||
default:
|
||||
return false;
|
||||
/* do not allow other keys to passthru to the rest of the GUI
|
||||
when editing.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!insert_map.empty() && (input_string.length() >= insert_map.size())) {
|
||||
|
|
|
@ -1457,7 +1457,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
void set_loop_from_selection (bool play);
|
||||
void set_punch_from_selection ();
|
||||
void set_punch_from_region ();
|
||||
void set_punch_from_loop ();
|
||||
|
||||
void setup_loop_record ();
|
||||
|
||||
void set_session_start_from_playhead ();
|
||||
void set_session_end_from_playhead ();
|
||||
void set_session_extents_from_selection ();
|
||||
|
@ -1684,7 +1687,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
|||
void marker_context_menu (GdkEventButton*, ArdourCanvas::Item*);
|
||||
void tempo_or_meter_marker_context_menu (GdkEventButton*, ArdourCanvas::Item*);
|
||||
void new_transport_marker_context_menu (GdkEventButton*, ArdourCanvas::Item*);
|
||||
void build_range_marker_menu (bool, bool);
|
||||
void build_range_marker_menu (bool, bool, bool);
|
||||
void build_marker_menu (ARDOUR::Location *);
|
||||
void build_tempo_or_meter_marker_menu (bool);
|
||||
void build_new_transport_marker_menu ();
|
||||
|
|
|
@ -306,6 +306,9 @@ Editor::register_actions ()
|
|||
reg_sens (editor_actions, "set-punch-from-edit-range", _("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection));
|
||||
reg_sens (editor_actions, "set-session-from-edit-range", _("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection));
|
||||
|
||||
reg_sens (editor_actions, "set-punch-from-loop", _("Set Punch from Loop"), sigc::mem_fun(*this, &Editor::set_punch_from_loop));
|
||||
reg_sens (editor_actions, "setup-loop-record", _("Setup Loop Record"), sigc::mem_fun(*this, &Editor::setup_loop_record));
|
||||
|
||||
/* this is a duplicated action so that the main menu can use a different label */
|
||||
reg_sens (editor_actions, "main-menu-play-selected-regions", _("Play Selected Regions"), sigc::mem_fun (*this, &Editor::play_selected_region));
|
||||
reg_sens (editor_actions, "play-from-edit-point", _("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point));
|
||||
|
|
|
@ -827,7 +827,7 @@ Editor::marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
|
|||
if (loc == transport_loop_location() || loc == transport_punch_location() || loc->is_session_range ()) {
|
||||
|
||||
if (transport_marker_menu == 0) {
|
||||
build_range_marker_menu (loc == transport_loop_location() || loc == transport_punch_location(), loc->is_session_range());
|
||||
build_range_marker_menu (loc == transport_loop_location(), loc == transport_punch_location(), loc->is_session_range());
|
||||
}
|
||||
|
||||
marker_menu_item = item;
|
||||
|
@ -857,7 +857,7 @@ Editor::marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
|
|||
|
||||
} else if (loc->is_range_marker()) {
|
||||
if (range_marker_menu == 0) {
|
||||
build_range_marker_menu (false, false);
|
||||
build_range_marker_menu (false, false, false);
|
||||
}
|
||||
marker_menu_item = item;
|
||||
range_marker_menu->popup (1, ev->time);
|
||||
|
@ -915,11 +915,11 @@ Editor::build_marker_menu (Location* loc)
|
|||
}
|
||||
|
||||
void
|
||||
Editor::build_range_marker_menu (bool loop_or_punch, bool session)
|
||||
Editor::build_range_marker_menu (bool loop, bool punch, bool session)
|
||||
{
|
||||
using namespace Menu_Helpers;
|
||||
|
||||
bool const loop_or_punch_or_session = loop_or_punch | session;
|
||||
bool const loop_or_punch_or_session = loop | punch | session;
|
||||
|
||||
Menu *markerMenu = new Menu;
|
||||
if (loop_or_punch_or_session) {
|
||||
|
@ -933,7 +933,12 @@ Editor::build_range_marker_menu (bool loop_or_punch, bool session)
|
|||
items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::marker_menu_play_range)));
|
||||
items.push_back (MenuElem (_("Locate to Marker"), sigc::mem_fun(*this, &Editor::marker_menu_set_playhead)));
|
||||
items.push_back (MenuElem (_("Play from Marker"), sigc::mem_fun(*this, &Editor::marker_menu_play_from)));
|
||||
items.push_back (MenuElem (_("Loop Range"), sigc::mem_fun(*this, &Editor::marker_menu_loop_range)));
|
||||
|
||||
if (!loop) {
|
||||
items.push_back (MenuElem (_("Loop Range"), sigc::mem_fun(*this, &Editor::marker_menu_loop_range)));
|
||||
} else {
|
||||
items.push_back (MenuElem (_("Setup Loop Record"), sigc::mem_fun(*this, &Editor::setup_loop_record)));
|
||||
}
|
||||
|
||||
items.push_back (MenuElem (_("Set Marker from Playhead"), sigc::mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
|
||||
if (!Profile->get_sae()) {
|
||||
|
|
|
@ -6265,6 +6265,60 @@ Editor::set_punch_from_selection ()
|
|||
set_punch_range (start, end, _("set punch range from selection"));
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_punch_from_loop ()
|
||||
{
|
||||
if (_session == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location* tll;
|
||||
|
||||
if ((tll = transport_loop_location()) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_punch_range (tll->start(), tll->end(), _("set punch range from loop"));
|
||||
}
|
||||
|
||||
void
|
||||
Editor::setup_loop_record ()
|
||||
{
|
||||
if (_session == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location * looploc = _session->locations()->auto_loop_location();
|
||||
|
||||
if (!looploc) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_punch_range (looploc->start(), looploc->end(), _("setup loop recording"));
|
||||
|
||||
Glib::RefPtr<Action> action = ActionManager::get_action ("Transport", "TogglePunch");
|
||||
|
||||
if (action) {
|
||||
|
||||
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(action);
|
||||
|
||||
if (!tact) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* drive the other two actions from this one */
|
||||
|
||||
Glib::RefPtr<Action> in_action = ActionManager::get_action ("Transport", "TogglePunchIn");
|
||||
Glib::RefPtr<Action> out_action = ActionManager::get_action ("Transport", "TogglePunchOut");
|
||||
|
||||
if (in_action && out_action) {
|
||||
Glib::RefPtr<ToggleAction> tiact = Glib::RefPtr<ToggleAction>::cast_dynamic(in_action);
|
||||
Glib::RefPtr<ToggleAction> toact = Glib::RefPtr<ToggleAction>::cast_dynamic(out_action);
|
||||
tiact->set_active (true);
|
||||
toact->set_active (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
Editor::set_session_extents_from_selection ()
|
||||
{
|
||||
|
|
|
@ -1817,7 +1817,7 @@ Session::disable_record (bool rt_context, bool force)
|
|||
|
||||
if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
|
||||
|
||||
if ((!Config->get_latched_record_enable () && !play_loop) || force) {
|
||||
if (!Config->get_latched_record_enable () || force) {
|
||||
g_atomic_int_set (&_record_status, Disabled);
|
||||
send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
|
||||
} else {
|
||||
|
@ -1868,11 +1868,6 @@ Session::maybe_enable_record ()
|
|||
|
||||
save_state ("", true);
|
||||
|
||||
if (Config->get_loop_is_mode()) {
|
||||
/* makes no sense to use loop play as mode when recording */
|
||||
request_play_loop (false);
|
||||
}
|
||||
|
||||
if (_transport_speed) {
|
||||
if (!config.get_punch_in()) {
|
||||
enable_record ();
|
||||
|
|
|
@ -283,6 +283,10 @@ Session::realtime_stop (bool abort, bool clear_state)
|
|||
/* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
|
||||
disable_record (true, (!Config->get_latched_record_enable() && clear_state));
|
||||
|
||||
if (clear_state && !Config->get_loop_is_mode()) {
|
||||
unset_play_loop ();
|
||||
}
|
||||
|
||||
reset_slave_state ();
|
||||
|
||||
_transport_speed = 0;
|
||||
|
@ -1108,8 +1112,8 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
|
|||
*/
|
||||
|
||||
bool transport_was_stopped = !transport_rolling();
|
||||
|
||||
if (transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
|
||||
|
||||
if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
|
||||
(!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
|
||||
realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
|
||||
transport_was_stopped = true;
|
||||
|
@ -1163,7 +1167,7 @@ Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool
|
|||
Location* al = _locations->auto_loop_location();
|
||||
|
||||
if (al) {
|
||||
if (_transport_frame < al->start() || _transport_frame > al->end()) {
|
||||
if (_transport_frame < al->start() || _transport_frame >= al->end()) {
|
||||
|
||||
// located outside the loop: cancel looping directly, this is called from event handling context
|
||||
|
||||
|
@ -1299,10 +1303,6 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, 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 */
|
||||
|
@ -1429,6 +1429,8 @@ Session::stop_transport (bool abort, bool clear_state)
|
|||
return;
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
|
||||
|
||||
if (!get_transport_declick_required()) {
|
||||
|
||||
/* stop has not yet been scheduled */
|
||||
|
@ -1481,8 +1483,8 @@ Session::stop_transport (bool abort, bool clear_state)
|
|||
/* Not recording, schedule a declick in the next process() cycle and then stop at its end */
|
||||
|
||||
new_bits = PendingDeclickOut;
|
||||
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
|
||||
}
|
||||
|
||||
|
||||
/* we'll be called again after the declick */
|
||||
transport_sub_state = SubState (transport_sub_state|new_bits);
|
||||
|
@ -1491,6 +1493,8 @@ Session::stop_transport (bool abort, bool clear_state)
|
|||
return;
|
||||
|
||||
} else {
|
||||
|
||||
DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
|
||||
|
||||
/* declick was scheduled, but we've been called again, which means it is really time to stop
|
||||
|
||||
|
|
Loading…
Reference in New Issue