large-scale refactoring of Pianoroll, CueEditor and AudioClipEditor

Enables code-sharing between "clip editors"
This commit is contained in:
Paul Davis 2025-07-29 14:55:46 -06:00
parent 81ca93bdfb
commit 1d4e3940d1
24 changed files with 2673 additions and 2668 deletions

View file

@ -2251,6 +2251,9 @@ ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
return ret;
}
std::string rus_path = Glib::build_filename (_session->session_directory().root_path(), "rus.xml");
region_ui_settings_manager.save (rus_path);
}
save_ardour_state (); /* XXX cannot fail? yeah, right ... */

View file

@ -89,6 +89,7 @@
#include "ardour_window.h"
#include "editing.h"
#include "enums.h"
#include "region_ui_settings.h"
#include "shuttle_control.h"
#include "startup_fsm.h"
#include "transport_control.h"
@ -419,6 +420,8 @@ public:
void gui_idle_handler ();
RegionUISettingsManager region_ui_settings_manager;
protected:
friend class PublicEditor;

View file

@ -88,7 +88,6 @@ ARDOUR_UI::we_have_dependents ()
mixer->monitor_section().use_others_actions ();
StepEntry::setup_actions_and_bindings ();
ClipEditorBox::init ();
RegionEditor::setup_actions_and_bindings ();
setup_action_tooltips ();

View file

@ -80,6 +80,7 @@ ARDOUR_UI::audioengine_became_silent ()
pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/subscribe")));
msg.get_vbox()->pack_start (pay_label);
msg.get_vbox()->pack_start (pay_button_box);
msg.get_vbox()->pack_start (subscribe_label);

View file

@ -599,6 +599,15 @@ ARDOUR_UI::load_session_stage_two (const std::string& path, const std::string& s
msg.hide ();
}
{
if (new_session) {
std::string rus_path = Glib::build_filename (new_session->session_directory().root_path(), "rus.xml");
region_ui_settings_manager.load (rus_path);
} else {
region_ui_settings_manager.clear ();
}
}
/* Now the session been created, add the transport controls */
new_session->add_controllable(roll_controllable);
@ -611,6 +620,7 @@ ARDOUR_UI::load_session_stage_two (const std::string& path, const std::string& s
set_session (new_session);
if (_session) {
_session->set_clean ();
}
@ -620,6 +630,7 @@ ARDOUR_UI::load_session_stage_two (const std::string& path, const std::string& s
flush_pending (10);
}
retval = 0;
if (!mix_template.empty ()) {

View file

@ -41,12 +41,16 @@
#include "widgets/ardour_button.h"
#include "widgets/ardour_icon.h"
#include "ardour_ui.h"
#include "audio_clip_editor.h"
#include "audio_clock.h"
#include "editor_automation_line.h"
#include "editor_cursors.h"
#include "editor_drag.h"
#include "control_point.h"
#include "editor.h"
#include "region_view.h"
#include "verbose_cursor.h"
#include "ui_config.h"
#include "pbd/i18n.h"
@ -60,33 +64,11 @@ using namespace ArdourWidgets;
using std::max;
using std::min;
Glib::RefPtr<Gtk::ActionGroup> ClipEditorBox::clip_editor_actions;
void
ClipEditorBox::init ()
{
Bindings* bindings = Bindings::get_bindings (X_("Clip Editing"));
register_clip_editor_actions (bindings);
}
void
ClipEditorBox::register_clip_editor_actions (Bindings* clip_editor_bindings)
{
clip_editor_actions = ActionManager::create_action_group (clip_editor_bindings, X_("ClipEditing"));
/* two versions to allow same action for Delete and Backspace */
// ActionManager::register_action (clip_editor_actions, X_("zoom-in"), _("Zoom In"), sigc::mem_fun (*this, &ClipEditorBox::zoom_in));
// ActionManager::register_action (clip_editor_actions, X_("zoom-in"), _("Zoom In"), sigc::mem_fun (*this, &ClipEditorBox::zoom_out));
}
void
AudioClipEditor::ClipBBTMetric::get_marks (std::vector<ArdourCanvas::Ruler::Mark>& marks, int64_t lower, int64_t upper, int maxchars) const
{
TriggerPtr trigger (tref.trigger());
if (!trigger) {
std::cerr << "No trigger\n";
return;
}
@ -121,46 +103,153 @@ AudioClipEditor::ClipBBTMetric::get_marks (std::vector<ArdourCanvas::Ruler::Mark
}
}
AudioClipEditor::AudioClipEditor ()
: clip_metric (0)
, _spp (0)
AudioClipEditor::AudioClipEditor (std::string const & name, bool with_transport)
: CueEditor (name, with_transport)
, clip_metric (nullptr)
, scroll_fraction (0)
, current_line_drag (0)
, current_scroll_drag (0)
{
const double scale = UIConfiguration::instance ().get_ui_scale ();
build_upper_toolbar ();
build_canvas ();
build_lower_toolbar ();
frame = new ArdourCanvas::Rectangle (root ());
frame->name = "audio clip editor frame";
frame->set_fill (false);
frame->Event.connect (sigc::mem_fun (*this, &AudioClipEditor::event_handler));
load_bindings ();
register_actions ();
/* Scroll bar does not scroll and it outside the frame */
build_grid_type_menu ();
}
scroll_bar_trough = new ArdourCanvas::Rectangle (root ());
scroll_bar_handle = new ArdourCanvas::Rectangle (scroll_bar_trough);
scroll_bar_handle->set_outline (false);
scroll_bar_handle->set_corner_radius (5.);
scroll_bar_handle->Event.connect (sigc::mem_fun (*this, &AudioClipEditor::scroll_event_handler));
scroll_bar_handle->disable_scroll_translation ();
void
AudioClipEditor::load_shared_bindings ()
{
/* Full shared binding loading must have preceded this in some other EditingContext */
assert (!need_shared_actions);
/* A scrolling container for our waves and lines etc. */
Bindings* b = Bindings::get_bindings (X_("Editing"));
waves_container = new ArdourCanvas::ScrollGroup (frame, ScrollGroup::ScrollsHorizontally);
add_scroller (*waves_container);
/* Copy each shared bindings but give them a new name, which will make them refer to actions
* named after this EditingContext (ie. unique to this EC)
*/
ruler_container = new ArdourCanvas::Container (waves_container);
ruler = new ArdourCanvas::Ruler (ruler_container, 0);
ruler->name = "Clip Editor";
ruler->set_font_description (UIConfiguration::instance ().get_SmallerFont ());
ruler->set_fill_color (UIConfiguration::instance().color (X_("theme:bg1")));
ruler->set_outline_color (UIConfiguration::instance().color (X_("theme:contrasting less")));
Bindings* shared_bindings = new Bindings (editor_name(), *b);
register_common_actions (shared_bindings, editor_name());
shared_bindings->associate ();
/* Attach bindings to the canvas for this editing context */
bindings.push_back (shared_bindings);
}
void
AudioClipEditor::pack_inner (Gtk::Box& box)
{
box.pack_start (snap_box, false, false);
box.pack_start (grid_box, false, false);
}
void
AudioClipEditor::pack_outer (Gtk::Box& box)
{
if (with_transport_controls) {
box.pack_start (play_box, false, false);
}
std::cerr << "pack up rec box\n";
box.pack_start (rec_box, false, false);
box.pack_start (follow_playhead_button, false, false);
}
void
AudioClipEditor::build_lower_toolbar ()
{
_toolbox.pack_start (*_canvas_hscrollbar, false, false);
}
void
AudioClipEditor::build_canvas ()
{
_canvas.set_background_color (UIConfiguration::instance().color ("arrange base"));
_canvas.signal_event().connect (sigc::mem_fun (*this, &CueEditor::canvas_pre_event), false);
_canvas.use_nsglview (UIConfiguration::instance().get_nsgl_view_mode () == NSGLHiRes);
_canvas.PreRender.connect (sigc::mem_fun(*this, &EditingContext::pre_render));
/* scroll group for items that should not automatically scroll
* (e.g verbose cursor). It shares the canvas coordinate space.
*/
no_scroll_group = new ArdourCanvas::Container (_canvas.root());
h_scroll_group = new ArdourCanvas::ScrollGroup (_canvas.root(), ArdourCanvas::ScrollGroup::ScrollsHorizontally);
CANVAS_DEBUG_NAME (h_scroll_group, "audioclip h scroll");
_canvas.add_scroller (*h_scroll_group);
v_scroll_group = new ArdourCanvas::ScrollGroup (_canvas.root(), ArdourCanvas::ScrollGroup::ScrollsVertically);
CANVAS_DEBUG_NAME (v_scroll_group, "audioclip v scroll");
_canvas.add_scroller (*v_scroll_group);
hv_scroll_group = new ArdourCanvas::ScrollGroup (_canvas.root(),
ArdourCanvas::ScrollGroup::ScrollSensitivity (ArdourCanvas::ScrollGroup::ScrollsVertically|
ArdourCanvas::ScrollGroup::ScrollsHorizontally));
CANVAS_DEBUG_NAME (hv_scroll_group, "audioclip hv scroll");
_canvas.add_scroller (*hv_scroll_group);
cursor_scroll_group = new ArdourCanvas::ScrollGroup (_canvas.root(), ArdourCanvas::ScrollGroup::ScrollsHorizontally);
CANVAS_DEBUG_NAME (cursor_scroll_group, "audioclip cursor scroll");
_canvas.add_scroller (*cursor_scroll_group);
/*a group to hold global rects like punch/loop indicators */
global_rect_group = new ArdourCanvas::Container (hv_scroll_group);
CANVAS_DEBUG_NAME (global_rect_group, "audioclip global rect group");
transport_loop_range_rect = new ArdourCanvas::Rectangle (global_rect_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, ArdourCanvas::COORD_MAX));
CANVAS_DEBUG_NAME (transport_loop_range_rect, "audioclip loop rect");
transport_loop_range_rect->hide();
/*a group to hold time (measure) lines */
time_line_group = new ArdourCanvas::Container (h_scroll_group);
CANVAS_DEBUG_NAME (time_line_group, "audioclip time line group");
n_timebars = 0;
minsec_ruler = new ArdourCanvas::Ruler (time_line_group, clip_metric, ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height));
// minsec_ruler->set_name ("audio clip editor ruler");
minsec_ruler->set_font_description (UIConfiguration::instance ().get_SmallerFont ());
minsec_ruler->set_fill_color (UIConfiguration::instance().color (X_("theme:bg1")));
minsec_ruler->set_outline_color (UIConfiguration::instance().color (X_("theme:contrasting less")));
n_timebars++;
minsec_ruler->Event.connect (sigc::mem_fun (*this, &CueEditor::ruler_event));
data_group = new ArdourCanvas::Container (hv_scroll_group);
CANVAS_DEBUG_NAME (data_group, "cue data group");
data_group->set_position (ArdourCanvas::Duple (_timeline_origin, timebar_height * n_timebars));
no_scroll_group->set_position (ArdourCanvas::Duple (_timeline_origin, timebar_height * n_timebars));
cursor_scroll_group->set_position (ArdourCanvas::Duple (_timeline_origin, timebar_height * n_timebars));
h_scroll_group->set_position (Duple (_timeline_origin, 0.));
_verbose_cursor = new VerboseCursor (*this);
// _playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event, X_("playhead"));
_playhead_cursor = new EditorCursor (*this, X_("playhead"));
_playhead_cursor->set_sensitive (UIConfiguration::instance().get_sensitize_playhead());
_playhead_cursor->set_color (UIConfiguration::instance().color ("play head"));
_playhead_cursor->canvas_item().raise_to_top();
h_scroll_group->raise_to_top ();
_canvas.set_name ("AudioClipCanvas");
_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK | Gdk::SCROLL_MASK | Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
_canvas.set_can_focus ();
_canvas_viewport.signal_size_allocate().connect (sigc::mem_fun(*this, &AudioClipEditor::canvas_allocate), false);
_toolbox.pack_start (_canvas_viewport, true, true);
/* the lines */
line_container = new ArdourCanvas::Container (waves_container);
line_container = new ArdourCanvas::Container (data_group);
CANVAS_DEBUG_NAME (line_container, "audio clip line container");
const double line_width = 3.;
double scale = UIConfiguration::instance().get_ui_scale();
start_line = new Line (line_container);
start_line->set_outline_width (line_width * scale);
@ -222,41 +311,6 @@ AudioClipEditor::line_event_handler (GdkEvent* ev, ArdourCanvas::Line* l)
return false;
}
bool
AudioClipEditor::scroll_event_handler (GdkEvent* ev)
{
switch (ev->type) {
case GDK_BUTTON_PRESS:
current_scroll_drag = new ScrollDrag (*this);
current_scroll_drag->begin (&ev->button);
return true;
case GDK_BUTTON_RELEASE:
if (current_scroll_drag) {
current_scroll_drag->end (&ev->button);
delete current_scroll_drag;
current_scroll_drag = 0;
return true;
}
break;
case GDK_MOTION_NOTIFY:
if (current_scroll_drag) {
current_scroll_drag->motion (&ev->motion);
return true;
}
break;
case GDK_KEY_PRESS:
return key_press (&ev->key);
default:
break;
}
return false;
}
bool
AudioClipEditor::key_press (GdkEventKey* ev)
{
@ -266,27 +320,15 @@ AudioClipEditor::key_press (GdkEventKey* ev)
void
AudioClipEditor::position_lines ()
{
if (!audio_region) {
if (!_region) {
return;
}
start_line->set_x0 (sample_to_pixel (audio_region->start ().samples ()));
start_line->set_x1 (sample_to_pixel (audio_region->start ().samples ()));
start_line->set_x0 (sample_to_pixel (_region->start ().samples ()));
start_line->set_x1 (sample_to_pixel (_region->start ().samples ()));
end_line->set_x0 (sample_to_pixel (audio_region->end ().samples ()));
end_line->set_x1 (sample_to_pixel (audio_region->end ().samples ()));
}
double
AudioClipEditor::sample_to_pixel (samplepos_t s)
{
return round (s / _spp);
}
samplepos_t
AudioClipEditor::pixel_to_sample (double p)
{
return round (p * _spp);
end_line->set_x0 (sample_to_pixel (_region->end ().samples ()));
end_line->set_x1 (sample_to_pixel (_region->end ().samples ()));
}
AudioClipEditor::LineDrag::LineDrag (AudioClipEditor& ed, ArdourCanvas::Line& l)
@ -317,78 +359,15 @@ AudioClipEditor::LineDrag::motion (GdkEventMotion* ev)
void
AudioClipEditor::set_colors ()
{
set_background_color (UIConfiguration::instance ().color (X_("theme:bg")));
frame->set_outline_color (UIConfiguration::instance ().color (X_("neutral:midground")));
_canvas.set_background_color (UIConfiguration::instance ().color (X_("theme:bg")));
start_line->set_outline_color (UIConfiguration::instance ().color (X_("theme:contrasting clock")));
end_line->set_outline_color (UIConfiguration::instance ().color (X_("theme:contrasting alt")));
loop_line->set_outline_color (UIConfiguration::instance ().color (X_("theme:contrasting selection")));
scroll_bar_trough->set_fill_color (UIConfiguration::instance ().color (X_("theme:bg")));
scroll_bar_trough->set_outline_color (UIConfiguration::instance ().color (X_("theme:contrasting less")));
scroll_bar_handle->set_fill_color (UIConfiguration::instance ().color (X_("theme:contrasting clock")));
set_waveform_colors ();
}
void
AudioClipEditor::scroll_changed ()
{
if (!audio_region) {
return;
}
const double right_edge = scroll_bar_handle->get ().x0;
const double avail_width = scroll_bar_trough->get ().width () - scroll_bar_handle->get ().width ();
scroll_fraction = right_edge / avail_width;
scroll_fraction = std::min (1., std::max (0., scroll_fraction));
const samplepos_t s = llrintf (audio_region->source (0)->length ().samples () * scroll_fraction);
ruler->set_range (s, s + pixel_to_sample (frame->get().width() - 2.));
scroll_to (sample_to_pixel (s), 0);
queue_draw ();
}
AudioClipEditor::ScrollDrag::ScrollDrag (AudioClipEditor& e)
: editor (e)
{
e.scroll_bar_handle->grab ();
}
void
AudioClipEditor::ScrollDrag::begin (GdkEventButton* ev)
{
last_x = ev->x;
}
void
AudioClipEditor::ScrollDrag::end (GdkEventButton* ev)
{
editor.scroll_bar_handle->ungrab ();
editor.scroll_changed ();
}
void
AudioClipEditor::ScrollDrag::motion (GdkEventMotion* ev)
{
ArdourCanvas::Rectangle& r (*editor.scroll_bar_handle);
const double xdelta = ev->x - last_x;
ArdourCanvas::Rect n (r.get ());
const double handle_width = n.width ();
const double avail_width = editor.scroll_bar_trough->get ().width () - handle_width;
n.x0 = std::max (0., std::min (avail_width, n.x0 + xdelta));
n.x1 = n.x0 + handle_width;
r.set (n);
last_x = ev->x;
editor.scroll_changed ();
}
void
AudioClipEditor::drop_waves ()
{
@ -400,11 +379,39 @@ AudioClipEditor::drop_waves ()
}
void
AudioClipEditor::set_region (std::shared_ptr<AudioRegion> r, TriggerReference tr)
AudioClipEditor::set_trigger (TriggerReference& tr)
{
if (tr == ref) {
return;
}
CueEditor::set_trigger (tr);
rec_box.show ();
minsec_ruler->show ();
minsec_ruler->set_range (0, pixel_to_sample (_visible_canvas_width - 2.));
}
void
AudioClipEditor::set_region (std::shared_ptr<Region> region)
{
CueEditor::set_region (region);
if (_visible_pending_region) {
return;
}
drop_waves ();
audio_region = r;
if (!region) {
return;
}
std::shared_ptr<AudioRegion> r (std::dynamic_pointer_cast<AudioRegion> (region));
if (!r) {
return;
}
/* Ruler has to reflect tempo of the region, so we have to recreate it
* every time. Note that we retain ownership of the metric, and that
@ -414,8 +421,8 @@ AudioClipEditor::set_region (std::shared_ptr<AudioRegion> r, TriggerReference tr
*/
delete clip_metric;
clip_metric = new ClipBBTMetric (tr);
ruler->set_metric (clip_metric);
clip_metric = new ClipBBTMetric (ref);
minsec_ruler->set_metric (clip_metric);
uint32_t n_chans = r->n_channels ();
samplecnt_t len;
@ -424,6 +431,7 @@ AudioClipEditor::set_region (std::shared_ptr<AudioRegion> r, TriggerReference tr
for (uint32_t n = 0; n < n_chans; ++n) {
std::shared_ptr<Region> wr = RegionFactory::get_whole_region_for_source (r->source (n));
if (!wr) {
continue;
}
@ -433,8 +441,8 @@ AudioClipEditor::set_region (std::shared_ptr<AudioRegion> r, TriggerReference tr
continue;
}
WaveView* wv = new WaveView (waves_container, war);
wv->set_channel (n);
WaveView* wv = new WaveView (data_group, war);
wv->set_channel (0);
wv->set_show_zero_line (false);
wv->set_clip_level (1.0);
wv->lower_to_bottom ();
@ -442,75 +450,56 @@ AudioClipEditor::set_region (std::shared_ptr<AudioRegion> r, TriggerReference tr
waves.push_back (wv);
}
TriggerPtr trigger (tr.trigger());
std::shared_ptr<AudioTrigger> at = std::dynamic_pointer_cast<AudioTrigger> (trigger);
if (at) {
if (at->segment_tempo() == 0.) {
/* tempo unknown, hide ruler */
ruler->hide ();
} else {
ruler->show ();
ruler->set_range (0, pixel_to_sample (frame->get().width() - 2.));
}
} else {
ruler->hide ();
}
set_spp_from_length (len);
set_wave_heights ();
set_waveform_colors ();
line_container->show ();
line_container->raise_to_top ();
set_session (&r->session ());
state_connection.disconnect ();
PBD::PropertyChange interesting_stuff;
region_changed (interesting_stuff);
region->PropertyChanged.connect (state_connection, invalidator (*this), std::bind (&AudioClipEditor::region_changed, this, _1), gui_context ());
maybe_set_from_rsu ();
}
void
AudioClipEditor::on_size_allocate (Gtk::Allocation& alloc)
AudioClipEditor::canvas_allocate (Gtk::Allocation& alloc)
{
GtkCanvas::on_size_allocate (alloc);
_canvas.size_allocate (alloc);
ArdourCanvas::Rect r (1, 1, alloc.get_width () - 2, alloc.get_height () - 2);
frame->set (r);
_visible_canvas_width = alloc.get_width();
_visible_canvas_height = alloc.get_height();
const double ruler_height = 25.;
ruler->set (ArdourCanvas::Rect (2, 2, alloc.get_width() - 4, ruler_height));
/* no track header here, "track width" is the whole canvas */
_track_canvas_width = _visible_canvas_width;
const double scroll_bar_height = 10.;
const double scroll_bar_width = alloc.get_width () - 2;
const double scroll_bar_handle_left = scroll_bar_width * scroll_fraction;
scroll_bar_trough->set (ArdourCanvas::Rect (1, alloc.get_height () - scroll_bar_height, scroll_bar_width, alloc.get_height ()));
scroll_bar_handle->set (ArdourCanvas::Rect (scroll_bar_handle_left, scroll_bar_trough->get ().y0 + 1, scroll_bar_handle_left + 30., scroll_bar_trough->get ().y1 - 1));
minsec_ruler->set (ArdourCanvas::Rect (2, 2, alloc.get_width() - 4, timebar_height));
position_lines ();
start_line->set_y1 (frame->get ().height () - 2. - scroll_bar_height);
end_line->set_y1 (frame->get ().height () - 2. - scroll_bar_height);
loop_line->set_y1 (frame->get ().height () - 2. - scroll_bar_height);
start_line->set_y1 (_visible_canvas_height - 2.);
end_line->set_y1 (_visible_canvas_height - 2.);
loop_line->set_y1 (_visible_canvas_height - 2.);
set_wave_heights ();
}
void
AudioClipEditor::set_spp (double samples_per_pixel)
{
_spp = samples_per_pixel;
catch_pending_show_region ();
clip_metric->units_per_pixel = _spp;
position_lines ();
for (auto& wave : waves) {
wave->set_samples_per_pixel (_spp);
}
update_grid ();
}
void
AudioClipEditor::set_spp_from_length (samplecnt_t len)
{
double available_width = frame->get ().width ();
double s = floor (len / available_width);
set_spp (s);
if (_visible_canvas_width) {
set_samples_per_pixel (floor (len / _visible_canvas_width));
}
}
void
@ -521,12 +510,12 @@ AudioClipEditor::set_wave_heights ()
}
uint32_t n = 0;
const Distance w = frame->get ().height () - scroll_bar_trough->get ().height () - 2. - ruler->get().height();
const Distance w = _visible_canvas_height - (n_timebars * timebar_height);
Distance ht = w / waves.size ();
for (auto& wave : waves) {
wave->set_height (ht);
wave->set_y_position (ruler->get ().height () + (n * ht));
wave->set_y_position ((n_timebars * timebar_height) + (n * ht));
++n;
}
}
@ -547,86 +536,146 @@ AudioClipEditor::set_waveform_colors ()
}
}
Gtk::Widget&
AudioClipEditor::contents ()
{
return _contents;
}
void
AudioClipEditor::region_changed (const PBD::PropertyChange& what_changed)
{
}
void
AudioClipEditor::set_samples_per_pixel (samplecnt_t spp)
{
CueEditor::set_samples_per_pixel (spp);
clip_metric->units_per_pixel = samples_per_pixel;
position_lines ();
for (auto& wave : waves) {
wave->set_samples_per_pixel (samples_per_pixel);
}
horizontal_adjustment.set_upper (max_zoom_extent().second.samples() / samples_per_pixel);
horizontal_adjustment.set_page_size (current_page_samples()/ samples_per_pixel / 10);
horizontal_adjustment.set_page_increment (current_page_samples()/ samples_per_pixel / 20);
horizontal_adjustment.set_step_increment (current_page_samples() / samples_per_pixel / 100);
}
samplecnt_t
AudioClipEditor::current_page_samples() const
{
return (samplecnt_t) _track_canvas_width * samples_per_pixel;
}
bool
AudioClipEditor::event_handler (GdkEvent* ev)
AudioClipEditor::canvas_enter_leave (GdkEventCrossing* ev)
{
switch (ev->type) {
case GDK_BUTTON_PRESS:
break;
case GDK_ENTER_NOTIFY:
break;
case GDK_LEAVE_NOTIFY:
break;
default:
break;
case GDK_ENTER_NOTIFY:
if (ev->detail != GDK_NOTIFY_INFERIOR) {
_canvas.grab_focus ();
// ActionManager::set_sensitive (_midi_actions, true);
within_track_canvas = true;
}
break;
case GDK_LEAVE_NOTIFY:
if (ev->detail != GDK_NOTIFY_INFERIOR) {
// ActionManager::set_sensitive (_midi_actions, false);
within_track_canvas = false;
ARDOUR_UI::instance()->reset_focus (&_canvas_viewport);
gdk_window_set_cursor (_canvas_viewport.get_window()->gobj(), nullptr);
}
default:
break;
}
return false;
}
AudioClipEditorBox::AudioClipEditorBox ()
void
AudioClipEditor::begin_write ()
{
_header_label.set_text (_("AUDIO Region Trimmer:"));
_header_label.set_alignment (0.0, 0.5);
zoom_in_button.set_icon (ArdourIcon::ZoomIn);
zoom_out_button.set_icon (ArdourIcon::ZoomOut);
zoom_in_button.signal_clicked.connect (sigc::mem_fun (*this, &AudioClipEditorBox::zoom_in_click));
zoom_out_button.signal_clicked.connect (sigc::mem_fun (*this, &AudioClipEditorBox::zoom_out_click));
header_box.pack_start (_header_label, false, false);
header_box.pack_start (zoom_in_button, false, false);
header_box.pack_start (zoom_out_button, false, false);
pack_start (header_box, false, false, 6);
editor = manage (new AudioClipEditor);
editor->set_size_request (600, 120);
pack_start (*editor, true, true);
editor->show ();
}
AudioClipEditorBox::~AudioClipEditorBox ()
{
delete editor;
}
void
AudioClipEditorBox::zoom_in_click ()
AudioClipEditor::end_write ()
{
editor->set_spp (editor->spp () / 2.);
}
void
AudioClipEditorBox::zoom_out_click ()
AudioClipEditor::show_count_in (std::string const &)
{
editor->set_spp (editor->spp () * 2.);
}
void
AudioClipEditorBox::set_region (std::shared_ptr<Region> r, TriggerReference tref)
AudioClipEditor::hide_count_in ()
{
std::shared_ptr<AudioRegion> ar = std::dynamic_pointer_cast<AudioRegion> (r);
}
if (!ar) {
return;
void
AudioClipEditor::maybe_update ()
{
ARDOUR::TriggerPtr playing_trigger;
if (ref.trigger()) {
/* Trigger editor */
playing_trigger = ref.box()->currently_playing ();
if (!playing_trigger) {
if (_drags->active() || !_region || !_track || !_track->triggerbox()) {
return;
}
if (_track->triggerbox()->record_enabled() == Recording) {
_playhead_cursor->set_position (data_capture_duration);
}
} else {
if (playing_trigger->active ()) {
if (playing_trigger->the_region()) {
_playhead_cursor->set_position (playing_trigger->current_pos().samples() + playing_trigger->the_region()->start().samples());
}
} else {
_playhead_cursor->set_position (0);
}
}
#if 0
} else if (view->midi_region()) {
/* Timeline region editor */
if (!_session) {
return;
}
samplepos_t pos = _session->transport_sample();
samplepos_t spos = view->midi_region()->source_position().samples();
if (pos < spos) {
_playhead_cursor->set_position (0);
} else {
_playhead_cursor->set_position (pos - spos);
}
#endif
} else {
_playhead_cursor->set_position (0);
}
set_session (&r->session ());
state_connection.disconnect ();
_region = r;
editor->set_region (ar, tref);
PBD::PropertyChange interesting_stuff;
region_changed (interesting_stuff);
_region->PropertyChanged.connect (state_connection, invalidator (*this), std::bind (&AudioClipEditorBox::region_changed, this, _1), gui_context ());
if (follow_playhead()) {
reset_x_origin_to_follow_playhead ();
}
}
void
AudioClipEditorBox::region_changed (const PBD::PropertyChange& what_changed)
AudioClipEditor::unset (bool trigger_too)
{
drop_waves ();
CueEditor::unset (trigger_too);
}

View file

@ -25,6 +25,8 @@
#include <ytkmm/label.h>
#include <ytkmm/table.h>
#include "pbd/history_owner.h"
#include "ardour/ardour.h"
#include "ardour/session_handle.h"
#include "ardour/triggerbox.h"
@ -36,7 +38,6 @@
#include "widgets/ardour_button.h"
#include "canvas/canvas.h"
#include "canvas/container.h"
#include "canvas/line.h"
#include "canvas/rectangle.h"
@ -44,6 +45,7 @@
#include "canvas/scroll_group.h"
#include "audio_clock.h"
#include "cue_editor.h"
namespace ARDOUR
{
@ -63,59 +65,76 @@ namespace ArdourWaveView
class WaveView;
}
class ClipEditorBox : public Gtk::VBox, public ARDOUR::SessionHandlePtr
class AudioClipEditor : public CueEditor
{
public:
ClipEditorBox () {}
~ClipEditorBox () {}
virtual void set_region (std::shared_ptr<ARDOUR::Region>, ARDOUR::TriggerReference) = 0;
static void init ();
static void register_clip_editor_actions (Gtkmm2ext::Bindings*);
static Glib::RefPtr<Gtk::ActionGroup> clip_editor_actions;
};
class ClipEditor
{
public:
virtual ~ClipEditor () {}
virtual void zoom_in () = 0;
virtual void zoom_out () = 0;
};
class AudioClipEditor : public ArdourCanvas::GtkCanvas
{
public:
AudioClipEditor ();
AudioClipEditor (std::string const &, bool with_transport = false);
~AudioClipEditor ();
void set_region (std::shared_ptr<ARDOUR::AudioRegion>, ARDOUR::TriggerReference);
void on_size_allocate (Gtk::Allocation&);
void canvas_allocate (Gtk::Allocation&);
double sample_to_pixel (ARDOUR::samplepos_t);
samplepos_t pixel_to_sample (double);
Gtk::Widget& contents ();
void set_spp (double);
double spp () const
{
return _spp;
}
void set_trigger (ARDOUR::TriggerReference&);
void set_region (std::shared_ptr<ARDOUR::Region> r);
void region_changed (const PBD::PropertyChange& what_changed);
bool key_press (GdkEventKey*);
private:
ArdourCanvas::Rectangle* frame;
ArdourCanvas::ScrollGroup* waves_container;
ArdourCanvas::Container* line_container;
ArdourCanvas::Line* start_line;
ArdourCanvas::Line* end_line;
ArdourCanvas::Line* loop_line;
ArdourCanvas::Rectangle* scroll_bar_trough;
ArdourCanvas::Rectangle* scroll_bar_handle;
ArdourCanvas::Container* ruler_container;
ArdourCanvas::Ruler* ruler;
/* EditingContext API. As of July 2025, we do not implement most of
* these
*/
bool button_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool button_press_handler_1 (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool button_press_handler_2 (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool button_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool button_press_dispatch (GdkEventButton*) { return true; }
bool button_release_dispatch (GdkEventButton*) { return true; }
bool motion_handler (ArdourCanvas::Item*, GdkEvent*, bool from_autoscroll = false) { return true; }
bool enter_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool leave_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool key_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType) { return true; }
bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) { return true; }
bool canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item*) { return true; }
bool canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item*) { return true; }
bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*) { return true; }
bool canvas_bg_event (GdkEvent* event, ArdourCanvas::Item*) { return true; }
samplecnt_t current_page_samples() const;
void set_samples_per_pixel (samplecnt_t);
Gdk::Cursor* which_track_cursor () const { return nullptr; }
Gdk::Cursor* which_mode_cursor () const { return nullptr; }
Gdk::Cursor* which_trim_cursor (bool left_side) const { return nullptr; }
Gdk::Cursor* which_canvas_cursor (ItemType type) const { return nullptr; }
Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start, Temporal::RoundMode direction, ARDOUR::SnapPref gpref) const { return start; }
void snap_to_internal (Temporal::timepos_t& first, Temporal::RoundMode direction = Temporal::RoundNearest, ARDOUR::SnapPref gpref = ARDOUR::SnapToAny_Visual, bool ensure_snap = false) const {}
void select_all_within (Temporal::timepos_t const &, Temporal::timepos_t const &, double, double, std::list<SelectableOwner*> const &, ARDOUR::SelectionOperation, bool) {}
void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<std::shared_ptr<Evoral::Note<Temporal::Beats> > > > >&) const {}
void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const {}
void point_selection_changed () {}
void delete_ () {}
void paste (float times, bool from_context_menu) {}
void keyboard_paste () {}
void cut_copy (Editing::CutCopyOp) {}
void maybe_update ();
bool idle_data_captured () { return false; }
private:
ArdourCanvas::Container* line_container;
ArdourCanvas::Line* start_line;
ArdourCanvas::Line* end_line;
ArdourCanvas::Line* loop_line;
ArdourCanvas::Container* ruler_container;
ArdourCanvas::Ruler* minsec_ruler;
class ClipBBTMetric : public ArdourCanvas::Ruler::Metric
{
@ -135,9 +154,7 @@ private:
std::vector<ArdourWaveView::WaveView*> waves;
double non_wave_height;
samplepos_t left_origin;
double _spp;
double scroll_fraction;
std::shared_ptr<ARDOUR::AudioRegion> audio_region;
void scroll_left ();
void scrol_right ();
@ -150,7 +167,6 @@ private:
bool event_handler (GdkEvent* ev);
bool line_event_handler (GdkEvent* ev, ArdourCanvas::Line*);
bool scroll_event_handler (GdkEvent* ev);
void drop_waves ();
void set_wave_heights ();
void set_spp_from_length (ARDOUR::samplecnt_t);
@ -176,47 +192,21 @@ private:
friend class LineDrag;
LineDrag* current_line_drag;
class ScrollDrag
{
public:
ScrollDrag (AudioClipEditor&);
void begin (GdkEventButton*);
void end (GdkEventButton*);
void motion (GdkEventMotion*);
private:
AudioClipEditor& editor;
double last_x;
};
friend class ScrollDrag;
ScrollDrag* current_scroll_drag;
};
class AudioClipEditorBox : public ClipEditorBox
{
public:
AudioClipEditorBox ();
~AudioClipEditorBox ();
void set_region (std::shared_ptr<ARDOUR::Region>, ARDOUR::TriggerReference);
void region_changed (const PBD::PropertyChange& what_changed);
private:
Gtk::HBox header_box;
ArdourWidgets::ArdourButton zoom_in_button;
ArdourWidgets::ArdourButton zoom_out_button;
Gtk::Label _header_label;
Gtk::Table table;
AudioClipEditor* editor;
PBD::ScopedConnection state_connection;
std::shared_ptr<ARDOUR::Region> _region;
void build_canvas ();
void build_lower_toolbar ();
void pack_inner (Gtk::Box&);
void pack_outer (Gtk::Box&);
void zoom_in_click ();
void zoom_out_click ();
bool canvas_enter_leave (GdkEventCrossing* ev);
void begin_write ();
void end_write ();
void show_count_in (std::string const &);
void hide_count_in ();
void unset (bool trigger_too);
void load_shared_bindings ();
};

File diff suppressed because it is too large Load diff

View file

@ -20,15 +20,34 @@
#include "pbd/history_owner.h"
#include "canvas/canvas.h"
#include "widgets/ardour_button.h"
#include "widgets/eventboxext.h"
#include "editing.h"
#include "editing_context.h"
#include "region_ui_settings.h"
namespace Gtk {
class HScrollbar;
}
class CueEditor : public EditingContext, public PBD::HistoryOwner
{
public:
CueEditor (std::string const & name);
CueEditor (std::string const & name, bool with_transport_controls);
~CueEditor ();
virtual Gtk::Widget& contents () = 0;
void session_going_away ();
ArdourCanvas::Container* get_trackview_group () const { return data_group; }
ArdourCanvas::Container* get_noscroll_group() const { return no_scroll_group; }
ArdourCanvas::ScrollGroup* get_hscroll_group () const { return h_scroll_group; }
ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; }
void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const;
StripableTimeAxisView* get_stripable_time_axis_by_id (const PBD::ID& id) const;
TrackViewList axis_views_from_routes (std::shared_ptr<ARDOUR::RouteList>) const;
@ -46,6 +65,7 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner
void redisplay_grid (bool immediate_redraw);
Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) const;
std::list<SelectableOwner*> selectable_owners() { return std::list<SelectableOwner*>(); }
void instant_save();
@ -56,6 +76,8 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner
void undo_selection_op ();
void redo_selection_op ();
RegionSelection region_selection();
PBD::HistoryOwner& history() { return *this; }
void history_changed ();
PBD::ScopedConnection history_connection;
@ -85,6 +107,7 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner
Editing::MouseMode current_mouse_mode () const;
/** cue editors are *always* used for internal editing */
bool internal_editing() const { return true; }
void mouse_mode_toggled (Editing::MouseMode);
Gdk::Cursor* get_canvas_cursor () const;
MouseCursors const* cursors () const {
@ -97,10 +120,150 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner
std::shared_ptr<Temporal::TempoMap const> start_local_tempo_map (std::shared_ptr<Temporal::TempoMap>);
void end_local_tempo_map (std::shared_ptr<Temporal::TempoMap const>);
void scrolled ();
bool canvas_pre_event (GdkEvent*);
void catch_pending_show_region ();
std::pair<Temporal::timepos_t,Temporal::timepos_t> max_zoom_extent() const;
void full_zoom_clicked();
void zoom_to_show (Temporal::timecnt_t const &);
bool ruler_event (GdkEvent*);
virtual void set_show_source (bool);
virtual void set_region (std::shared_ptr<ARDOUR::Region>);
virtual void set_track (std::shared_ptr<ARDOUR::Track>);
virtual void set_trigger (ARDOUR::TriggerReference&);
virtual void maybe_update () = 0;
ArdourCanvas::GtkCanvasViewport* get_canvas_viewport() const;
ArdourCanvas::GtkCanvas* get_canvas() const;
int set_state (const XMLNode&, int version);
XMLNode& get_state () const;
protected:
ArdourCanvas::GtkCanvasViewport _canvas_viewport;
ArdourCanvas::GtkCanvas& _canvas;
ARDOUR::TriggerReference ref;
std::shared_ptr<ARDOUR::Region> _region;
std::shared_ptr<ARDOUR::Track> _track;
bool with_transport_controls;
bool show_source;
ArdourWidgets::EventBoxExt _contents;
Gtk::VBox _toolbox;
Gtk::HBox button_bar;
Gtk::HScrollbar* _canvas_hscrollbar;
void load_bindings ();
void register_actions ();
/* The group containing all other groups that are scrolled vertically
and horizontally.
*/
ArdourCanvas::ScrollGroup* hv_scroll_group;
/* The group containing all other groups that are scrolled horizontally ONLY
*/
ArdourCanvas::ScrollGroup* h_scroll_group;
ArdourCanvas::ScrollGroup* v_scroll_group;
/* Scroll group for cursors, scrolled horizontally, above everything else
*/
ArdourCanvas::ScrollGroup* cursor_scroll_group;
ArdourCanvas::Container* global_rect_group;
ArdourCanvas::Container* no_scroll_group;
ArdourCanvas::Container* data_group;
Gtk::Label length_label;
Gtk::HBox rec_box;
Gtk::HBox play_box;
virtual void pack_inner (Gtk::Box&) = 0;
virtual void pack_outer (Gtk::Box&) = 0;
void build_zoom_focus_menu ();
virtual void update_rulers() {}
virtual bool canvas_enter_leave (GdkEventCrossing* ev) = 0;
void build_upper_toolbar ();
void do_undo (uint32_t n);
void do_redo (uint32_t n);
Temporal::timepos_t _get_preferred_edit_position (Editing::EditIgnoreOption, bool use_context_click, bool from_outside_canvas);
ArdourWidgets::ArdourButton rec_enable_button;
ArdourWidgets::ArdourButton play_button;
ArdourWidgets::ArdourButton solo_button;
ArdourWidgets::ArdourButton loop_button;
ArdourCanvas::Rectangle* transport_loop_range_rect;
bool play_button_press (GdkEventButton*);
bool solo_button_press (GdkEventButton*);
bool bang_button_press (GdkEventButton*);
bool loop_button_press (GdkEventButton*);
ArdourWidgets::ArdourDropdown length_selector;
Temporal::BBT_Offset rec_length;
bool zoom_in_allocate;
void set_recording_length (Temporal::BBT_Offset bars);
bool rec_button_press (GdkEventButton*);
void rec_enable_change ();
void blink_rec_enable (bool);
sigc::connection rec_blink_connection;
sigc::connection _update_connection;
PBD::ScopedConnectionList object_connections;
void trigger_arm_change ();
double timebar_height;
size_t n_timebars;
/* autoscrolling */
bool autoscroll_canvas ();
void start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary);
void visual_changer (const VisualChange&);
void update_solo_display ();
std::shared_ptr<ARDOUR::Region> _visible_pending_region;
void ruler_locate (GdkEventButton*);
virtual void begin_write () = 0;
virtual void end_write () = 0;
virtual void manage_possible_header (Gtk::Allocation&) {}
sigc::connection count_in_connection;
Temporal::Beats count_in_to;
void count_in (Temporal::timepos_t, unsigned int);
void maybe_set_count_in ();
virtual void show_count_in (std::string const &) = 0;
virtual void hide_count_in () = 0;
void data_captured (samplecnt_t);
virtual bool idle_data_captured () = 0;
std::atomic<int> idle_update_queued;
PBD::ScopedConnectionList capture_connections;
samplecnt_t data_capture_duration;
virtual void unset (bool trigger_too);
RegionUISettings region_ui_settings;
void maybe_set_from_rsu ();
virtual void set_from_rsu (RegionUISettings&);
void metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>&, samplepos_t, samplepos_t, gint);
};

File diff suppressed because it is too large Load diff

View file

@ -147,7 +147,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
void toggle_follow_playhead ();
/** @return true if the editor is following the playhead */
bool follow_playhead () const { return _follow_playhead; }
bool follow_playhead () const;
Temporal::timepos_t get_preferred_edit_position (Editing::EditIgnoreOption eio = Editing::EDIT_IGNORE_NONE,
bool use_context_click = false,
@ -258,6 +258,9 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
double timeline_to_canvas (double p) const { return p + _timeline_origin; }
double canvas_to_timeline (double p) const { return p - _timeline_origin; }
double visible_canvas_width () const { return _visible_canvas_width; }
double visible_canvas_height () const { return _visible_canvas_height; }
/** computes the timeline position for an event whose coordinates
* are in canvas units (pixels, scroll offset included). The time
* domain used by the return value will match ::default_time_domain()
@ -291,12 +294,12 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
void cycle_snap_mode ();
void next_grid_choice ();
void prev_grid_choice ();
void set_grid_to (Editing::GridType);
void set_grid_type (Editing::GridType);
void set_snap_mode (Editing::SnapMode);
void set_draw_length_to (Editing::GridType);
void set_draw_velocity_to (int);
void set_draw_channel_to (int);
void set_draw_length (Editing::GridType);
void set_draw_velocity (int);
void set_draw_channel (int);
Editing::GridType draw_length () const;
int draw_velocity () const;
@ -516,7 +519,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
Glib::RefPtr<Gtk::ActionGroup> velocity_actions;
Glib::RefPtr<Gtk::ActionGroup> zoom_actions;
void load_shared_bindings ();
virtual void load_shared_bindings ();
Editing::GridType pre_internal_grid_type;
Editing::SnapMode pre_internal_snap_mode;
@ -525,19 +528,11 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
static std::vector<std::string> grid_type_strings;
Glib::RefPtr<Gtk::RadioAction> grid_type_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> snap_mode_action (Editing::SnapMode);
Glib::RefPtr<Gtk::RadioAction> draw_length_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> draw_velocity_action (int);
Glib::RefPtr<Gtk::RadioAction> draw_channel_action (int);
Editing::GridType _grid_type;
Editing::SnapMode _snap_mode;
Editing::GridType _draw_length;
int _draw_velocity;
int _draw_channel;
std::map<Editing::GridType, Glib::RefPtr<Gtk::RadioAction> > grid_actions;
std::map<Editing::SnapMode, Glib::RefPtr<Gtk::RadioAction> > snap_mode_actions;
std::map<Editing::GridType, Glib::RefPtr<Gtk::RadioAction> > draw_length_actions;
std::map<int, Glib::RefPtr<Gtk::RadioAction> > draw_velocity_actions;
std::map<int, Glib::RefPtr<Gtk::RadioAction> > draw_channel_actions;
void draw_channel_chosen (int);
void draw_velocity_chosen (int);
@ -561,8 +556,6 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
ArdourWidgets::ArdourDropdown draw_channel_selector;
void build_draw_midi_menus ();
void grid_type_selection_done (Editing::GridType);
void snap_mode_selection_done (Editing::SnapMode);
void snap_mode_chosen (Editing::SnapMode);
void grid_type_chosen (Editing::GridType);
@ -600,7 +593,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
EditorCursor* _playhead_cursor;
EditorCursor* _snapped_cursor;
bool _follow_playhead;
Glib::RefPtr<Gtk::ToggleAction> follow_playhead_action;
/* selection process */
@ -633,7 +626,6 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
bool ensure_snap = false) const = 0;
void check_best_snap (Temporal::timepos_t const & presnap, Temporal::timepos_t &test, Temporal::timepos_t &dist, Temporal::timepos_t &best) const;
virtual double visible_canvas_width() const = 0;
enum BBTRulerScale {
bbt_show_many,
@ -819,8 +811,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
/* protected helper functions to help with registering actions */
static Glib::RefPtr<Gtk::Action> reg_sens (Glib::RefPtr<Gtk::ActionGroup> group, char const* name, char const* label, sigc::slot<void> slot);
static void toggle_reg_sens (Glib::RefPtr<Gtk::ActionGroup> group, char const* name, char const* label, sigc::slot<void> slot);
static void radio_reg_sens (Glib::RefPtr<Gtk::ActionGroup> action_group, Gtk::RadioAction::Group& radio_group, char const* name, char const* label, sigc::slot<void> slot);
static Glib::RefPtr<Gtk::ToggleAction> toggle_reg_sens (Glib::RefPtr<Gtk::ActionGroup> group, char const* name, char const* label, sigc::slot<void> slot);
static Glib::RefPtr<Gtk::RadioAction> radio_reg_sens (Glib::RefPtr<Gtk::ActionGroup> action_group, Gtk::RadioAction::Group& radio_group, char const* name, char const* label, sigc::slot<void> slot);
void center_screen_internal (samplepos_t, float);

View file

@ -379,7 +379,6 @@ Editor::Editor ()
, _last_cut_copy_source_track (nullptr)
, _region_selection_change_updates_region_list (true)
, _following_mixer_selection (false)
, _show_touched_automation (false)
, _control_point_toggled_on_press (false)
, _stepping_axis_view (nullptr)
, _main_menu_disabler (nullptr)
@ -1151,7 +1150,7 @@ Editor::map_position_change (samplepos_t sample)
return;
}
if (_follow_playhead) {
if (follow_playhead()) {
center_screen (sample);
}
@ -1229,7 +1228,7 @@ Editor::set_session (Session *t)
if (!_pianoroll) {
// XXX this should really not happen here
_pianoroll = new Pianoroll ("editor pianoroll", true);
_pianoroll->viewport().set_size_request (-1, 120);
_pianoroll->get_canvas_viewport()->set_size_request (-1, 120);
}
_pianoroll->set_session (_session);
@ -2068,6 +2067,8 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
void
Editor::show_rulers_for_grid ()
{
GridType gt (grid_type());
/* show appropriate rulers for this grid setting. */
if (grid_musical()) {
ruler_tempo_action->set_active(true);
@ -2079,7 +2080,7 @@ Editor::show_rulers_for_grid ()
ruler_minsec_action->set_active(false);
ruler_samples_action->set_active(false);
}
} else if (_grid_type == GridTypeTimecode) {
} else if (gt == GridTypeTimecode) {
ruler_timecode_action->set_active(true);
if (UIConfiguration::instance().get_rulers_follow_grid()) {
@ -2089,7 +2090,7 @@ Editor::show_rulers_for_grid ()
ruler_minsec_action->set_active(false);
ruler_samples_action->set_active(false);
}
} else if (_grid_type == GridTypeMinSec) {
} else if (gt == GridTypeMinSec) {
ruler_minsec_action->set_active(true);
if (UIConfiguration::instance().get_rulers_follow_grid()) {
@ -2099,7 +2100,7 @@ Editor::show_rulers_for_grid ()
ruler_timecode_action->set_active(false);
ruler_samples_action->set_active(false);
}
} else if (_grid_type == GridTypeCDFrame) {
} else if (gt == GridTypeCDFrame) {
ruler_minsec_action->set_active(true);
if (UIConfiguration::instance().get_rulers_follow_grid()) {
@ -2334,7 +2335,7 @@ Editor::set_state (const XMLNode& node, int version)
RefPtr<ToggleAction> tact;
tact = ActionManager::get_toggle_action ((editor_name () + X_("Editing")).c_str(), X_("toggle-follow-playhead"));
yn = _follow_playhead;
yn = follow_playhead();
if (tact->get_active() != yn) {
tact->set_active (yn);
}
@ -2374,19 +2375,14 @@ Editor::get_state () const
node->set_property ("y-origin", vertical_adjustment.get_value ());
node->set_property ("maximised", _maximised);
node->set_property ("follow-playhead", _follow_playhead);
node->set_property ("follow-playhead", follow_playhead());
node->set_property ("stationary-playhead", _stationary_playhead);
node->set_property ("mouse-mode", mouse_mode);
node->set_property ("join-object-range", smart_mode_action->get_active ());
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Editor"), X_("show-editor-mixer"));
node->set_property (X_("show-editor-mixer"), tact->get_active());
tact = ActionManager::get_toggle_action (X_("Editor"), X_("show-editor-list"));
node->set_property (X_("show-editor-list"), tact->get_active());
tact = ActionManager::get_toggle_action (X_("Editor"), X_("show-editor-props"));
node->set_property (X_("show-editor-props"), tact->get_active());
node->set_property (X_("show-editor-mixer"), show_editor_mixer_action->get_active());
node->set_property (X_("show-editor-list"), show_editor_list_action->get_active());
node->set_property (X_("show-editor-props"), show_editor_props_action->get_active());
node->set_property (X_("editor-list-page"), _the_notebook.get_current_page ());
node->set_property (X_("editor-list-btn1"), _notebook_tab1.index ());
@ -2399,7 +2395,7 @@ Editor::get_state () const
}
node->set_property (X_("show-marker-lines"), _show_marker_lines);
node->set_property (X_("show-touched-automation"), _show_touched_automation);
node->set_property (X_("show-touched-automation"), show_touched_automation());
node->add_child_nocopy (selection->get_state ());
@ -2615,7 +2611,7 @@ Editor::snap_to_grid (timepos_t const & presnap, Temporal::RoundMode direction,
ret = snap_to_bbt (presnap, direction, gpref);
}
switch (_grid_type) {
switch (grid_type()) {
case GridTypeTimecode:
ret = snap_to_timecode(presnap, direction, gpref);
break;
@ -3458,28 +3454,29 @@ Editor::set_stationary_playhead (bool yn)
}
bool
Editor::show_touched_automation () const
Editor::show_touched_automation() const
{
if (!contents().get_mapped()) {
return false;
}
return _show_touched_automation;
if (!show_touched_automation_action) {
return false;
}
return show_touched_automation_action->get_active ();
}
void
Editor::toggle_show_touched_automation ()
{
RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Editor"), X_("show-touched-automation"));
set_show_touched_automation (tact->get_active());
set_show_touched_automation (show_touched_automation_action->get_active());
}
void
Editor::set_show_touched_automation (bool yn)
{
if (_show_touched_automation == yn) {
return;
}
_show_touched_automation = yn;
show_touched_automation_action->set_active (yn);
if (!yn) {
RouteTimeAxisView::signal_ctrl_touched (true);
}
@ -4546,7 +4543,7 @@ Editor::located ()
if (_session) {
_playhead_cursor->set_position (_session->audible_sample ());
if (_follow_playhead && !_pending_initial_locate) {
if (follow_playhead() && !_pending_initial_locate) {
reset_x_origin_to_follow_playhead ();
}
update_section_box ();
@ -5330,7 +5327,7 @@ Editor::super_rapid_screen_update ()
return;
}
if (!_follow_playhead || pending_visual_change.being_handled) {
if (!follow_playhead() || pending_visual_change.being_handled) {
/* We only do this if we aren't already
* handling a visual change (ie if
* pending_visual_change.being_handled is
@ -5721,7 +5718,7 @@ Editor::snap_to_internal (timepos_t& start, Temporal::RoundMode direction, SnapP
timepos_t best = timepos_t::max (start.time_domain()); // this records the best snap-result we've found so far
/* check Grid */
if ( (_grid_type != GridTypeNone) && (uic.get_snap_target () != SnapTargetOther) ) {
if ( (grid_type() != GridTypeNone) && (uic.get_snap_target () != SnapTargetOther) ) {
timepos_t pre (presnap);
timepos_t post (snap_to_grid (pre, direction, pref));
check_best_snap (presnap, post, dist, best);

View file

@ -2065,6 +2065,11 @@ private:
Glib::RefPtr<Gtk::Action> selection_undo_action;
Glib::RefPtr<Gtk::Action> selection_redo_action;
Glib::RefPtr<Gtk::ToggleAction> show_editor_mixer_action;
Glib::RefPtr<Gtk::ToggleAction> show_editor_list_action;
Glib::RefPtr<Gtk::ToggleAction> show_editor_props_action;
Glib::RefPtr<Gtk::ToggleAction> show_touched_automation_action;
void history_changed ();
Editing::EditPoint _edit_point;
@ -2200,7 +2205,6 @@ private:
/* RTAV Automation display option */
void toggle_show_touched_automation ();
void set_show_touched_automation (bool);
bool _show_touched_automation;
int time_fx (ARDOUR::RegionList&, Temporal::ratio_t ratio, bool pitching, bool fixed_end);
void toggle_sound_midi_notes ();

View file

@ -187,17 +187,17 @@ Editor::register_actions ()
/* attachments visibility (editor-mixer-strip, bottom properties, sidebar list) */
act = ActionManager::register_toggle_action (editor_actions, "show-editor-list", _("Show Editor List"), sigc::mem_fun (*this, &Tabbable::att_right_button_toggled));
ActionManager::session_sensitive_actions.push_back (act);
right_attachment_button.set_related_action (act);
show_editor_list_action = ActionManager::register_toggle_action (editor_actions, "show-editor-list", _("Show Editor List"), sigc::mem_fun (*this, &Tabbable::att_right_button_toggled));
ActionManager::session_sensitive_actions.push_back (show_editor_list_action);
right_attachment_button.set_related_action (show_editor_list_action);
act = ActionManager::register_toggle_action (editor_actions, "show-editor-mixer", _("Show Editor Mixer"), sigc::mem_fun (*this, &Tabbable::att_left_button_toggled));
ActionManager::session_sensitive_actions.push_back (act);
left_attachment_button.set_related_action (act);
show_editor_mixer_action = ActionManager::register_toggle_action (editor_actions, "show-editor-mixer", _("Show Editor Mixer"), sigc::mem_fun (*this, &Tabbable::att_left_button_toggled));
ActionManager::session_sensitive_actions.push_back (show_editor_mixer_action);
left_attachment_button.set_related_action (show_editor_mixer_action);
act = ActionManager::register_toggle_action (editor_actions, "show-editor-props", _("Show Editor Properties Box"), sigc::mem_fun (*this, &Tabbable::att_bottom_button_toggled));
ActionManager::session_sensitive_actions.push_back (act);
bottom_attachment_button.set_related_action (act);
show_editor_props_action = ActionManager::register_toggle_action (editor_actions, "show-editor-props", _("Show Editor Properties Box"), sigc::mem_fun (*this, &Tabbable::att_bottom_button_toggled));
ActionManager::session_sensitive_actions.push_back (show_editor_props_action);
bottom_attachment_button.set_related_action (show_editor_props_action);
reg_sens (editor_actions, "playhead-to-next-region-boundary", _("Playhead to Next Region Boundary"), sigc::bind (sigc::mem_fun(*this, &Editor::cursor_to_next_region_boundary), true));
reg_sens (editor_actions, "playhead-to-next-region-boundary-noselection", _("Playhead to Next Region Boundary (No Track Selection)"), sigc::bind (sigc::mem_fun(*this, &Editor::cursor_to_next_region_boundary), false));
@ -480,7 +480,7 @@ Editor::register_actions ()
ActionManager::register_toggle_action (editor_actions, "toggle-stationary-playhead", _("Stationary Playhead"), (mem_fun(*this, &Editor::toggle_stationary_playhead)));
ActionManager::register_toggle_action (editor_actions, "show-touched-automation", _("Show Automation Lane on Touch"), (mem_fun(*this, &Editor::toggle_show_touched_automation)));
show_touched_automation_action = ActionManager::register_toggle_action (editor_actions, "show-touched-automation", _("Show Automation Lane on Touch"), (mem_fun(*this, &Editor::toggle_show_touched_automation)));
act = reg_sens (editor_actions, "insert-time", _("Insert Time"), (sigc::mem_fun(*this, &Editor::do_insert_time)));
ActionManager::track_selection_sensitive_actions.push_back (act);

View file

@ -3106,7 +3106,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
/* only snap to bars. */
editing_context.set_grid_to (GridTypeBar);
editing_context.set_grid_type (GridTypeBar);
editing_context.set_snap_mode (SnapMagnetic);
}
@ -3143,7 +3143,7 @@ MeterMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
}
/* reinstate old snap setting */
editing_context.set_grid_to (_old_grid_type);
editing_context.set_grid_type (_old_grid_type);
editing_context.set_snap_mode (_old_snap_mode);
_editor.commit_tempo_map_edit (map);
@ -3167,7 +3167,7 @@ MeterMarkerDrag::aborted (bool moved)
if (moved) {
/* reinstate old snap setting */
editing_context.set_grid_to (_old_grid_type);
editing_context.set_grid_type (_old_grid_type);
editing_context.set_snap_mode (_old_snap_mode);
// delete the dummy marker we used for visual representation while moving.

View file

@ -150,14 +150,14 @@ Editor::mouse_mode_toggled (MouseMode m)
this must toggle the actions and not call set_snap_*() directly,
otherwise things get out of sync and the combo box stops working. */
if (!UIConfiguration::instance().get_grid_follows_internal()) {
grid_type_action(pre_internal_grid_type)->set_active(true);
snap_mode_action(pre_internal_snap_mode)->set_active(true);
grid_actions[pre_internal_grid_type]->set_active(true);
snap_mode_actions[pre_internal_snap_mode]->set_active(true);
} else if (!was_internal && internal_editing()) {
grid_type_action(internal_grid_type)->set_active(true);
snap_mode_action(internal_snap_mode)->set_active(true);
grid_actions[internal_grid_type]->set_active(true);
snap_mode_actions[internal_snap_mode]->set_active(true);
} else if (was_internal && !internal_editing()) {
grid_type_action(pre_internal_grid_type)->set_active(true);
snap_mode_action(pre_internal_snap_mode)->set_active(true);
grid_actions[pre_internal_grid_type]->set_active(true);
snap_mode_actions[pre_internal_snap_mode]->set_active(true);
}
instant_save ();
@ -2108,7 +2108,7 @@ void
Editor::mouse_brush_insert_region (RegionView* rv, timepos_t const & pos)
{
/* no brushing without a useful quantize setting */
if (_grid_type == GridTypeNone)
if (grid_type() == GridTypeNone)
return;
/* don't brush a copy over the original */

View file

@ -2620,7 +2620,7 @@ Editor::maybe_locate_with_edit_preroll (samplepos_t location)
}
//if follow_playhead is on, keep the playhead on the screen
if (_follow_playhead)
if (follow_playhead())
if (location < _leftmost_sample)
location = _leftmost_sample;
@ -7801,7 +7801,7 @@ Editor::playhead_forward_to_grid ()
timepos_t pos (_playhead_cursor->current_sample ());
if (_grid_type == GridTypeNone) {
if (grid_type() == GridTypeNone) {
timepos_t const decipage (samplepos_t(floor (current_page_samples() * 0.1)));
if (pos < timepos_t::max (pos.time_domain()).earlier (decipage)) {
pos += timepos_t (decipage);
@ -7830,7 +7830,7 @@ Editor::playhead_backward_to_grid ()
timepos_t pos (_playhead_cursor->current_sample ());
if (_grid_type == GridTypeNone) {
if (grid_type() == GridTypeNone) {
samplepos_t const decipage (floor (current_page_samples() * 0.1));
if (pos.samples() > decipage) {
pos.shift_earlier (timepos_t (decipage));

View file

@ -363,7 +363,7 @@ Editor::compute_current_bbt_points (Temporal::TempoMapPoints& grid, samplepos_t
const samplecnt_t sr (_session->sample_rate());
float divisor;
switch (_grid_type) {
switch (grid_type()) {
case GridTypeBeatDiv3:
case GridTypeBeatDiv6:
case GridTypeBeatDiv12:

View file

@ -202,7 +202,6 @@ MidiView::init (std::shared_ptr<MidiTrack> mt)
void
MidiView::note_mode_changed ()
{
std::cerr << "NM change\n";
clear_events ();
model_changed ();
}

File diff suppressed because it is too large Load diff

View file

@ -58,12 +58,8 @@ class Pianoroll : public CueEditor
Pianoroll (std::string const & name, bool with_transport_controls = false);
~Pianoroll ();
ArdourCanvas::Container* get_trackview_group () const { return data_group; }
ArdourCanvas::Container* get_noscroll_group() const { return no_scroll_group; }
Gtk::Widget& viewport();
Gtk::Widget& contents ();
double visible_canvas_width() const { return _visible_canvas_width; }
samplecnt_t current_page_samples() const;
void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<std::shared_ptr<Evoral::Note<Temporal::Beats> > > > >&) const {}
@ -83,33 +79,13 @@ class Pianoroll : public CueEditor
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; }
void set_trigger (ARDOUR::TriggerReference&);
void set_region (std::shared_ptr<ARDOUR::MidiRegion>);
void set_track (std::shared_ptr<ARDOUR::MidiTrack>);
ArdourCanvas::ScrollGroup* get_hscroll_group () const { return h_scroll_group; }
ArdourCanvas::ScrollGroup* get_cursor_scroll_group () const { return cursor_scroll_group; }
void set_region (std::shared_ptr<ARDOUR::Region>);
void set_track (std::shared_ptr<ARDOUR::Track>);
double max_extents_scale() const { return 1.2; }
void set_samples_per_pixel (samplecnt_t);
void set_mouse_mode (Editing::MouseMode, bool force = false);
void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () const;
bool internal_editing() const;
void trigger_arm_change ();
double timebar_height;
size_t n_timebars;
ArdourCanvas::GtkCanvasViewport* get_canvas_viewport() const;
ArdourCanvas::GtkCanvas* get_canvas() const;
int set_state (const XMLNode&, int version);
XMLNode& get_state () const;
void maybe_autoscroll (bool, bool, bool);
bool autoscroll_active() const;
void midi_action (void (MidiView::*method)());
@ -133,9 +109,6 @@ class Pianoroll : public CueEditor
void set_trigger_length (Temporal::timecnt_t const &);
void set_trigger_bounds (Temporal::timepos_t const &, Temporal::timepos_t const &);
void full_zoom_clicked();
void zoom_to_show (Temporal::timecnt_t const &);
void delete_ ();
void paste (float times, bool from_context_menu);
void keyboard_paste ();
@ -143,7 +116,6 @@ class Pianoroll : public CueEditor
PianorollMidiView* midi_view() const { return view; }
void set_session (ARDOUR::Session*);
void session_going_away ();
bool allow_trim_cursors () const;
void shift_midi (Temporal::timepos_t const &, bool model);
@ -154,9 +126,6 @@ class Pianoroll : public CueEditor
void set_show_source (bool);
protected:
void load_bindings ();
void register_actions ();
Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start,
Temporal::RoundMode direction,
ARDOUR::SnapPref gpref) const;
@ -178,46 +147,14 @@ class Pianoroll : public CueEditor
bool key_press_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
bool key_release_handler (ArdourCanvas::Item*, GdkEvent*, ItemType);
void mouse_mode_toggled (Editing::MouseMode);
void escape ();
private:
ARDOUR::TriggerReference ref;
std::shared_ptr<ARDOUR::MidiTrack> _track;
ArdourCanvas::GtkCanvasViewport* _canvas_viewport;
ArdourCanvas::GtkCanvas* _canvas;
Gtk::HScrollbar* _canvas_hscrollbar;
/* The group containing all other groups that are scrolled vertically
and horizontally.
*/
ArdourCanvas::ScrollGroup* hv_scroll_group;
/* The group containing all other groups that are scrolled horizontally ONLY
*/
ArdourCanvas::ScrollGroup* h_scroll_group;
ArdourCanvas::ScrollGroup* v_scroll_group;
/* Scroll group for cursors, scrolled horizontally, above everything else
*/
ArdourCanvas::ScrollGroup* cursor_scroll_group;
ArdourCanvas::Container* global_rect_group;
ArdourCanvas::Container* no_scroll_group;
ArdourCanvas::Container* data_group;
ArdourCanvas::Ruler* bbt_ruler;
ArdourCanvas::Rectangle* tempo_bar;
ArdourCanvas::Rectangle* meter_bar;
ArdourCanvas::PianoRollHeader* prh;
ArdourCanvas::Rectangle* transport_loop_range_rect;
ArdourWidgets::EventBoxExt _contents;
Gtk::VBox _toolbox;
Gtk::HBox button_bar;
ArdourWidgets::ArdourButton* velocity_button;
ArdourWidgets::ArdourButton* bender_button;
ArdourWidgets::ArdourButton* pressure_button;
@ -236,15 +173,10 @@ class Pianoroll : public CueEditor
void build_canvas ();
void canvas_allocate (Gtk::Allocation);
void build_upper_toolbar ();
void build_lower_toolbar ();
RegionSelection region_selection();
bool canvas_enter_leave (GdkEventCrossing* ev);
void metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>&, samplepos_t, samplepos_t, gint);
class BBTMetric : public ArdourCanvas::Ruler::Metric
{
public:
@ -260,16 +192,6 @@ class Pianoroll : public CueEditor
BBTMetric bbt_metric;
bool canvas_pre_event (GdkEvent*);
/* autoscrolling */
bool autoscroll_canvas ();
void start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary);
void stop_canvas_autoscroll ();
sigc::connection _update_connection;
PBD::ScopedConnectionList object_connections;
PBD::ScopedConnectionList view_connections;
void maybe_update ();
void trigger_prop_change (PBD::PropertyChange const &);
@ -277,14 +199,9 @@ class Pianoroll : public CueEditor
void unset (bool trigger_too);
void visual_changer (const VisualChange&);
void bindings_changed ();
void data_captured (samplecnt_t);
bool idle_data_captured ();
std::atomic<int> idle_update_queued;
PBD::ScopedConnectionList capture_connections;
samplecnt_t data_capture_duration;
bool user_automation_button_event (GdkEventButton* ev, ArdourWidgets::MetaButton* mb);
bool automation_button_event (GdkEventButton*, Evoral::ParameterType type, int id);
@ -299,37 +216,8 @@ class Pianoroll : public CueEditor
void automation_state_changed ();
void build_zoom_focus_menu ();
std::pair<Temporal::timepos_t,Temporal::timepos_t> max_zoom_extent() const;
void point_selection_changed ();
bool zoom_in_allocate;
ArdourWidgets::ArdourButton rec_enable_button;
ArdourWidgets::ArdourButton play_button;
ArdourWidgets::ArdourButton solo_button;
ArdourWidgets::ArdourButton loop_button;
bool play_button_press (GdkEventButton*);
bool bang_button_press (GdkEventButton*);
bool solo_button_press (GdkEventButton*);
bool loop_button_press (GdkEventButton*);
ArdourWidgets::ArdourDropdown length_selector;
Temporal::BBT_Offset rec_length;
Gtk::Label length_label;
Gtk::HBox rec_box;
Gtk::HBox play_box;
void set_recording_length (Temporal::BBT_Offset bars);
bool rec_button_press (GdkEventButton*);
void rec_enable_change ();
void blink_rec_enable (bool);
sigc::connection rec_blink_connection;
void add_single_controller_item (Gtk::Menu_Helpers::MenuList& ctl_items, int ctl, const std::string& name, ArdourWidgets::MetaButton*);
void add_multi_controller_item (Gtk::Menu_Helpers::MenuList& ctl_items, uint16_t channels, int ctl, const std::string& name, ArdourWidgets::MetaButton*);
void reset_user_cc_choice (std::string, Evoral::Parameter param, ArdourWidgets::MetaButton*);
@ -337,30 +225,29 @@ class Pianoroll : public CueEditor
bool ignore_channel_changes;
void visible_channel_changed ();
bool with_transport_controls;
void update_solo_display ();
void map_transport_state ();
sigc::connection count_in_connection;
Temporal::Beats count_in_to;
void count_in (Temporal::timepos_t, unsigned int);
void maybe_set_count_in ();
bool bbt_ruler_event (GdkEvent*);
void ruler_locate (GdkEventButton*);
void scrolled ();
void update_tempo_based_rulers ();
void update_rulers() { update_tempo_based_rulers (); }
Gtk::Menu _region_context_menu;
void popup_region_context_menu (ArdourCanvas::Item* item, GdkEvent* event);
std::shared_ptr<ARDOUR::MidiRegion> _visible_pending_region;
void catch_pending_show_region ();
bool show_source;
void set_note_selection (uint8_t note);
void add_note_selection (uint8_t note);
void extend_note_selection (uint8_t note);
void toggle_note_selection (uint8_t note);
void pack_inner (Gtk::Box&);
void pack_outer (Gtk::Box&);
void begin_write ();
void end_write ();
void manage_possible_header (Gtk::Allocation& alloc);
void show_count_in (std::string const &);
void hide_count_in ();
void instant_save ();
};

View file

@ -19,6 +19,7 @@
#include "pbd/compose.h"
#include "ardour/midi_region.h"
#include "ardour/midi_track.h"
#include "gtkmm2ext/doi.h"
@ -35,7 +36,7 @@ PianorollWindow::PianorollWindow (std::string const & name, Session& s)
, region_editor (nullptr)
{
pianoroll->set_session (&s);
pianoroll->viewport().set_size_request (600, 120);
pianoroll->get_canvas_viewport()->set_size_request (600, 120);
add (hpacker);
hpacker.show ();

View file

@ -144,24 +144,21 @@ TriggerPage::TriggerPage ()
_sidebar_pager2.set_index (3);
_midi_editor = new Pianoroll (X_("MIDICueEditor"));
_audio_editor = new AudioClipEditor (X_("AudioClipEditor"));
_audio_editor->get_canvas_viewport()->show ();
_midi_editor->get_canvas_viewport()->show ();
/* Bottom -- Properties of selected Slot/Region */
table.set_homogeneous (false);
table.set_spacings (8); //match to slot_properties_box::set_spacings
table.set_border_width (8);
hpacker.set_homogeneous (false);
hpacker.set_spacing (8); //match to slot_properties_box::set_spacings
hpacker.set_border_width (8);
int col = 0;
table.attach (_properties_box, col, col + 1, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK | Gtk::FILL);
++col;
table.attach (_audio_trig_box, col, col + 1, 0, 1, Gtk::FILL, Gtk::SHRINK | Gtk::FILL);
clip_editor_column = ++col;
++col;
table.set_no_show_all ();
_parameter_box.pack_start (table);
_parameter_box.show ();
hpacker.pack_start (_properties_box, false, false);
hpacker.pack_start (_midi_trig_box, false, false);
hpacker.pack_start (_audio_trig_box, false, false);
hpacker.set_no_show_all ();
_sidebar_notebook.signal_switch_page().connect ([this](GtkNotebookPage*, guint page) {
std::string label (_sidebar_notebook.get_tab_label_text (*_sidebar_notebook.get_nth_page (page)));
@ -184,7 +181,7 @@ TriggerPage::TriggerPage ()
/* Top-level Layout */
content_app_bar.add (_application_bar);
content_main.add (_strip_group_box);
content_att_bottom.add (_parameter_box);
content_att_bottom.add (hpacker);
content_att_right.add (_sidebar_vbox);
/* Show all */
@ -263,6 +260,7 @@ TriggerPage::get_state () const
node->set_property (X_("triggerpage-sidebar-btn2"), _sidebar_pager2.index ());
node->add_child_nocopy (_midi_editor->get_state());
node->add_child_nocopy (_audio_editor->get_state());
Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Cues", "ToggleTriggerList");
node->set_property ("show-trigger-list", act->get_active ());
@ -306,6 +304,11 @@ TriggerPage::set_state (const XMLNode& node, int version)
_midi_editor->set_state (*mn, version);
}
XMLNode* an = node.child (_audio_editor->editor_name().c_str());
if (an) {
_audio_editor->set_state (*an, version);
}
bool yn = true;
node.get_property ("show-trigger-list", yn);
{
@ -368,10 +371,10 @@ TriggerPage::set_session (Session* s)
initial_track_display ();
_properties_box.set_session (s);
_audio_trig_box.set_session (s);
_midi_trig_box.set_session (s);
_midi_editor->set_session (s);
_audio_editor->set_session (s);
update_title ();
start_updating ();
@ -475,9 +478,7 @@ TriggerPage::trigger_arm_changed (Trigger const * trigger)
/* hide everything */
_audio_trig_box.hide ();
_midi_trig_box.hide ();
_midi_editor->viewport().hide ();
hide_all ();
Tabbable::showhide_att_bottom (false);
@ -485,10 +486,13 @@ TriggerPage::trigger_arm_changed (Trigger const * trigger)
TriggerReference ref (trigger->boxptr(), trigger->index());
if (box.data_type () == DataType::AUDIO) {
if (trigger->the_region()) {
_audio_trig_box.set_trigger (ref);
_audio_trig_box.show ();
}
_audio_trig_box.set_trigger (ref);
_audio_trig_box.show ();
_audio_editor->set_trigger (ref);
hpacker.pack_start (_audio_editor->contents(), true, true);
} else {
@ -496,7 +500,7 @@ TriggerPage::trigger_arm_changed (Trigger const * trigger)
_midi_trig_box.show ();
_midi_editor->set_trigger (ref);
_midi_editor->viewport().show ();
hpacker.pack_start (_midi_editor->contents(), true, true);
}
if (_show_bottom_pane) {
@ -505,38 +509,46 @@ TriggerPage::trigger_arm_changed (Trigger const * trigger)
}
void
TriggerPage::selection_changed ()
TriggerPage::hide_all ()
{
Selection& selection (Editor::instance ().get_selection ());
/* hide everything */
_audio_trig_box.hide ();
_midi_trig_box.hide ();
_midi_editor->contents().hide(); // although we de-parent this, it requires this explicit HIDE to prevent bleeding into other pages on macOS
if (_audio_editor->contents().get_parent()) {
_audio_editor->contents().get_parent()->remove (_audio_editor->contents());
}
if (_midi_editor->contents().get_parent()) {
_midi_editor->contents().get_parent()->remove (_midi_editor->contents());
}
_audio_trig_box.hide ();
_midi_trig_box.hide ();
}
void
TriggerPage::selection_changed ()
{
Selection& selection (Editor::instance ().get_selection ());
hide_all ();
Tabbable::showhide_att_bottom (false);
if (selection.triggers.empty ()) {
return;
}
TriggerSelection ts = selection.triggers;
TriggerEntry* entry = *ts.begin ();
TriggerReference ref = entry->trigger_reference ();
TriggerPtr trigger = entry->trigger ();
TriggerReference ref = selection.triggers.front()->trigger_reference ();
std::shared_ptr<TriggerBox> box = ref.box();
if (box->data_type () == DataType::AUDIO) {
if (trigger->the_region()) {
_audio_trig_box.set_trigger (ref);
_audio_trig_box.show ();
}
_audio_trig_box.set_trigger (ref);
_audio_trig_box.show ();
_audio_editor->set_trigger (ref);
_audio_editor->get_canvas_viewport()->show ();
hpacker.pack_start (_audio_editor->contents(), true, true);
_audio_editor->contents().show_all ();
} else {
@ -544,12 +556,13 @@ TriggerPage::selection_changed ()
_midi_trig_box.show ();
_midi_editor->set_trigger (ref);
_midi_editor->get_canvas_viewport()->show ();
table.attach (_midi_editor->contents(), clip_editor_column, clip_editor_column + 1, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL);
hpacker.pack_start (_midi_editor->contents(), true, true);
_midi_editor->contents().show_all ();
}
table.show ();
hpacker.show ();
if (_show_bottom_pane) {
Tabbable::showhide_att_bottom (true);

View file

@ -30,6 +30,7 @@
#include "widgets/tabbable.h"
#include "application_bar.h"
#include "audio_clip_editor.h"
#include "audio_region_operations_box.h"
#include "audio_trigger_properties_box.h"
#include "axis_provider.h"
@ -76,7 +77,7 @@ private:
void remove_route (TriggerStrip*);
void clear_selected_slot ();
void hide_all ();
void redisplay_track_list ();
void pi_property_changed (PBD::PropertyChange const&);
void stripable_property_changed (PBD::PropertyChange const&, std::weak_ptr<ARDOUR::Stripable>);
@ -117,7 +118,6 @@ private:
Gtk::EventBox _no_strips;
Gtk::Alignment _cue_area_frame;
Gtk::VBox _cue_area_box;
Gtk::HBox _parameter_box;
Gtk::VBox _sidebar_vbox;
ArdourWidgets::MetaButton _sidebar_pager1;
ArdourWidgets::MetaButton _sidebar_pager2;
@ -126,7 +126,7 @@ private:
TriggerSourceList _trigger_source_list;
TriggerRegionList _trigger_region_list;
TriggerRouteList _trigger_route_list;
Gtk::Table table;
Gtk::HBox hpacker;
CueBoxWidget _cue_box;
FittedCanvasWidget _master_widget;
@ -140,10 +140,10 @@ private:
#if REGION_PROPERTIES_BOX_TODO
AudioRegionOperationsBox _audio_ops_box;
AudioClipEditorBox _audio_trim_box;
#endif
Pianoroll* _midi_editor;
AudioClipEditor* _audio_editor;
RouteProcessorSelection _selection;
std::list<TriggerStrip*> _strips;