13
0

Compare commits

...

19 Commits

Author SHA1 Message Date
90d45ac428
Merge branch 'ardour' 2024-11-15 16:57:30 +01:00
438a514c2b
NO-OP: clarify Tabbable layout and attachment enum 2024-11-15 14:10:56 +01:00
0b933127e9
Use new Tabbable API 2024-11-15 04:40:39 +01:00
5c8bd6e977
Tweak Tabbable Layout
* allow for left side resizable pane
* automatically set attachment button sensitivity
* remove right-side pane box when unused
2024-11-15 04:38:43 +01:00
6f331be7ca
Remove deprecated 32C define 2024-11-15 03:54:17 +01:00
c6044f226c
Remove unused function 2024-11-14 07:06:05 +01:00
da0f1728ed
Fix External Sync Toggle Button 2024-11-14 07:05:58 +01:00
a53b99b307
Introduction of route property boxen and editor properties pane 2024-11-13 04:27:41 +01:00
9b64f64546
store and recall the Editor visibility for the bottom panel 2024-11-13 04:19:47 +01:00
48ed5be776 skeleton for clip start/end editing 2024-11-12 18:54:41 -07:00
e7b10fc37d virtualize editing connections to parameter changes 2024-11-12 10:47:08 -07:00
677a6764ac add new buttons to EditingContext; use them in MidiCueEditor 2024-11-12 09:49:59 -07:00
d3272a6400 midi cue editor: don't allocate space for automation till asked to do so 2024-11-12 08:51:29 -07:00
0622f26b2a redesign cue editor layout to use ArdourButton and GtkBoxen 2024-11-12 08:12:16 -07:00
a1dd7ae4c3 remove unused member variable
this was a solution to a problem eventually solved a different way
2024-11-11 22:06:05 -07:00
5dd65171c1 remove unused variable decl 2024-11-11 22:01:32 -07:00
47db75b0d6 cleanup some aspects of midicue editor playhead behavior 2024-11-11 21:49:55 -07:00
bccf36d665 catch pushing identical cursors to the cursor stack 2024-11-11 21:01:11 -07:00
b9b3e75b5c fix totally incorrect use of GdkCursor; use standard cursors in canvas piano roll header 2024-11-11 21:00:51 -07:00
31 changed files with 905 additions and 273 deletions

View File

@ -163,6 +163,29 @@ bool drag_failed (const Glib::RefPtr<Gdk::DragContext>& context, DragResult resu
void
ARDOUR_UI::setup_transport ()
{
/* NOTE - LIVETRAX does not call this */
RefPtr<Action> act;
/* setup actions */
/* CANNOT sigc::bind these to clicked or toggled, must use pressed or released */
error_alert_button.signal_button_release_event().connect (sigc::mem_fun(*this,&ARDOUR_UI::error_alert_press), false);
act = ActionManager::get_action (X_("Editor"), X_("toggle-log-window"));
error_alert_button.set_related_action(act);
error_alert_button.set_fallthrough_to_parent(true);
#ifndef LIVETRAX
editor_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-editor-visibility")));
mixer_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-mixer-visibility")));
prefs_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-preferences-visibility")));
recorder_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-recorder-visibility")));
trigger_page_visibility_button.set_related_action (ActionManager::get_action (X_("Common"), X_("change-trigger-visibility")));
#endif
/* connect signals */
ARDOUR_UI::Clock.connect (sigc::bind (sigc::mem_fun (primary_clock, &MainClock::set), false));
ARDOUR_UI::Clock.connect (sigc::bind (sigc::mem_fun (secondary_clock, &MainClock::set), false));
editor_visibility_button.signal_drag_failed().connect (sigc::bind (sigc::ptr_fun (drag_failed), editor));
mixer_visibility_button.signal_drag_failed().connect (sigc::bind (sigc::ptr_fun (drag_failed), mixer));
#ifndef LIVETRAX

View File

@ -525,6 +525,11 @@ ARDOUR_UI::livetrax_setup_windows ()
act = ActionManager::get_action (X_("Common"), X_("open-media-folder"));
livetrax_view_in_folder_button->set_related_action (act);
error_alert_button.signal_button_release_event().connect (sigc::mem_fun(*this,&ARDOUR_UI::error_alert_press), false);
act = ActionManager::get_action (X_("Editor"), X_("toggle-log-window"));
error_alert_button.set_related_action(act);
error_alert_button.set_fallthrough_to_parent(true);
_main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
/* pack the main vpacker into the main window and show everything

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2011-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2024 Ben Loftis <ben@harrisonconsoles.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "pbd/compose.h"
#include <algorithm>
#include "gtkmm2ext/actions.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h"
#include "ardour/location.h"
#include "ardour/profile.h"
#include "ardour/session.h"
#include "audio_clock.h"
#include "automation_line.h"
#include "control_point.h"
#include "editor.h"
#include "region_view.h"
#include "audio_route_properties_box.h"
#include "pbd/i18n.h"
using namespace Gtk;
using namespace ARDOUR;
using namespace ArdourWidgets;
using std::max;
using std::min;
AudioRoutePropertiesBox::AudioRoutePropertiesBox ()
{
_header_label.set_text (_("AUDIO Region Properties:"));
Gtk::Table* audio_t = manage (new Gtk::Table ());
audio_t->set_homogeneous (true);
audio_t->set_spacings (4);
pack_start (*audio_t);
}
AudioRoutePropertiesBox::~AudioRoutePropertiesBox ()
{
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2021 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2024 Ben Loftis <ben@harrisonconsoles.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <map>
#include <gtkmm/box.h>
#include <gtkmm/label.h>
#include <gtkmm/table.h>
#include "ardour/ardour.h"
#include "ardour/session_handle.h"
#include "widgets/ardour_button.h"
#include "gtkmm2ext/cairo_packer.h"
#include "route_properties_box.h"
class AudioRoutePropertiesBox : public RoutePropertiesBox
{
public:
AudioRoutePropertiesBox ();
~AudioRoutePropertiesBox ();
private:
};

View File

@ -61,6 +61,7 @@ using namespace Gtk;
using namespace Gtkmm2ext;
using namespace PBD;
using namespace Temporal;
using namespace ArdourWidgets;
using std::string;
sigc::signal<void> EditingContext::DropDownKeys;
@ -124,11 +125,15 @@ EditingContext::EditingContext (std::string const & name)
#endif
, _snap_mode (SnapOff)
, _timeline_origin (0.)
, play_note_selection_button (_("Ear"), ArdourButton::Text, true)
, follow_playhead_button (_("F"), ArdourButton::Text, true)
, full_zoom_button (_("<->"), ArdourButton::Text)
, _drags (new DragManager (this))
, _leftmost_sample (0)
, _playhead_cursor (nullptr)
, _snapped_cursor (nullptr)
, _follow_playhead (false)
, visible_channel_label (_("MIDI|Channel"))
, selection (new Selection (this, true))
, cut_buffer (new Selection (this, false))
, _selection_memento (new SelectionMemento())
@ -153,6 +158,8 @@ EditingContext::EditingContext (std::string const & name)
, entered_regionview (nullptr)
, clear_entered_track (false)
{
using namespace Gtk::Menu_Helpers;
if (!button_bindings) {
button_bindings = new Bindings ("editor-mouse");
@ -188,15 +195,46 @@ EditingContext::EditingContext (std::string const & name)
set_tooltip (grid_type_selector, _("Grid Mode"));
set_tooltip (snap_mode_button, _("Snap Mode\n\nRight-click to visit Snap preferences."));
set_tooltip (play_note_selection_button, _("Play notes when selected"));
set_tooltip (follow_playhead_button, _("Scroll automatically to keep playhead visible"));
/* Leave tip for full zoom button to derived class */
set_tooltip (visible_channel_selector, _("Select visible MIDI channel"));
play_note_selection_button.signal_clicked.connect (sigc::mem_fun (*this, &EditingContext::play_note_selection_clicked));
follow_playhead_button.signal_clicked.connect (sigc::mem_fun (*this, &EditingContext::follow_playhead_clicked));
full_zoom_button.signal_clicked.connect (sigc::mem_fun (*this, &EditingContext::full_zoom_clicked));
for (int i = 0; i < 16; i++) {
char buf[4];
sprintf(buf, "%d", i+1);
visible_channel_selector.AddMenuElem (MenuElem (buf, [this,i]() { EditingContext::set_visible_channel (i); }));
}
/* handle escape */
ARDOUR_UI::instance()->Escape.connect (escape_connection, MISSING_INVALIDATOR, std::bind (&EditingContext::escape, this), gui_context());
Config->ParameterChanged.connect (parameter_connections, MISSING_INVALIDATOR, std::bind (&EditingContext::parameter_changed, this, _1), gui_context());
UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &EditingContext::ui_parameter_changed));
}
EditingContext::~EditingContext()
{
}
void
EditingContext::ui_parameter_changed (string parameter)
{
if (parameter == "sound-midi-note") {
}
}
void
EditingContext::parameter_changed (string parameter)
{
}
void
EditingContext::set_session (ARDOUR::Session* s)
{
@ -2043,6 +2081,7 @@ EditingContext::set_canvas_cursor (Gdk::Cursor* cursor)
For now, drop down and use C API
*/
gdk_window_set_cursor (win->gobj(), cursor ? cursor->gobj() : 0);
gdk_flush ();
}
}
@ -2050,6 +2089,12 @@ size_t
EditingContext::push_canvas_cursor (Gdk::Cursor* cursor)
{
if (!_cursors->is_invalid (cursor)) {
if (!_cursor_stack.empty()) {
if (cursor == _cursor_stack.back()) {
return _cursor_stack.size() - 1;
}
}
_cursor_stack.push_back (cursor);
set_canvas_cursor (cursor);
}
@ -2066,7 +2111,7 @@ EditingContext::pop_canvas_cursor ()
}
_cursor_stack.pop_back();
if (_cursor_stack.back()) {
if (!_cursor_stack.empty()) {
/* Popped to an existing cursor, we're done. Otherwise, the
context that created this cursor has been destroyed, so we need
to skip to the next down the stack. */
@ -2769,4 +2814,12 @@ EditingContext::update_all_enter_cursors ()
}
}
void
EditingContext::play_note_selection_clicked ()
{
}
void
EditingContext::follow_playhead_clicked ()
{
}

View File

@ -494,6 +494,17 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
void snap_mode_chosen (Editing::SnapMode);
void grid_type_chosen (Editing::GridType);
ArdourWidgets::ArdourButton play_note_selection_button;
ArdourWidgets::ArdourButton follow_playhead_button;
ArdourWidgets::ArdourButton full_zoom_button;
Gtk::Label visible_channel_label;
ArdourWidgets::ArdourDropdown visible_channel_selector;
virtual void play_note_selection_clicked();
virtual void follow_playhead_clicked ();
virtual void full_zoom_clicked() {};
virtual void set_visible_channel (int) {}
DragManager* _drags;
ArdourWidgets::ArdourButton snap_mode_button;
@ -674,6 +685,10 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
uint32_t autoscroll_cnt;
ArdourCanvas::Rect autoscroll_boundary;
PBD::ScopedConnectionList parameter_connections;
virtual void parameter_changed (std::string);
virtual void ui_parameter_changed (std::string);
bool _mouse_changed_selection;
ArdourMarker* entered_marker;
TimeAxisView* entered_track;

View File

@ -305,8 +305,8 @@ Editor::Editor ()
, controls_layout (unused_adjustment, vertical_adjustment)
, _scroll_callbacks (0)
, _full_canvas_height (0)
, edit_controls_left_menu (nullptr)
, edit_controls_right_menu (nullptr)
, edit_controls_left_menu (0)
, edit_controls_right_menu (0)
, _trigger_clip_picker (nullptr)
, _tvl_no_redisplay(false)
, _tvl_redisplay_on_resume(false)
@ -651,20 +651,11 @@ Editor::Editor ()
Location::end_changed.connect (*this, invalidator (*this), std::bind (&Editor::location_changed, this, _1), gui_context());
Location::changed.connect (*this, invalidator (*this), std::bind (&Editor::location_changed, this, _1), gui_context());
#if SELECTION_PROPERTIES_BOX_TODO
add_notebook_page (_("Selection"), *_properties_box);
#warning Fix Properties Sidebar Layout to fit < 720px height
#endif
if (!Profile->get_livetrax()) {
if (!Profile->get_livetrax()) {
_trigger_clip_picker = manage (new TriggerClipPicker ());
}
#ifndef LIVETRAX
add_notebook_page (_("Tracks & Busses"), _routes->widget ());
add_notebook_page (_("Sources"), _sources->widget ());
add_notebook_page (_("Regions"), _regions->widget ());
add_notebook_page (_("Clips"), *_trigger_clip_picker);
add_notebook_page (_("Clips"), _trigger_clip_picker);
add_notebook_page (_("Arrangement"), _sections->widget ());
add_notebook_page (_("Snapshots"), _snapshots->widget ());
add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
@ -675,7 +666,7 @@ Editor::Editor ()
_the_notebook.popup_disable ();
_the_notebook.set_tab_pos (Gtk::POS_RIGHT);
_the_notebook.show_all ();
}
#endif
_notebook_shrunk = false;
@ -688,14 +679,38 @@ Editor::Editor ()
settings->get_property ("notebook-shrunk", _notebook_shrunk);
}
if (!Profile->get_livetrax()) {
#ifndef LIVETRAX
editor_summary_pane.set_check_divider_position (true);
editor_summary_pane.add (edit_packer);
Button* summary_arrow_left = manage (new Button);
summary_arrow_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
summary_arrow_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
summary_arrow_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
Button* summary_arrow_right = manage (new Button);
summary_arrow_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
summary_arrow_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
summary_arrow_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
VBox* summary_arrows_left = manage (new VBox);
summary_arrows_left->pack_start (*summary_arrow_left);
VBox* summary_arrows_right = manage (new VBox);
summary_arrows_right->pack_start (*summary_arrow_right);
Gtk::Frame* summary_frame = manage (new Gtk::Frame);
summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
summary_frame->add (*_summary);
summary_frame->show ();
_summary_hbox.pack_start (*summary_arrows_left, false, false);
_summary_hbox.pack_start (*summary_frame, true, true);
_summary_hbox.pack_start (*summary_arrows_right, false, false);
editor_summary_pane.add (_summary_hbox);
_editor_list_vbox.pack_start (_the_notebook);
_editor_list_vbox.pack_start (*_properties_box, false, false, 0);
content_right_pane.set_drag_cursor (*_cursors->expand_left_right);
editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
@ -705,12 +720,13 @@ Editor::Editor ()
/* initial allocation is 90% to canvas, 10% to summary */
fract = 0.90;
}
}
editor_summary_pane.set_divider (0, fract);
#endif
global_vpacker.set_spacing (0);
global_vpacker.set_border_width (0);
if (!Profile->get_livetrax()) {
#ifndef LIVETRAX
ArdourWidgets::ArdourDropShadow *toolbar_shadow = manage (new (ArdourWidgets::ArdourDropShadow));
toolbar_shadow->set_size_request (-1, 4);
toolbar_shadow->set_mode(ArdourWidgets::ArdourDropShadow::DropShadowBoth);
@ -724,6 +740,7 @@ Editor::Editor ()
*/
content_app_bar.add (_application_bar);
content_att_right.add (_editor_list_vbox);
content_att_bottom.add (*_properties_box);
content_toolbar.add (global_vpacker);
content_innermost_hbox.add (editor_summary_pane);
@ -733,11 +750,11 @@ Editor::Editor ()
content_hbox.show ();
ebox_hpacker.show();
global_vpacker.show();
} else {
#else /* LIVETRAX */
global_vpacker.pack_start (edit_packer, true, true);
content_innermost_hbox.add (global_vpacker);
global_vpacker.show();
}
#endif
/* register actions now so that set_state() can find them and set toggles/checks etc */
@ -784,9 +801,6 @@ Editor::Editor ()
Session::AskAboutPlaylistDeletion.connect_same_thread (*this, std::bind (&Editor::playlist_deletion_dialog, this, _1));
Route::PluginSetup.connect_same_thread (*this, std::bind (&Editor::plugin_setup, this, _1, _2, _3));
Config->ParameterChanged.connect (*this, invalidator (*this), std::bind (&Editor::parameter_changed, this, _1), gui_context());
UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), std::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
_ignore_region_action = false;
@ -2350,6 +2364,15 @@ Editor::set_state (const XMLNode& node, int version)
tact->set_active (yn);
}
yn = false;
node.get_property ("show-editor-props", yn);
{
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Editor"), X_("show-editor-props"));
/* do it twice to force the change */
tact->set_active (!yn);
tact->set_active (yn);
}
int32_t el_page;
if (node.get_property (X_("editor-list-page"), el_page)) {
_the_notebook.set_current_page (el_page);
@ -2457,6 +2480,9 @@ Editor::get_state () const
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_("editor-list-page"), _the_notebook.get_current_page ());
if (button_bindings) {
@ -5841,6 +5867,8 @@ Editor::zoom_vertical_modifier_released()
void
Editor::ui_parameter_changed (string parameter)
{
EditingContext::ui_parameter_changed (parameter);
if (parameter == "icon-set") {
while (!_cursor_stack.empty()) {
_cursor_stack.pop_back();

View File

@ -1100,7 +1100,7 @@ Editor::marker_click_behavior_chosen (Editing::MarkerClickBehavior m)
void
Editor::parameter_changed (std::string p)
{
ENSURE_GUI_THREAD (*this, &Editor::parameter_changed, p)
EditingContext::parameter_changed (p);
if (p == "auto-loop") {
update_loop_range_view ();

View File

@ -7540,3 +7540,81 @@ VelocityLineDrag::aborted (bool)
{
vd->end_line_drag (false);
}
ClipStartDrag::ClipStartDrag (EditingContext& ec, ArdourCanvas::Rectangle& r, Temporal::timepos_t const & os)
: Drag (ec, &r, os.time_domain(), nullptr, false)
, dragging_rect (&r)
, original_start (os)
{
}
ClipStartDrag::~ClipStartDrag ()
{
}
void
ClipStartDrag::start_grab (GdkEvent* ev,Gdk::Cursor* c)
{
Drag::start_grab (ev, c);
}
bool
ClipStartDrag::end_grab (GdkEvent* ev)
{
Drag::end_grab (ev);
return false;
}
void
ClipStartDrag::motion (GdkEvent*, bool)
{
}
void
ClipStartDrag::finished (GdkEvent*, bool)
{
}
void
ClipStartDrag::aborted (bool)
{
}
ClipEndDrag::ClipEndDrag (EditingContext& ec, ArdourCanvas::Rectangle& r, Temporal::timepos_t const & oe)
: Drag (ec, &r, oe.time_domain(), nullptr, false)
, dragging_rect (&r)
, original_end (oe)
{
}
ClipEndDrag::~ClipEndDrag ()
{
}
void
ClipEndDrag::start_grab (GdkEvent* ev,Gdk::Cursor* c)
{
Drag::start_grab (ev, c);
}
bool
ClipEndDrag::end_grab (GdkEvent* ev)
{
Drag::end_grab (ev);
return false;
}
void
ClipEndDrag::motion (GdkEvent*, bool)
{
}
void
ClipEndDrag::finished (GdkEvent*, bool)
{
}
void
ClipEndDrag::aborted (bool)
{
}

View File

@ -1640,6 +1640,39 @@ class VelocityLineDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoi
bool drag_did_change;
};
class ClipStartDrag : public Drag
{
public:
ClipStartDrag (EditingContext&, ArdourCanvas::Rectangle &, Temporal::timepos_t const &);
~ClipStartDrag ();
void start_grab (GdkEvent*,Gdk::Cursor*);
bool end_grab (GdkEvent*);
void motion (GdkEvent*, bool);
void finished (GdkEvent*, bool);
void aborted (bool);
private:
ArdourCanvas::Rectangle* dragging_rect;
Temporal::timepos_t original_start;
};
class ClipEndDrag : public Drag
{
public:
ClipEndDrag (EditingContext&, ArdourCanvas::Rectangle &, Temporal::timepos_t const &);
~ClipEndDrag ();
void start_grab (GdkEvent*,Gdk::Cursor*);
bool end_grab (GdkEvent*);
void motion (GdkEvent*, bool);
void finished (GdkEvent*, bool);
void aborted (bool);
private:
ArdourCanvas::Rectangle* dragging_rect;
Temporal::timepos_t original_end;
};
#endif /* __gtk2_ardour_editor_drag_h_ */

View File

@ -69,6 +69,8 @@ enum ItemType {
GridZoneItem,
VelocityItem,
VelocityBaseItem,
ClipStartItem,
ClipEndItem,
/* don't remove this */

View File

@ -31,6 +31,8 @@
#include "gtkmm2ext/actions.h"
#include "widgets/ardour_button.h"
#include "widgets/ardour_dropdown.h"
#include "widgets/tooltips.h"
#include "ardour_ui.h"
#include "editor_cursors.h"
@ -74,10 +76,9 @@ MidiCueEditor::MidiCueEditor()
build_grid_type_menu ();
build_draw_midi_menus();
build_upper_toolbar ();
build_canvas ();
setup_toolbar ();
_toolbox.pack_start (viewport(), true, true);
build_lower_toolbar ();
set_mouse_mode (Editing::MouseContent, true);
}
@ -126,8 +127,36 @@ MidiCueEditor::canvas_pre_event (GdkEvent* ev)
}
void
MidiCueEditor::setup_toolbar ()
MidiCueEditor::build_lower_toolbar ()
{
velocity_button = new ArdourButton (_("Velocity"), ArdourButton::Text, true);
bender_button = new ArdourButton (_("Bender"), ArdourButton::Text, true);
pressure_button = new ArdourButton (_("Pressure"), ArdourButton::Text, true);
expression_button = new ArdourButton (_("Expression"), ArdourButton::Text, true);
modulation_button = new ArdourButton (_("Modulation"), ArdourButton::Text, true);
// button_bar.set_homogeneous (true);
button_bar.set_spacing (6);
button_bar.set_border_width (6);
button_bar.pack_start (*velocity_button, false, false);
button_bar.pack_start (*bender_button, false, false);
button_bar.pack_start (*pressure_button, false, false);
button_bar.pack_start (*modulation_button, false, false);
velocity_button->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &MidiCueEditor::automation_button_event), ARDOUR::MidiVelocityAutomation, 0), false);
pressure_button->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &MidiCueEditor::automation_button_event), ARDOUR::MidiChannelPressureAutomation, 0), false);
bender_button->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &MidiCueEditor::automation_button_event), ARDOUR::MidiPitchBenderAutomation, 0), false);
modulation_button->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &MidiCueEditor::automation_button_event), ARDOUR::MidiCCAutomation, MIDI_CTL_MSB_MODWHEEL), false);
expression_button->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &MidiCueEditor::automation_button_event), ARDOUR::MidiCCAutomation, MIDI_CTL_MSB_EXPRESSION), false);
_toolbox.pack_start (button_bar, false, false);
}
void
MidiCueEditor::build_upper_toolbar ()
{
using namespace Gtk::Menu_Helpers;
Gtk::HBox* mode_box = manage(new Gtk::HBox);
mode_box->set_border_width (2);
mode_box->set_spacing(2);
@ -169,13 +198,28 @@ MidiCueEditor::setup_toolbar ()
_toolbar_inner->pack_start (grid_box, false, false);
_toolbar_inner->pack_start (draw_box, false, false);
set_tooltip (full_zoom_button, _("Zoom to full clip"));
_toolbar_outer->set_border_width (6);
_toolbar_outer->set_spacing (12);
_toolbar_outer->pack_start (visible_channel_label, false, false);
_toolbar_outer->pack_start (visible_channel_selector, false, false);
_toolbar_outer->pack_start (play_note_selection_button, false, false);
_toolbar_outer->pack_start (follow_playhead_button, false, false);
_toolbar_outer->pack_start (full_zoom_button, false, false);
_toolbar_outer->pack_start (*_toolbar_inner, true, false);
_toolbox.pack_start (*_toolbar_outer, false, false);
Bindings* pr_bindings = Bindings::get_bindings (X_("Pianoroll"));
_toolbox.set_data (X_("ardour-bindings"), pr_bindings);
}
void
MidiCueEditor::set_visible_channel (int n)
{
}
void
MidiCueEditor::build_canvas ()
{
@ -268,7 +312,7 @@ MidiCueEditor::build_canvas ()
prh = new ArdourCanvas::PianoRollHeader (v_scroll_group, *bg);
view = new MidiCueView (nullptr, 0, *data_group, *this, *bg, 0xff0000ff);
view = new MidiCueView (nullptr, 0, *data_group, *no_scroll_group, *this, *bg, 0xff0000ff);
bg->set_view (view);
prh->set_view (view);
@ -282,6 +326,7 @@ MidiCueEditor::build_canvas ()
prh->set_position (Duple (0., n_timebars * timebar_height));
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.));
@ -292,11 +337,14 @@ MidiCueEditor::build_canvas ()
_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 ("MidiCueCanvas");
_canvas->add_events (Gdk::POINTER_MOTION_HINT_MASK | Gdk::SCROLL_MASK | Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
_canvas->set_can_focus ();
_toolbox.pack_start (*_canvas_viewport, true, true);
bindings_changed ();
}
@ -317,11 +365,6 @@ MidiCueEditor::maybe_update ()
return;
}
if (_track->rec_enable_control()->get_value()) {
/* ::data_captured() will handle it */
return;
}
ARDOUR::TriggerPtr trigger = _track->triggerbox()->currently_playing ();
if (!trigger) {
@ -1613,8 +1656,6 @@ MidiCueEditor::which_canvas_cursor (ItemType type) const
bool
MidiCueEditor::enter_handler (ArdourCanvas::Item* item, GdkEvent* ev, ItemType item_type)
{
EditorAutomationLine* al;
choose_canvas_cursor_on_entry (item_type);
switch (item_type) {
@ -1752,6 +1793,8 @@ MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiRegion> r)
}
view->set_region (r);
view->show_start (true);
view->show_end (true);
/* Compute zoom level to show entire source plus some margin if possible */
@ -1774,9 +1817,36 @@ MidiCueEditor::set_region (std::shared_ptr<ARDOUR::MidiRegion> r)
{
EditingContext::TempoMapScope tms (*this, map);
double width = bg->width();
samplecnt_t samples = duration.samples();
/* make it 20% wider than we need */
samplecnt_t samples = (samplecnt_t) floor (1.2 * duration.samples());
std::cerr << "new spp from " << samples << " / " << width << std::endl;
samplecnt_t spp = floor (samples / width);
reset_zoom (spp);
}
}
bool
MidiCueEditor::automation_button_event (GdkEventButton* ev, Evoral::ParameterType type, int id)
{
SelectionOperation op = ArdourKeyboard::selection_type (ev->state);
switch (ev->type) {
case GDK_BUTTON_RELEASE:
automation_button_click (type, id, op);
break;
default:
break;
}
return false;
}
void
MidiCueEditor::automation_button_click (Evoral::ParameterType type, int id, SelectionOperation op)
{
#warning paul allow channel selection (2nd param)
if (view) {
view->update_automation_display (Evoral::Parameter (type, 0, id), op);
}
}

View File

@ -109,6 +109,8 @@ class MidiCueEditor : public CueEditor
Gdk::Cursor* which_trim_cursor (bool left_side) const;
Gdk::Cursor* which_canvas_cursor (ItemType type) const;
void set_visible_channel (int chan);
protected:
void register_actions ();
@ -171,11 +173,20 @@ class MidiCueEditor : public CueEditor
Gtk::VBox _toolbox;
Gtk::HBox button_bar;
ArdourWidgets::ArdourButton* velocity_button;
ArdourWidgets::ArdourButton* bender_button;
ArdourWidgets::ArdourButton* pressure_button;
ArdourWidgets::ArdourButton* expression_button;
ArdourWidgets::ArdourButton* modulation_button;
CueMidiBackground* bg;
MidiCueView* view;
void build_canvas ();
void canvas_allocate (Gtk::Allocation);
void build_upper_toolbar ();
void build_lower_toolbar ();
RegionSelection region_selection();
@ -199,7 +210,6 @@ class MidiCueEditor : public CueEditor
BBTMetric bbt_metric;
bool canvas_pre_event (GdkEvent*);
void setup_toolbar ();
/* autoscrolling */
@ -222,6 +232,11 @@ class MidiCueEditor : public CueEditor
std::atomic<int> idle_update_queued;
PBD::ScopedConnectionList capture_connections;
samplecnt_t data_capture_duration;
bool automation_button_event (GdkEventButton*, Evoral::ParameterType type, int id);
void automation_button_click (Evoral::ParameterType type, int id, ARDOUR::SelectionOperation);
int _visible_channel;
};

View File

@ -48,6 +48,7 @@ using namespace Gtkmm2ext;
MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
uint32_t slot_index,
ArdourCanvas::Item& parent,
ArdourCanvas::Item& noscroll_parent,
EditingContext& ec,
MidiViewBackground& bg,
uint32_t basic_color)
@ -55,11 +56,10 @@ MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
, active_automation (nullptr)
, velocity_display (nullptr)
, _slot_index (slot_index)
, _height (0.)
{
CANVAS_DEBUG_NAME (_note_group, X_("note group for MIDI cue"));
_needs_active_notes_for_rec_enabled_track = true;
/* Containers don't get canvas events, so we need an invisible rect
* that will. It will be resized as needed sothat it always covers the
* entire canvas/view.
@ -79,46 +79,8 @@ MidiCueView::MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
automation_group->set_fill_color (UIConfiguration::instance().color ("midi automation track fill"));
automation_group->set_data ("linemerger", this);
button_bar = new ArdourCanvas::Box (&parent, ArdourCanvas::Box::Horizontal);
CANVAS_DEBUG_NAME (button_bar, "button bar");
button_bar->set_spacing (12.);
/* Right-side padding only */
button_bar->set_padding (0., 0., 0., 24.);
button_bar->set_margin (5., 5., 5., 5.);
Pango::FontDescription button_font = UIConfiguration::instance().get_NormalFont();
velocity_button = new ArdourCanvas::Button (button_bar, _("Velocity"), button_font);
velocity_button->text()->set_color (UIConfiguration::instance().color ("neutral:foreground"));
CANVAS_DEBUG_NAME (velocity_button, "velocity button");
bender_button = new ArdourCanvas::Button (button_bar, _("Bender"), button_font);
bender_button->text()->set_color (UIConfiguration::instance().color ("neutral:foreground"));
CANVAS_DEBUG_NAME (bender_button, "bender button");
pressure_button = new ArdourCanvas::Button (button_bar, _("Pressure"), button_font);
pressure_button->text()->set_color (UIConfiguration::instance().color ("neutral:foreground"));
CANVAS_DEBUG_NAME (pressure_button, "pressure button");
expression_button = new ArdourCanvas::Button (button_bar, _("Expression"), button_font);
expression_button->text()->set_color (UIConfiguration::instance().color ("neutral:foreground"));
CANVAS_DEBUG_NAME (expression_button, "expression button");
modulation_button = new ArdourCanvas::Button (button_bar, _("Modulation"), button_font);
modulation_button->text()->set_color (UIConfiguration::instance().color ("neutral:foreground"));
CANVAS_DEBUG_NAME (modulation_button, "modulation button");
velocity_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &MidiCueView::automation_button_event), ARDOUR::MidiVelocityAutomation, 0));
pressure_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &MidiCueView::automation_button_event), ARDOUR::MidiChannelPressureAutomation, 0));
bender_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &MidiCueView::automation_button_event), ARDOUR::MidiPitchBenderAutomation, 0));
modulation_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &MidiCueView::automation_button_event), ARDOUR::MidiCCAutomation, MIDI_CTL_MSB_MODWHEEL));
expression_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &MidiCueView::automation_button_event), ARDOUR::MidiCCAutomation, MIDI_CTL_MSB_EXPRESSION));
set_extensible (true);
/* show velocity by default */
update_automation_display (Evoral::Parameter (MidiVelocityAutomation, 0, 0), SelectionSet);
}
MidiCueView::~MidiCueView ()
@ -129,11 +91,18 @@ MidiCueView::~MidiCueView ()
void
MidiCueView::set_height (double h)
{
double bbw, bbh;
button_bar->size_request (bbw, bbh);
_height = h;
double note_area_height = ceil ((h - bbh) / 2.);
double automation_height = ceil (h - bbh - note_area_height);
double note_area_height;
double automation_height;
if (automation_map.empty()) {
note_area_height = h;
automation_height = 0.;
} else {
note_area_height = ceil (h / 2.);
automation_height = ceil (h - note_area_height);
}
event_rect->set (ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, note_area_height));
midi_context().set_size (midi_context().width(), note_area_height);
@ -141,8 +110,6 @@ MidiCueView::set_height (double h)
automation_group->set_position (ArdourCanvas::Duple (0., note_area_height));
automation_group->set (ArdourCanvas::Rect (0., 0., ArdourCanvas::COORD_MAX, automation_height));
button_bar->size_allocate (ArdourCanvas::Rect (0., note_area_height + automation_height, ArdourCanvas::COORD_MAX, note_area_height + automation_height + bbh));
for (auto & ads : automation_map) {
ads.second.set_height (automation_height);
}
@ -275,29 +242,6 @@ MidiCueView::update_hit (Hit* h)
}
}
bool
MidiCueView::automation_button_event (GdkEvent* ev, Evoral::ParameterType type, int id)
{
SelectionOperation op = ArdourKeyboard::selection_type (ev->button.state);
switch (ev->type) {
case GDK_BUTTON_RELEASE:
automation_button_click (type, id, op);
break;
default:
break;
}
return false;
}
void
MidiCueView::automation_button_click (Evoral::ParameterType type, int id, SelectionOperation op)
{
#warning paul allow channel selection (2nd param)
update_automation_display (Evoral::Parameter (type, 0, id), op);
}
void
MidiCueView::update_automation_display (Evoral::Parameter const & param, SelectionOperation op)
{
@ -413,6 +357,8 @@ MidiCueView::update_automation_display (Evoral::Parameter const & param, Selecti
/* undefined in this context */
break;
}
set_height (_height);
}
std::list<SelectableOwner*>

View File

@ -35,7 +35,6 @@ class MidiCueAutomationLine;
namespace ArdourCanvas {
class Box;
class Button;
}
class MidiCueView : public MidiView
@ -44,6 +43,7 @@ class MidiCueView : public MidiView
MidiCueView (std::shared_ptr<ARDOUR::MidiTrack> mt,
uint32_t slot_index,
ArdourCanvas::Item& parent,
ArdourCanvas::Item& noscroll_parent,
EditingContext& ec,
MidiViewBackground& bg,
uint32_t basic_color
@ -109,13 +109,6 @@ class MidiCueView : public MidiView
VelocityDisplay* velocity_display;
ArdourCanvas::Box* button_bar;
ArdourCanvas::Button* velocity_button;
ArdourCanvas::Button* bender_button;
ArdourCanvas::Button* pressure_button;
ArdourCanvas::Button* expression_button;
ArdourCanvas::Button* modulation_button;
std::shared_ptr<Temporal::TempoMap const> tempo_map;
ArdourCanvas::Rectangle* event_rect;
uint32_t _slot_index;
@ -123,6 +116,5 @@ class MidiCueView : public MidiView
void update_sustained (Note *);
void update_hit (Hit *);
bool automation_button_event (GdkEvent*, Evoral::ParameterType type, int id);
void automation_button_click (Evoral::ParameterType type, int id, ARDOUR::SelectionOperation);
double _height;
};

View File

@ -120,9 +120,10 @@ MidiView::MidiView (std::shared_ptr<MidiTrack> mt,
, _step_edit_cursor (0)
, _step_edit_cursor_width (1, 0)
, _channel_selection_scoped_note (0)
, _needs_active_notes_for_rec_enabled_track (false)
, _mouse_state(None)
, _pressed_button(0)
, _start_boundary_rect (nullptr)
, _end_boundary_rect (nullptr)
, _optimization_iterator (_events.end())
, _list_editor (nullptr)
, _no_sound_notes (false)
@ -152,7 +153,6 @@ MidiView::MidiView (MidiView const & other)
, _step_edit_cursor (0)
, _step_edit_cursor_width (1, 0)
, _channel_selection_scoped_note (0)
, _needs_active_notes_for_rec_enabled_track (false)
, _mouse_state(None)
, _pressed_button(0)
, _optimization_iterator (_events.end())
@ -186,6 +186,52 @@ MidiView::init (std::shared_ptr<MidiTrack> mt)
_midi_context.NoteRangeChanged.connect (sigc::mem_fun (*this, &MidiView::view_changed));
}
void
MidiView::show_start (bool yn)
{
if (!yn) {
delete _start_boundary_rect;
_start_boundary_rect = nullptr;
return;
}
if (!_midi_region) {
return;
}
if (!_start_boundary_rect) {
_start_boundary_rect = new ArdourCanvas::Rectangle (_note_group->parent());
_start_boundary_rect->set_fill_color (0xff000087);
_start_boundary_rect->set_outline_color (0xff0000ff);
}
double width = _editing_context.sample_to_pixel (_midi_region->start().samples());
_start_boundary_rect->set (ArdourCanvas::Rect (0., 0., width, height()));
}
void
MidiView::show_end (bool yn)
{
if (!yn) {
delete _end_boundary_rect;
_end_boundary_rect = nullptr;
return;
}
if (!_midi_region) {
return;
}
if (!_end_boundary_rect) {
_end_boundary_rect = new ArdourCanvas::Rectangle (_note_group->parent());
_end_boundary_rect->set_fill_color (0xff000087);
_end_boundary_rect->set_outline_color (0xff0000ff);
}
double offset = _editing_context.sample_to_pixel ((_midi_region->start() + _midi_region->length()).samples());
_end_boundary_rect->set (ArdourCanvas::Rect (offset, 0., ArdourCanvas::COORD_MAX, height()));
}
void
MidiView::set_track (std::shared_ptr<MidiTrack> mt)
{

View File

@ -348,6 +348,9 @@ class MidiView : public virtual sigc::trackable, public LineMerger
void select_self () { select_self (false); }
virtual void select_self_uniquely () {}
void show_start (bool yn);
void show_end (bool yn);
protected:
void init (std::shared_ptr<ARDOUR::MidiTrack>);
virtual void region_resized (const PBD::PropertyChange&);
@ -503,9 +506,10 @@ class MidiView : public virtual sigc::trackable, public LineMerger
Temporal::Beats _step_edit_cursor_width;
Temporal::Beats _step_edit_cursor_position;
NoteBase* _channel_selection_scoped_note;
bool _needs_active_notes_for_rec_enabled_track;
MouseState _mouse_state;
int _pressed_button;
ArdourCanvas::Rectangle* _start_boundary_rect;
ArdourCanvas::Rectangle* _end_boundary_rect;
/** Currently selected NoteBase objects */
Selection _selection;

View File

@ -133,7 +133,7 @@ Mixer_UI::instance ()
}
Mixer_UI::Mixer_UI ()
: Tabbable (_("Mixer"), X_("mixer"))
: Tabbable (_("Mixer"), X_("mixer"), NULL, true, Tabbable::NoPanes)
, plugin_search_clear_button (X_("Clear"))
, _mixer_scene_release (0)
, no_track_list_redisplay (false)
@ -164,13 +164,6 @@ Mixer_UI::Mixer_UI ()
contents().set_data ("ardour-bindings", bindings);
if (!Profile->get_mixbus ()) {
right_attachment_button.set_sensitive(false);
} else {
left_attachment_button.set_sensitive(false);
}
bottom_attachment_button.set_sensitive(false);
PresentationInfo::Change.connect (*this, invalidator (*this), std::bind (&Mixer_UI::presentation_info_changed, this, _1), gui_context());
Route::FanOut.connect (*this, invalidator (*this), std::bind (&Mixer_UI::fan_out, this, _1, false, true), gui_context());
@ -390,7 +383,7 @@ Mixer_UI::Mixer_UI ()
favorite_plugins_scroller.show();
group_display_vbox.show();
group_display_frame.show();
favorite_plugins_frame.show();
favorite_plugins_frame.show_all();
rhs_pane1.show();
rhs_pane2.show();
strip_packer.show();
@ -3737,7 +3730,6 @@ Mixer_UI::register_actions ()
act = ActionManager::register_toggle_action (group, "ToggleMixerList", _("(Mixer) Show Sidebar List"), sigc::mem_fun (*this, &Tabbable::att_left_button_toggled));
left_attachment_button.set_related_action (act);
act = ActionManager::register_toggle_action (group, "ToggleMixerStrip", _("(Mixer) Show Sidebar Strip"), []{});
content_right_pane.remove(content_right_vbox);
} else {
act = ActionManager::register_toggle_action (group, "ToggleMixerList", _("(Mixer) Show Sidebar List"), sigc::mem_fun (*this, &Tabbable::att_right_button_toggled));
right_attachment_button.set_related_action (act);
@ -3748,7 +3740,6 @@ Mixer_UI::register_actions ()
act = ActionManager::register_toggle_action (group, "ToggleMixerProps", _("(Mixer) Show Properties Bottom"), sigc::mem_fun (*this, &Tabbable::att_bottom_button_toggled));
bottom_attachment_button.set_related_action (act);
#else
content_right_pane.remove(content_right_vbox);
act = ActionManager::register_toggle_action (group, "ToggleMixerProps", _("(Mixer) Show Properties Bottom"), []{});
act = ActionManager::register_toggle_action (group, "ToggleMixerStrip", _("(Mixer) Show Sidebar Strip"), []{});
act = ActionManager::register_toggle_action (group, "ToggleMixerList", _("(Mixer) Show Sidebar List"), []{});

View File

@ -153,8 +153,6 @@ public:
void toggle_mixer_strip ();
void toggle_mixer_props ();
void showhide_mixer_list (bool yn);
void toggle_surround_master ();
void toggle_monitor_section ();

View File

@ -37,6 +37,7 @@
#include "gui_thread.h"
#include "midi_view.h"
#include "midi_view_background.h"
#include "mouse_cursors.h"
#include "prh.h"
#include "editing_context.h"
#include "ui_config.h"
@ -630,21 +631,19 @@ PianoRollHeader::motion_handler (GdkEventMotion* ev)
if (!_scroomer_drag && ev->x < _scroomer_size){
Gdk::Cursor m_Cursor;
double scroomer_top = max (1.0, (1.0 - ((_adj.get_value()+_adj.get_page_size()) / 127.0)) * get().height());
double scroomer_bottom = (1.0 - (_adj.get_value () / 127.0)) * get().height();
double edge = 5. * UIConfiguration::instance().get_ui_scale();
if (evd.y > scroomer_top - 5 && evd.y < scroomer_top + 5){
m_Cursor = Gdk::Cursor (Gdk::TOP_SIDE);
_view->editing_context().push_canvas_cursor (&m_Cursor);
if (evd.y > scroomer_top - 5 && evd.y < scroomer_top + edge){
_view->editing_context().push_canvas_cursor (_view->editing_context().cursors()->resize_top);
_scroomer_state = TOP;
} else if (evd.y > scroomer_bottom - 5 && evd.y < scroomer_bottom + 5){
m_Cursor = Gdk::Cursor (Gdk::BOTTOM_SIDE);
_view->editing_context().push_canvas_cursor (&m_Cursor);
} else if (evd.y > scroomer_bottom - edge && evd.y < scroomer_bottom + edge){
_view->editing_context().push_canvas_cursor (_view->editing_context().cursors()->resize_bottom);
_scroomer_state = BOTTOM;
} else {
_view->editing_context().push_canvas_cursor (_view->editing_context().cursors()->grabber);
_scroomer_state = MOVE;
_view->editing_context().pop_canvas_cursor ();
}
}

View File

@ -33,7 +33,7 @@ ARDOUR::DataType PublicEditor::pbdid_dragged_dt = ARDOUR::DataType::NIL;
PublicEditor::PublicEditor ()
: EditingContext (X_("Editor"))
, Tabbable (_("Editor"), X_("editor"))
, Tabbable (_("Editor"), X_("editor"), NULL, true, Tabbable::NoPanes)
, mouse_mode_hbox (nullptr)
{
_suspend_route_redisplay_counter.store (0);

View File

@ -78,7 +78,7 @@ using namespace Menu_Helpers;
#define PX_SCALE(px) std::max ((float)px, rintf ((float)px* UIConfiguration::instance ().get_ui_scale ()))
RecorderUI::RecorderUI ()
: Tabbable (_("Recorder"), X_("recorder"))
: Tabbable (_("Recorder"), X_("recorder"), NULL, true, Tabbable::NoPanes)
, _toolbar_sep (1.0)
, _btn_rec_all (_("All"))
, _btn_rec_none (_("None"))
@ -101,11 +101,6 @@ RecorderUI::RecorderUI ()
load_bindings ();
register_actions ();
content_right_pane.remove(content_right_vbox);
left_attachment_button.set_sensitive(false);
bottom_attachment_button.set_sensitive(false);
right_attachment_button.set_sensitive(false);
/* monitoring */
_auto_input_button.set_related_action (ActionManager::get_action ("Transport", "ToggleAutoInput"));
_auto_input_button.set_name ("transport option button");

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2011-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2024 Ben Loftis <ben@harrisonconsoles.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "pbd/compose.h"
#include <algorithm>
#include "gtkmm2ext/actions.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h"
#include "ardour/location.h"
#include "ardour/profile.h"
#include "ardour/session.h"
#include "audio_clock.h"
#include "automation_line.h"
#include "control_point.h"
#include "editor.h"
#include "region_view.h"
#include "route_properties_box.h"
#include "pbd/i18n.h"
using namespace Gtk;
using namespace ARDOUR;
using namespace ArdourWidgets;
using std::max;
using std::min;
RoutePropertiesBox::RoutePropertiesBox ()
{
show_all();
}
RoutePropertiesBox::~RoutePropertiesBox ()
{
}
void
RoutePropertiesBox::set_route (std::shared_ptr<ARDOUR::Route> rt)
{
//TODO: route properties
// rt->PropertyChanged.connect (state_connection, invalidator (*this), boost::bind (&RoutePropertiesBox::region_changed, this, _1), gui_context ());
}
void
RoutePropertiesBox::property_changed (const PBD::PropertyChange& what_changed)
{
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2021 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2024 Ben Loftis <ben@harrisonconsoles.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <map>
#include <gtkmm/box.h>
#include <gtkmm/label.h>
#include <gtkmm/table.h>
#include "ardour/ardour.h"
#include "ardour/session_handle.h"
#include "widgets/ardour_button.h"
#include "gtkmm2ext/cairo_packer.h"
#include "region_editor.h"
#include "audio_clock.h"
namespace ARDOUR
{
class Session;
class Location;
}
class RoutePropertiesBox : public Gtk::HBox, public ARDOUR::SessionHandlePtr
{
public:
RoutePropertiesBox ();
~RoutePropertiesBox ();
virtual void set_route (std::shared_ptr<ARDOUR::Route>);
protected:
std::shared_ptr<ARDOUR::Region> _route;
Gtk::Label _header_label;
private:
void property_changed (const PBD::PropertyChange& what_changed);
PBD::ScopedConnection state_connection;
};

View File

@ -46,6 +46,8 @@
#include "slot_properties_box.h"
#include "audio_route_properties_box.h"
#include "selection_properties_box.h"
#include "pbd/i18n.h"
@ -65,12 +67,10 @@ SelectionPropertiesBox::SelectionPropertiesBox ()
_time_info_box = new TimeInfoBox ("EditorTimeInfo", true);
pack_start(*_time_info_box, false, false, 0);
#if SELECTION_PROPERTIES_BOX_TODO
/* Region ops (mute/unmute), for multiple-Region selections */
_mregions_prop_box = new MultiRegionPropertiesBox ();
pack_start(*_mregions_prop_box, false, false, 0);
/* MIDI Region props, for Clips */
_midi_prop_box = new MidiRegionPropertiesBox ();
pack_start(*_midi_prop_box, false, false, 0);
@ -79,7 +79,6 @@ SelectionPropertiesBox::SelectionPropertiesBox ()
_audio_prop_box = new AudioRegionPropertiesBox ();
pack_start(*_audio_prop_box, false, false, 0);
/* MIDI Region ops (transpose, quantize), for only-midi selections */
_midi_ops_box = new MidiRegionOperationsBox ();
pack_start(*_midi_ops_box, false, false, 0);
@ -88,11 +87,62 @@ SelectionPropertiesBox::SelectionPropertiesBox ()
_audio_ops_box = new AudioRegionOperationsBox ();
pack_start(*_audio_ops_box, false, false, 0);
/* SLOT properties, for Trigger slot selections */
_slot_prop_box = new SlotPropertiesBox ();
pack_start(*_slot_prop_box, false, false, 0);
#endif
/* ROUTE properties, for Track selections */
_route_prop_box = new RoutePropertiesBox ();
pack_start(*_route_prop_box, false, false, 0);
_time_info_box->set_no_show_all();
_mregions_prop_box->set_no_show_all();
_audio_prop_box->set_no_show_all();
_midi_ops_box->set_no_show_all();
_audio_ops_box->set_no_show_all();
_slot_prop_box->set_no_show_all();
_route_prop_box->set_no_show_all();
}
SelectionPropertiesBox::~SelectionPropertiesBox ()
{
delete _time_info_box;
delete _mregions_prop_box;
delete _slot_prop_box;
delete _midi_ops_box;
delete _audio_ops_box;
delete _midi_prop_box;
delete _audio_prop_box;
delete _route_prop_box; //todo: split into midi/audio
}
void
SelectionPropertiesBox::set_session (Session* s)
{
SessionHandlePtr::set_session (s);
if (!s) {
return;
}
_time_info_box->set_session(s);
_mregions_prop_box->set_session(s);
_midi_prop_box->set_session(s);
_audio_prop_box->set_session(s);
_midi_ops_box->set_session(s);
_audio_ops_box->set_session(s);
_slot_prop_box->set_session(s);
_route_prop_box->set_session(s);
/* watch for any change in our selection, so we can show an appropriate property editor */
Editor::instance().get_selection().TracksChanged.connect (sigc::mem_fun (*this, &SelectionPropertiesBox::selection_changed));
@ -111,47 +161,6 @@ SelectionPropertiesBox::SelectionPropertiesBox ()
selection_changed();
}
SelectionPropertiesBox::~SelectionPropertiesBox ()
{
delete _time_info_box;
#if SELECTION_PROPERTIES_BOX_TODO
delete _mregions_prop_box;
delete _slot_prop_box;
delete _midi_ops_box;
delete _audio_ops_box;
delete _midi_prop_box;
delete _audio_prop_box;
#endif
}
void
SelectionPropertiesBox::set_session (Session* s)
{
SessionHandlePtr::set_session (s);
if (!s) {
return;
}
_time_info_box->set_session(s);
#if SELECTION_PROPERTIES_BOX_TODO
_mregions_prop_box->set_session(s);
_midi_prop_box->set_session(s);
_audio_prop_box->set_session(s);
_midi_ops_box->set_session(s);
_audio_ops_box->set_session(s);
_slot_prop_box->set_session(s);
#endif
}
void
SelectionPropertiesBox::track_mouse_mode ()
{
@ -165,7 +174,6 @@ SelectionPropertiesBox::selection_changed ()
_time_info_box->hide();
#if SELECTION_PROPERTIES_BOX_TODO
_mregions_prop_box->hide();
_midi_ops_box->hide();
@ -175,7 +183,8 @@ SelectionPropertiesBox::selection_changed ()
_audio_prop_box->hide();
_slot_prop_box->hide();
#endif
_route_prop_box->hide();
_header_label.hide();
@ -185,6 +194,16 @@ SelectionPropertiesBox::selection_changed ()
_header_label.show();
}
if (!selection.tracks.empty()) {
_route_prop_box->show();
TimeAxisView *tav = *(selection.tracks.begin());
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView *>(tav);
_route_prop_box->set_route(rtav->route());
_header_label.set_text(_("Track Properties (Press ESC to Deselect All)"));
_header_label.hide();
}
#if SELECTION_PROPERTIES_BOX_TODO
/* one or more regions, show the multi-region operations box (just MUTE? kinda boring) */
if (!selection.regions.empty()) {
@ -215,8 +234,10 @@ SelectionPropertiesBox::selection_changed ()
if (found_audio_regions && ! found_midi_regions) {
_audio_ops_box->show();
}
#endif
std::shared_ptr<ARDOUR::Region> selected_region = std::shared_ptr<ARDOUR::Region>();
RegionView *selected_regionview = NULL;
if (!selection.triggers.empty()) {
TriggerSelection ts = selection.triggers;
@ -227,21 +248,21 @@ SelectionPropertiesBox::selection_changed ()
_slot_prop_box->set_slot(ref);
_slot_prop_box->show();
selected_region = ref.trigger()->region();
// selected_region = ref.trigger()->region();
} else if (selection.regions.size()==1) {
selected_region = (*(selection.regions.begin()))->region();
selected_regionview = *(selection.regions.begin());
}
if (selected_region) {
#if 0 // TODO pack region-properties here
if (selected_regionview) {
std::shared_ptr<ARDOUR::Region> r = selected_regionview->region();
//region properties
if (selected_region->data_type() == DataType::MIDI) {
_midi_prop_box->set_region(selected_region);
if (r && r->data_type() == DataType::MIDI) {
_midi_prop_box->set_regionview(selected_regionview);
_midi_prop_box->show();
_midi_ops_box->show();
} else {
_audio_prop_box->set_region(selected_region);
} else if (r) {
_audio_prop_box->set_regionview(selected_regionview); //retains a SessionHandler reference somewhere @robin
_audio_prop_box->show();
_audio_ops_box->show();
}
}
#endif

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2021 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2021 Ben Loftis <ben@harrisonconsoles.com>
* Copyright (C) 2024 Ben Loftis <ben@harrisonconsoles.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -47,7 +47,9 @@ class MidiRegionPropertiesBox;
class AudioRegionOperationsBox;
class MidiRegionOperationsBox;
class SelectionPropertiesBox : public Gtk::VBox, public ARDOUR::SessionHandlePtr
class RoutePropertiesBox;
class SelectionPropertiesBox : public Gtk::HBox, public ARDOUR::SessionHandlePtr
{
public:
SelectionPropertiesBox ();
@ -74,6 +76,8 @@ private:
SlotPropertiesBox* _slot_prop_box;
RoutePropertiesBox* _route_prop_box;
void selection_changed ();
void track_mouse_mode ();

View File

@ -77,8 +77,6 @@ TriggerPage::TriggerPage ()
load_bindings ();
register_actions ();
left_attachment_button.set_sensitive(false);
/* Match TriggerStrip::_name_button height */
ArdourButton* spacer = manage (new ArdourButton (ArdourButton::Text));
spacer->set_name ("mixer strip button");

View File

@ -45,6 +45,7 @@ gtk2_ardour_sources = [
'audio_region_view.cc',
'audio_region_operations_box.cc',
'audio_region_properties_box.cc',
'audio_route_properties_box.cc',
'audio_trigger_properties_box.cc',
'audio_streamview.cc',
'audio_time_axis.cc',
@ -268,6 +269,7 @@ gtk2_ardour_sources = [
'route_group_menu.cc',
'route_list_base.cc',
'route_params_ui.cc',
'route_properties_box.cc',
'route_processor_selection.cc',
'route_time_axis.cc',
'route_ui.cc',

View File

@ -37,10 +37,11 @@ using namespace Gtk;
using namespace Gtkmm2ext;
using namespace ArdourWidgets;
Tabbable::Tabbable (const string& visible_name, string const & nontranslatable_name, Widget* w, bool tabbed_by_default)
Tabbable::Tabbable (const string& visible_name, string const & nontranslatable_name, Widget* w, bool tabbed_by_default, PaneLayout pl)
: WindowProxy (visible_name, nontranslatable_name)
, _parent_notebook (0)
, tab_requested_by_state (tabbed_by_default)
, _panelayout (pl)
{
if (w) {
_contents = w;
@ -78,6 +79,10 @@ Tabbable::default_layout ()
right_attachment_button.set_tweaks (ArdourButton::ExpandtoSquare);
bottom_attachment_button.set_tweaks (ArdourButton::ExpandtoSquare);
left_attachment_button.set_sensitive (0 != (_panelayout & (PaneLeft | AttLeft)));
right_attachment_button.set_sensitive (0 != (_panelayout & PaneRight));
bottom_attachment_button.set_sensitive (0 != (_panelayout & AttBottom));
content_attachment_hbox.set_border_width(3);
content_attachment_hbox.set_spacing(3);
content_attachment_hbox.pack_end (right_attachment_button, false, false);
@ -99,27 +104,43 @@ Tabbable::default_layout ()
_content_vbox.pack_start (*toolbar_frame, false, false);
#endif
_content_vbox.pack_start (content_hbox, true, true);
if (_panelayout & PaneLeft) {
_content_vbox.pack_start (content_left_pane, true, true);
content_left_pane.add (content_att_left);
content_left_pane.add (content_midlevel_vbox);
} else {
_content_vbox.pack_start (content_hbox, true, true);
content_hbox.pack_start (content_att_left, false, false);
content_hbox.pack_start (content_midlevel_vbox, true, true);
}
content_midlevel_vbox.pack_start (content_right_pane, true, true);
content_midlevel_vbox.pack_start (content_att_bottom, false, false);
content_right_pane.add (content_inner_vbox);
content_right_pane.add (content_right_vbox);
//TODO: menu switcher here?
if (_panelayout & PaneRight) {
content_right_pane.add (content_right_vbox);
content_right_vbox.pack_start (content_att_right, true, true);
}
content_inner_vbox.pack_start (content_toolbar, false, false);
content_inner_vbox.pack_start (content_innermost_hbox, true, true);
if (_panelayout & PaneRight) {
content_right_pane.set_child_minsize (content_att_right, 160); /* rough guess at width of notebook tabs */
}
content_right_pane.set_check_divider_position (true);
content_right_pane.set_divider (0, 0.85);
if (_panelayout & PaneLeft) {
content_left_pane.set_child_minsize (content_att_left, 80);
}
content_left_pane.set_check_divider_position (true);
content_left_pane.set_divider (0, 0.15);
_content_vbox.show_all();
}
@ -412,7 +433,8 @@ Tabbable::get_state() const
node.set_property (X_("tabbed"), tabbed());
node.set_property (string_compose("%1%2", _menu_name, X_("-listpane-pos")).c_str(), content_right_pane.get_divider ());
node.set_property (string_compose("%1%2", _menu_name, X_("-rightpane-pos")).c_str(), content_right_pane.get_divider ());
node.set_property (string_compose("%1%2", _menu_name, X_("-leftpane-pos")).c_str(), content_left_pane.get_divider ());
return node;
}
@ -436,10 +458,14 @@ Tabbable::set_state (const XMLNode& node, int version)
if (window_node) {
window_node->get_property (X_("tabbed"), tab_requested_by_state);
float fract;
if ( window_node->get_property (string_compose("%1%2", _menu_name, X_("-listpane-pos")).c_str(), fract) ) {
if ( window_node->get_property (string_compose("%1%2", _menu_name, X_("-rightpane-pos")).c_str(), fract) ) {
fract = std::max (.05f, std::min (.95f, fract));
content_right_pane.set_divider (0, fract);
}
if ( window_node->get_property (string_compose("%1%2", _menu_name, X_("-leftpane-pos")).c_str(), fract) ) {
fract = std::max (.05f, std::min (.95f, fract));
content_left_pane.set_divider (0, fract);
}
}

View File

@ -48,7 +48,17 @@ namespace ArdourWidgets {
class LIBWIDGETS_API Tabbable : public Gtkmm2ext::WindowProxy
{
public:
Tabbable (const std::string& user_visible_name, std::string const & untranslated_name, Gtk::Widget* top = NULL, bool tabbed_by_default = true);
enum PaneLayout {
NoPanes = 0x0, ///< disable all attachment buttons, do not pack any panes or attachments
PaneLeft = 0x1, ///< left side attachment is a resizable pane
PaneRight = 0x2, ///< pack a resizable Pane on the right-side
AttBottom = 0x4, ///< bottom is a fixed size EBox attachment
PaneLeftBtm = 0x5,
PaneRightBtm = 0x6,
AttLeft = 0x8, ///< if PaneLeft is not set, pack a fixed size Ebox on the left (Editor-Mixer)
};
Tabbable (const std::string& user_visible_name, std::string const & untranslated_name, Gtk::Widget* top = NULL, bool tabbed_by_default = true, PaneLayout pl = PaneRightBtm);
~Tabbable ();
void add_to_notebook (Gtk::Notebook& notebook);
@ -101,8 +111,53 @@ protected:
bool delete_event_handler (GdkEventAny *ev);
/* This is the heirarchy of a Tabbable's widget packing.
* The end result is to provide 8(ish) event-boxen where the tab can put its contents
* Please maintain the indention here so the hierarchy is visible
*
* The end result is to provide 7 event-boxes (marked with a $) where the tab can put its contents.
*
* +--_content_vbox----------------------------------------------------------------------------------+
* | |
* | /--toolbar_frame------------------------------------------------------------------------------\ |
* | | +--content_header_hbox--------------------------------------------------------------------+ | |
* | | | | | |
* | | | +--content_app_bar--------------------+ +--attachment_hbox--+ +--content_tabbables--+ | | |
* | | | $ (EBOX) | | (internal) | $ (EBOX) | | | |
* | | | | MAIN APPLICATION BAR | | (attachment btns) | | PAGE SWITCHER BTN | | | |
* | | | | | | | | | | | |
* | | | +-------------------------------------+ +-------------------+ +---------------------+ | | |
* | | | | | |
* | | +-----------------------------------------------------------------------------------------+ | |
* | \---------------------------------------------------------------------------------------------/ |
* | |
* | +--content_hbox--OR--content_left_pane--------------------------------------------------------+ |
* | | | |
* | | +--att_left--+ +--content_midlevel_vbox-------------------------------------------------+ | |
* | | $ (EBOX) | | +--content_right_pane------------------------------------------------+ | | |
* | | | | | | +--content_inner_vbox-----------------+ +--content_right_vbox--+ | | | |
* | | | O | | | | | | | | | | |
* | | | P S | | | | +--content_toolbar----------------+ | | +--att_right-------+ | | | | |
* | | | T I | | | | $ OPTIONAL TOOLBAR (EBOX) | | | $ (EBOX) | | | | | |
* | | | I D | | | | +---------------------------------+ |<->| | | | | | | |
* | | | O E |<->| | | | P | | OPTIONAL | | | | | |
* | | | N B | O | | | +--content_innermost_hbox---------+ | A | | SIDEBAR | | | | | |
* | | | A A | P | | | $ (HBOX) | | N | | | | | | | |
* | | | L R | T | | | | | | E | | | | | | | |
* | | | | . | | | | !! MAIN PAGE CONTENT !! | |<->| | (LIST) | | | | | |
* | | | | P | | | | | | | | | | | | | |
* | | | | A | | | | | | | | | | | | | |
* | | | | N | | | +---------------------------------+ | | +------------------+ | | | | |
* | | | (STRIP) | E | | +-------------------------------------+ +----------------------+ | | | |
* | | | |<->| +--------------------------------------------------------------------+ | | |
* | | | | | | | |
* | | | | | +-content_att_bottom-------------------------------------------------+ | | |
* | | | | | $ (EBOX) | | | |
* | | | | | | OPTIONAL BOTTOM (PROPERTIES) | | | |
* | | | | | | | | | |
* | | | | | +--------------------------------------------------------------------+ | | |
* | | +------------+ +------------------------------------------------------------------------+ | |
* | +---------------------------------------------------------------------------------------------+ |
* | |
* +-------------------------------------------------------------------------------------------------+
*
*/
/* clang-format off */
@ -113,6 +168,7 @@ protected:
Gtk::EventBox content_attachments; /* a placeholder the (strip, list, props) visibility buttons for this tab */
Gtk::HBox content_attachment_hbox;
EventBoxExt content_tabbables; /* a placeholder for the tabbable switching buttons (used by ArdourUI) */
HPane content_left_pane;
Gtk::HBox content_hbox;
EventBoxExt content_att_left; /* a placeholder for the mixer strip, if you want one */
Gtk::VBox content_midlevel_vbox;
@ -144,6 +200,7 @@ private:
Gtk::Notebook _own_notebook;
Gtk::Notebook* _parent_notebook;
bool tab_requested_by_state;
PaneLayout _panelayout;
};

View File

@ -749,10 +749,6 @@ int main() { return 0; }''',
compiler_flags.append ('-DMIXBUS')
conf.define('MIXBUS', 1)
if Options.options.program_name.lower() == "mixbus32c":
conf.define('MIXBUS32C', 1)
compiler_flags.append ('-DMIXBUS32C')
if Options.options.program_name.lower() == "livetrax":
compiler_flags.append ('-DLIVETRAX')
conf.define ('LIVETRAX', 1)