summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/mixer.bindings20
-rw-r--r--gtk2_ardour/mixer_actor.cc266
-rw-r--r--gtk2_ardour/mixer_actor.h74
-rw-r--r--gtk2_ardour/mixer_group_tabs.cc4
-rw-r--r--gtk2_ardour/mixer_strip.cc159
-rw-r--r--gtk2_ardour/mixer_strip.h14
-rw-r--r--gtk2_ardour/mixer_ui.cc165
-rw-r--r--gtk2_ardour/mixer_ui.h13
-rw-r--r--gtk2_ardour/processor_box.cc131
-rw-r--r--gtk2_ardour/processor_box.h17
-rw-r--r--gtk2_ardour/route_processor_selection.cc40
-rw-r--r--gtk2_ardour/route_processor_selection.h14
-rw-r--r--gtk2_ardour/route_ui.cc6
-rw-r--r--gtk2_ardour/route_ui.h2
-rw-r--r--gtk2_ardour/route_ui_selection.h (renamed from gtk2_ardour/route_selection.h)15
-rw-r--r--gtk2_ardour/time_axis_view.h2
-rw-r--r--gtk2_ardour/wscript1
17 files changed, 631 insertions, 312 deletions
diff --git a/gtk2_ardour/mixer.bindings b/gtk2_ardour/mixer.bindings
new file mode 100644
index 0000000000..3daeab53ca
--- /dev/null
+++ b/gtk2_ardour/mixer.bindings
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bindings name="ardour">
+ <Press>
+ <Binding key="s" action="Mixer/solo"/>
+ <Binding key="m" action="Mixer/mute"/>
+ <Binding key="r" action="Mixer/recenable"/>
+ <Binding key="0" action="Mixer/unity-gain"/>
+ <Binding key="Up" action="Mixer/increment-gain"/>
+ <Binding key="Down" action="Mixer/decrement-gain"/>
+ <Binding key="Left" action="Mixer/scroll-left"/>
+ <Binding key="Right" action="Mixer/scroll-right"/>
+ <Binding key="Primary-x" action="Mixer/cut-processors"/>
+ <Binding key="Primary-c" action="Mixer/copy-processors"/>
+ <Binding key="Primary-v" action="Mixer/paste-processors"/>
+ <Binding key="Delete" action="Mixer/delete-processors"/>
+ <Binding key="Return" action="Mixer/toggle-processors"/>
+ <Binding key="Primary-a" action="Mixer/select-all-processors"/>
+ <Binding key="Slash" action="Mixer/ab-plugins"/>
+ </Press>
+</Bindings>
diff --git a/gtk2_ardour/mixer_actor.cc b/gtk2_ardour/mixer_actor.cc
new file mode 100644
index 0000000000..b309b9fd7f
--- /dev/null
+++ b/gtk2_ardour/mixer_actor.cc
@@ -0,0 +1,266 @@
+/*
+ Copyright (C) 2000-2004 Paul Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifdef WAF_BUILD
+#include "gtk2ardour-config.h"
+#endif
+
+#include <boost/foreach.hpp>
+
+#include "pbd/filesystem.h"
+#include "pbd/file_utils.h"
+#include "pbd/search_path.h"
+#include "pbd/error.h"
+
+#include "ardour/filesystem_paths.h"
+
+#include "actions.h"
+#include "mixer_actor.h"
+#include "mixer_strip.h"
+#include "route_ui.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace PBD;
+
+MixerActor::MixerActor ()
+{
+ register_actions ();
+ load_bindings ();
+}
+
+MixerActor::~MixerActor ()
+{
+}
+
+void
+MixerActor::register_actions ()
+{
+ myactions.register_action ("Mixer", "solo", _("Toggle Solo on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &MixerActor::solo_action));
+ myactions.register_action ("Mixer", "mute", _("Toggle Mute on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &MixerActor::mute_action));
+ myactions.register_action ("Mixer", "recenable", _("Toggle Rec-enable on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &MixerActor::rec_enable_action));
+ myactions.register_action ("Mixer", "increment-gain", _("Decrease Gain on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &MixerActor::step_gain_up_action));
+ myactions.register_action ("Mixer", "decrement-gain", _("Increase Gain on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &MixerActor::step_gain_down_action));
+ myactions.register_action ("Mixer", "unity-gain", _("Set Gain to 0dB on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &MixerActor::unity_gain_action));
+
+
+ myactions.register_action ("Mixer", "copy-processors", _("Copy Selected Processors"), sigc::mem_fun (*this, &MixerActor::copy_processors));
+ myactions.register_action ("Mixer", "cut-processors", _("Cut Selected Processors"), sigc::mem_fun (*this, &MixerActor::cut_processors));
+ myactions.register_action ("Mixer", "paste-processors", _("Paste Selected Processors"), sigc::mem_fun (*this, &MixerActor::paste_processors));
+ myactions.register_action ("Mixer", "delete-processors", _("Delete Selected Processors"), sigc::mem_fun (*this, &MixerActor::delete_processors));
+ myactions.register_action ("Mixer", "select-all-processors", _("Select All (visible) Processors"), sigc::mem_fun (*this, &MixerActor::select_all_processors));
+ myactions.register_action ("Mixer", "toggle-processors", _("Toggle Selected Processors"), sigc::mem_fun (*this, &MixerActor::toggle_processors));
+ myactions.register_action ("Mixer", "ab-plugins", _("Toggle Selected Plugins"), sigc::mem_fun (*this, &MixerActor::ab_plugins));
+
+
+ myactions.register_action ("Mixer", "scroll-left", _("Scroll Mixer Window to the left"), sigc::mem_fun (*this, &MixerActor::scroll_left));
+ myactions.register_action ("Mixer", "scroll-right", _("Scroll Mixer Window to the left"), sigc::mem_fun (*this, &MixerActor::scroll_right));
+}
+
+void
+MixerActor::load_bindings ()
+{
+ /* XXX move this to a better place */
+
+ bindings.set_action_map (myactions);
+
+ sys::path binding_file;
+ SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
+
+ if (find_file_in_search_path (spath, "mixer.bindings", binding_file)) {
+ bindings.load (binding_file.to_string());
+ info << string_compose (_("Loaded mixer bindings from %1"), binding_file.to_string()) << endmsg;
+ } else {
+ error << string_compose (_("Could not find mixer.bindings in search path %1"), spath.to_string()) << endmsg;
+ }
+}
+
+void
+MixerActor::solo_action ()
+{
+ GdkEventButton ev;
+
+ ev.type = GDK_BUTTON_PRESS;
+ ev.button = 1;
+ ev.state = 0;
+
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ r->solo_press (&ev);
+ }
+}
+
+void
+MixerActor::mute_action ()
+{
+ GdkEventButton ev;
+
+ ev.type = GDK_BUTTON_PRESS;
+ ev.button = 1;
+ ev.state = 0;
+
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ r->mute_press (&ev);
+ }
+}
+
+void
+MixerActor::rec_enable_action ()
+{
+ GdkEventButton ev;
+
+ ev.type = GDK_BUTTON_PRESS;
+ ev.button = 1;
+ ev.state = 0;
+
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ r->rec_enable_press (&ev);
+ }
+}
+
+void
+MixerActor::step_gain_up_action ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->step_gain_up ();
+ }
+ }
+}
+
+void
+MixerActor::step_gain_down_action ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->step_gain_down ();
+ }
+ }
+}
+
+void
+MixerActor::unity_gain_action ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ boost::shared_ptr<Route> rp = r->route();
+ if (rp) {
+ rp->set_gain (1.0, this);
+ }
+ }
+}
+
+void
+MixerActor::copy_processors ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->copy_processors ();
+ }
+ }
+}
+void
+MixerActor::cut_processors ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->cut_processors ();
+ }
+ }
+}
+void
+MixerActor::paste_processors ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->paste_processors ();
+ }
+ }
+}
+void
+MixerActor::select_all_processors ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->select_all_processors ();
+ }
+ }
+}
+void
+MixerActor::delete_processors ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->delete_processors ();
+ }
+ }
+}
+void
+MixerActor::toggle_processors ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->toggle_processors ();
+ }
+ }
+}
+void
+MixerActor::ab_plugins ()
+{
+ set_route_targets_for_operation ();
+
+ BOOST_FOREACH(RouteUI* r, _route_targets) {
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+ if (ms) {
+ ms->ab_plugins ();
+ }
+ }
+}
diff --git a/gtk2_ardour/mixer_actor.h b/gtk2_ardour/mixer_actor.h
new file mode 100644
index 0000000000..980938f8a2
--- /dev/null
+++ b/gtk2_ardour/mixer_actor.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __gtk2_ardour_mixer_actor_h__
+#define __gtk2_ardour_mixer_actor_h__
+
+#include <glibmm/refptr.h>
+#include <gtkmm2ext/bindings.h>
+
+#include "route_processor_selection.h"
+
+namespace Gtk {
+ class ActionGroup;
+}
+
+class MixerActor : virtual public sigc::trackable
+{
+ public:
+ MixerActor ();
+ virtual ~MixerActor ();
+
+ RouteRedirectSelection& selection() { return _selection; }
+ void register_actions ();
+
+ void load_bindings ();
+ Gtkmm2ext::Bindings bindings;
+
+ protected:
+ RouteRedirectSelection _selection;
+ RouteUISelection _route_targets;
+ Gtkmm2ext::ActionMap myactions;
+
+ virtual void set_route_targets_for_operation () = 0;
+
+ void solo_action ();
+ void mute_action ();
+ void rec_enable_action ();
+ void step_gain_up_action ();
+ void step_gain_down_action ();
+ void unity_gain_action ();
+
+ void copy_processors ();
+ void cut_processors ();
+ void paste_processors ();
+ void select_all_processors ();
+ void delete_processors ();
+ void toggle_processors ();
+ void ab_plugins ();
+
+ /* these actions don't apply to the selection, so defer to
+ a derived class.
+ */
+
+ virtual void scroll_left () {}
+ virtual void scroll_right () {}
+};
+
+#endif /* __gtk2_ardour_mixer_actor_h__ */
diff --git a/gtk2_ardour/mixer_group_tabs.cc b/gtk2_ardour/mixer_group_tabs.cc
index b74455b28d..6a6149f67f 100644
--- a/gtk2_ardour/mixer_group_tabs.cc
+++ b/gtk2_ardour/mixer_group_tabs.cc
@@ -176,7 +176,9 @@ MixerGroupTabs::order_key () const
RouteList
MixerGroupTabs::selected_routes () const
{
- return _mixer->selection().routes;
+ RouteList rl;
+ /* XXX need a foreach here */
+ return rl;
}
void
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index f767396308..56c98c2024 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -1634,11 +1634,6 @@ MixerStrip::reset_strip_style ()
}
}
-RouteGroup*
-MixerStrip::route_group() const
-{
- return _route->route_group();
-}
void
MixerStrip::engine_stopped ()
@@ -1858,117 +1853,6 @@ MixerStrip::set_button_names ()
}
}
-bool
-MixerStrip::on_key_press_event (GdkEventKey* ev)
-{
- GdkEventButton fake;
- fake.type = GDK_BUTTON_PRESS;
- fake.button = 1;
- fake.state = ev->state;
-
- switch (ev->keyval) {
- case GDK_m:
- mute_press (&fake);
- return true;
- break;
-
- case GDK_s:
- solo_press (&fake);
- return true;
- break;
-
- case GDK_r:
- rec_enable_press (&fake);
- return true;
- break;
-
- case GDK_e:
- show_sends_press (&fake);
- return true;
- break;
-
- case GDK_g:
- if (ev->state & Keyboard::PrimaryModifier) {
- step_gain_down ();
- } else {
- step_gain_up ();
- }
- return true;
- break;
-
- case GDK_0:
- if (_route) {
- _route->set_gain (1.0, this);
- }
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-
-bool
-MixerStrip::on_key_release_event (GdkEventKey* ev)
-{
- GdkEventButton fake;
- fake.type = GDK_BUTTON_RELEASE;
- fake.button = 1;
- fake.state = ev->state;
-
- switch (ev->keyval) {
- case GDK_m:
- mute_release (&fake);
- return true;
- break;
-
- case GDK_s:
- solo_release (&fake);
- return true;
- break;
-
- case GDK_r:
- rec_enable_release (&fake);
- return true;
- break;
-
- case GDK_e:
- show_sends_release (&fake);
- return true;
- break;
-
- case GDK_g:
- return true;
- break;
-
- default:
- break;
- }
-
- return false;
-}
-
-bool
-MixerStrip::on_enter_notify_event (GdkEventCrossing*)
-{
- Keyboard::magic_widget_grab_focus ();
- return false;
-}
-
-bool
-MixerStrip::on_leave_notify_event (GdkEventCrossing* ev)
-{
- switch (ev->detail) {
- case GDK_NOTIFY_INFERIOR:
- break;
- default:
- Keyboard::magic_widget_drop_focus ();
- }
-
- return false;
-}
PluginSelector*
MixerStrip::plugin_selector()
@@ -2077,3 +1961,46 @@ MixerStrip::route_active_changed ()
{
reset_strip_style ();
}
+
+void
+MixerStrip::copy_processors ()
+{
+ processor_box.processor_operation (ProcessorBox::ProcessorsCopy);
+}
+
+void
+MixerStrip::cut_processors ()
+{
+ processor_box.processor_operation (ProcessorBox::ProcessorsCut);
+}
+
+void
+MixerStrip::paste_processors ()
+{
+ processor_box.processor_operation (ProcessorBox::ProcessorsPaste);
+}
+
+void
+MixerStrip::select_all_processors ()
+{
+ processor_box.processor_operation (ProcessorBox::ProcessorsSelectAll);
+}
+
+void
+MixerStrip::delete_processors ()
+{
+ processor_box.processor_operation (ProcessorBox::ProcessorsDelete);
+}
+
+void
+MixerStrip::toggle_processors ()
+{
+ processor_box.processor_operation (ProcessorBox::ProcessorsToggleActive);
+}
+
+void
+MixerStrip::ab_plugins ()
+{
+ processor_box.processor_operation (ProcessorBox::ProcessorsAB);
+}
+
diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h
index 14d89fa1b0..6aac87850d 100644
--- a/gtk2_ardour/mixer_strip.h
+++ b/gtk2_ardour/mixer_strip.h
@@ -92,7 +92,6 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void fast_update ();
void set_embedded (bool);
- ARDOUR::RouteGroup* route_group() const;
void set_route (boost::shared_ptr<ARDOUR::Route>);
void set_button_names ();
void show_send (boost::shared_ptr<ARDOUR::Send>);
@@ -123,6 +122,14 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void parameter_changed (std::string);
void route_active_changed ();
+ void copy_processors ();
+ void cut_processors ();
+ void paste_processors ();
+ void select_all_processors ();
+ void delete_processors ();
+ void toggle_processors ();
+ void ab_plugins ();
+
protected:
friend class Mixer_UI;
void set_packed (bool yn);
@@ -131,11 +138,6 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void set_selected(bool yn);
void set_stuff_from_route ();
- bool on_leave_notify_event (GdkEventCrossing* ev);
- bool on_enter_notify_event (GdkEventCrossing* ev);
- bool on_key_press_event (GdkEventKey* ev);
- bool on_key_release_event (GdkEventKey* ev);
-
private:
Mixer_UI& _mixer;
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index 2ef0956d2c..e65afb4cc7 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -68,6 +68,9 @@ using PBD::atoi;
Mixer_UI::Mixer_UI ()
: Window (Gtk::WINDOW_TOPLEVEL)
{
+ /* allow this window to become the key focus window */
+ set_flags (CAN_FOCUS);
+
_strip_width = Config->get_default_narrow_ms() ? Narrow : Wide;
track_menu = 0;
_monitor_section = 0;
@@ -80,6 +83,7 @@ Mixer_UI::Mixer_UI ()
Route::SyncOrderKeys.connect (*this, invalidator (*this), ui_bind (&Mixer_UI::sync_order_keys, this, _1), gui_context());
+ scroller_base.set_flags (Gtk::CAN_FOCUS);
scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
scroller_base.set_name ("MixerWindow");
scroller_base.signal_button_release_event().connect (sigc::mem_fun(*this, &Mixer_UI::strip_scroller_button_release));
@@ -190,15 +194,11 @@ Mixer_UI::Mixer_UI ()
set_wmclass (X_("ardour_mixer"), PROGRAM_NAME);
- add_accel_group (ActionManager::ui_manager->get_accel_group());
-
signal_delete_event().connect (sigc::mem_fun (*this, &Mixer_UI::hide_window));
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
- _selection.RoutesChanged.connect (sigc::mem_fun(*this, &Mixer_UI::follow_strip_selection));
-
route_group_display_button_box->show();
route_group_add_button->show();
route_group_remove_button->show();
@@ -267,6 +267,10 @@ Mixer_UI::show_window ()
ms->parameter_changed (X_("mixer-strip-visibility"));
}
}
+
+ /* force focus into main area */
+ scroller_base.grab_focus ();
+
_visible = true;
}
@@ -361,8 +365,6 @@ Mixer_UI::remove_strip (MixerStrip* strip)
ENSURE_GUI_THREAD (*this, &Mixer_UI::remove_strip, strip);
- cerr << "Mixer UI removing strip for " << strip << endl;
-
TreeModel::Children rows = track_model->children();
TreeModel::Children::iterator ri;
list<MixerStrip *>::iterator i;
@@ -429,31 +431,76 @@ Mixer_UI::sync_order_keys (string const & src)
}
}
-void
-Mixer_UI::follow_strip_selection ()
+MixerStrip*
+Mixer_UI::strip_by_route (boost::shared_ptr<Route> r)
{
for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
- (*i)->set_selected (_selection.selected ((*i)->route()));
+ if ((*i)->route() == r) {
+ return (*i);
+ }
}
+
+ return 0;
}
bool
Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
{
if (ev->button == 1) {
-
- /* this allows the user to click on the strip to terminate comment
- editing. XXX it needs improving so that we don't select the strip
- at the same time.
- */
-
- if (_selection.selected (strip->route())) {
- _selection.remove (strip->route());
+ if (_selection.selected (strip)) {
+ /* primary-click: toggle selection state of strip */
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
+ _selection.remove (strip);
+ }
} else {
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
- _selection.add (strip->route());
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
+ _selection.add (strip);
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::RangeSelectModifier)) {
+
+ if (!_selection.selected(strip)) {
+
+ /* extend selection */
+
+ vector<MixerStrip*> tmp;
+ bool accumulate = false;
+
+ tmp.push_back (strip);
+
+ for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ if ((*i) == strip) {
+ /* hit clicked strip, start accumulating till we hit the first
+ selected strip
+ */
+ if (accumulate) {
+ /* done */
+ break;
+ } else {
+ accumulate = true;
+ }
+ } else if (_selection.selected (*i)) {
+ /* hit selected strip. if currently accumulating others,
+ we're done. if not accumulating others, start doing so.
+ */
+ if (accumulate) {
+ /* done */
+ break;
+ } else {
+ accumulate = true;
+ }
+ } else {
+ if (accumulate) {
+ tmp.push_back (*i);
+ }
+ }
+ }
+
+ for (vector<MixerStrip*>::iterator i = tmp.begin(); i != tmp.end(); ++i) {
+ _selection.add (*i);
+ }
+ }
+
} else {
- _selection.set (strip->route());
+ _selection.set (strip);
}
}
}
@@ -1527,29 +1574,40 @@ Mixer_UI::scroll_right ()
bool
Mixer_UI::on_key_press_event (GdkEventKey* ev)
{
- switch (ev->keyval) {
- case GDK_Left:
- scroll_left ();
- return true;
+ /* focus widget gets first shot, then bindings, otherwise
+ forward to main window
+ */
- case GDK_Right:
- scroll_right ();
+ if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
return true;
-
- default:
- break;
}
-
- return key_press_focus_accelerator_handler (*this, ev);
+
+ KeyboardKey k (ev->state, ev->keyval);
+
+ if (bindings.activate (k, Bindings::Press)) {
+ return true;
+ }
+
+ return forward_key_press (ev);
}
bool
Mixer_UI::on_key_release_event (GdkEventKey* ev)
{
- return Gtk::Window::on_key_release_event (ev);
- // return key_press_focus_accelerator_handler (*this, ev);
-}
+ if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
+ return true;
+ }
+ KeyboardKey k (ev->state, ev->keyval);
+
+ if (bindings.activate (k, Bindings::Release)) {
+ return true;
+ }
+
+ /* don't forward releases */
+
+ return true;
+}
bool
Mixer_UI::on_scroll_event (GdkEventScroll* ev)
@@ -1704,4 +1762,41 @@ Mixer_UI::update_title ()
}
}
-
+MixerStrip*
+Mixer_UI::strip_by_x (int x)
+{
+ for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ int x1, x2, y;
+
+ (*i)->translate_coordinates (*this, 0, 0, x1, y);
+ x2 = x1 + (*i)->get_width();
+
+ if (x >= x1 && x <= x2) {
+ return (*i);
+ }
+ }
+
+ return 0;
+}
+
+void
+Mixer_UI::set_route_targets_for_operation ()
+{
+ _route_targets.clear ();
+
+ if (!_selection.empty()) {
+ _route_targets = _selection.routes;
+ return;
+ }
+
+ /* try to get mixer strip at mouse */
+
+ int x, y;
+ get_pointer (x, y);
+
+ MixerStrip* ms = strip_by_x (x);
+
+ if (ms) {
+ _route_targets.insert (ms);
+ }
+}
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index 0f13d93bee..6388ed5180 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -39,8 +39,8 @@
#include "ardour/ardour.h"
#include "ardour/session_handle.h"
-#include "route_processor_selection.h"
#include "enums.h"
+#include "mixer_actor.h"
namespace ARDOUR {
class Route;
@@ -52,7 +52,7 @@ class PluginSelector;
class MixerGroupTabs;
class MonitorSection;
-class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr
+class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor
{
public:
Mixer_UI ();
@@ -80,9 +80,11 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
void toggle_auto_rebinding ();
void set_auto_rebinding(bool);
- RouteRedirectSelection& selection() { return _selection; }
MonitorSection* monitor_section() const { return _monitor_section; }
+ protected:
+ void set_route_targets_for_operation ();
+
private:
bool _visible;
@@ -128,6 +130,8 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
void add_strip (ARDOUR::RouteList&);
void remove_strip (MixerStrip *);
+ MixerStrip* strip_by_route (boost::shared_ptr<ARDOUR::Route>);
+
void hide_all_strips (bool with_select);
void unselect_all_strips();
void select_all_strips ();
@@ -241,8 +245,6 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
bool strip_button_release_event (GdkEventButton*, MixerStrip*);
- RouteRedirectSelection _selection;
-
Width _strip_width;
void sync_order_keys (std::string const &);
@@ -265,6 +267,7 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
bool _in_group_rebuild_or_clear;
void update_title ();
+ MixerStrip* strip_by_x (int x);
friend class MixerGroupTabs;
};
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index 2cdf103034..c56c18ab00 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -488,9 +488,6 @@ ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelecto
processor_display.signal_enter_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::enter_notify), false);
processor_display.signal_leave_notify_event().connect (sigc::mem_fun(*this, &ProcessorBox::leave_notify), false);
- processor_display.signal_key_press_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_press_event));
- processor_display.signal_key_release_event().connect (sigc::mem_fun(*this, &ProcessorBox::processor_key_release_event));
-
processor_display.ButtonPress.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_press_event));
processor_display.ButtonRelease.connect (sigc::mem_fun (*this, &ProcessorBox::processor_button_release_event));
@@ -696,49 +693,19 @@ bool
ProcessorBox::enter_notify (GdkEventCrossing*)
{
_current_processor_box = this;
- Keyboard::magic_widget_grab_focus ();
- processor_display.grab_focus ();
-
return false;
}
bool
ProcessorBox::leave_notify (GdkEventCrossing* ev)
{
- switch (ev->detail) {
- case GDK_NOTIFY_INFERIOR:
- break;
- default:
- Keyboard::magic_widget_drop_focus ();
- }
-
return false;
}
-bool
-ProcessorBox::processor_key_press_event (GdkEventKey *ev)
-{
- switch (ev->keyval) {
- case GDK_a:
- case GDK_c:
- case GDK_x:
- case GDK_v:
- case GDK_Up:
- case GDK_Down:
- case GDK_Delete:
- case GDK_BackSpace:
- case GDK_Return:
- case GDK_slash:
- /* do real stuff on key release */
- return true;
- }
-
- return false;
-}
-
-bool
-ProcessorBox::processor_key_release_event (GdkEventKey *ev)
+void
+ProcessorBox::processor_operation (ProcessorOperation op)
{
+
bool ret = false;
ProcSelection targets;
@@ -756,57 +723,32 @@ ProcessorBox::processor_key_release_event (GdkEventKey *ev)
}
}
-
- switch (ev->keyval) {
- case GDK_a:
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
- processor_display.select_all ();
- ret = true;
- }
+ switch (op) {
+ case ProcessorsSelectAll:
+ processor_display.select_all ();
break;
- case GDK_c:
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
- copy_processors (targets);
- ret = true;
- }
+ case ProcessorsCopy:
+ copy_processors (targets);
break;
- case GDK_x:
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
- cut_processors (targets);
- ret = true;
- }
+ case ProcessorsCut:
+ cut_processors (targets);
break;
- case GDK_v:
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
- if (targets.empty()) {
- paste_processors ();
- } else {
- paste_processors (targets.front());
- }
- ret = true;
+ case ProcessorsPaste:
+ if (targets.empty()) {
+ paste_processors ();
+ } else {
+ paste_processors (targets.front());
}
break;
- case GDK_Up:
- processors_down ();
- ret = true;
- break;
-
- case GDK_Down:
- processors_up ();
- ret = true;
- break;
-
- case GDK_Delete:
- case GDK_BackSpace:
+ case ProcessorsDelete:
delete_processors (targets);
- ret = true;
break;
- case GDK_Return:
+ case ProcessorsToggleActive:
for (ProcSelection::iterator i = targets.begin(); i != targets.end(); ++i) {
if ((*i)->active()) {
(*i)->deactivate ();
@@ -817,16 +759,13 @@ ProcessorBox::processor_key_release_event (GdkEventKey *ev)
ret = true;
break;
- case GDK_slash:
+ case ProcessorsAB:
ab_plugins ();
- ret = true;
break;
default:
break;
}
-
- return ret;
}
bool
@@ -1403,14 +1342,6 @@ ProcessorBox::can_cut () const
}
void
-ProcessorBox::cut_processors ()
-{
- ProcSelection to_be_removed;
-
- get_selected_processors (to_be_removed);
-}
-
-void
ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
{
if (to_be_removed.empty()) {
@@ -1452,14 +1383,6 @@ ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
}
void
-ProcessorBox::copy_processors ()
-{
- ProcSelection to_be_copied;
- get_selected_processors (to_be_copied);
- copy_processors (to_be_copied);
-}
-
-void
ProcessorBox::copy_processors (const ProcSelection& to_be_copied)
{
if (to_be_copied.empty()) {
@@ -1494,14 +1417,6 @@ ProcessorBox::processors_down ()
void
-ProcessorBox::delete_processors ()
-{
- ProcSelection to_be_deleted;
- get_selected_processors (to_be_deleted);
- delete_processors (to_be_deleted);
-}
-
-void
ProcessorBox::delete_processors (const ProcSelection& targets)
{
if (targets.empty()) {
@@ -2136,7 +2051,7 @@ ProcessorBox::rb_cut ()
return;
}
- _current_processor_box->cut_processors ();
+ _current_processor_box->processor_operation (ProcessorsCut);
}
void
@@ -2146,7 +2061,7 @@ ProcessorBox::rb_delete ()
return;
}
- _current_processor_box->delete_processors ();
+ _current_processor_box->processor_operation (ProcessorsDelete);
}
void
@@ -2155,7 +2070,7 @@ ProcessorBox::rb_copy ()
if (_current_processor_box == 0) {
return;
}
- _current_processor_box->copy_processors ();
+ _current_processor_box->processor_operation (ProcessorsCopy);
}
void
@@ -2165,7 +2080,7 @@ ProcessorBox::rb_paste ()
return;
}
- _current_processor_box->paste_processors ();
+ _current_processor_box->processor_operation (ProcessorsPaste);
}
void
@@ -2184,7 +2099,7 @@ ProcessorBox::rb_select_all ()
return;
}
- _current_processor_box->select_all_processors ();
+ _current_processor_box->processor_operation (ProcessorsSelectAll);
}
void
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index 5d80e8a360..f6b4fc2fe6 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -194,6 +194,16 @@ private:
class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARDOUR::SessionHandlePtr
{
public:
+ enum ProcessorOperation {
+ ProcessorsCut,
+ ProcessorsCopy,
+ ProcessorsPaste,
+ ProcessorsDelete,
+ ProcessorsSelectAll,
+ ProcessorsToggleActive,
+ ProcessorsAB,
+ };
+
ProcessorBox (ARDOUR::Session*, boost::function<PluginSelector*()> get_plugin_selector,
RouteRedirectSelection&, MixerStrip* parent, bool owner_is_mixer = false);
~ProcessorBox ();
@@ -203,6 +213,8 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
void update();
+ void processor_operation (ProcessorOperation);
+
void select_all_processors ();
void deselect_all_processors ();
void select_all_plugins ();
@@ -279,8 +291,6 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
bool enter_notify (GdkEventCrossing *ev);
bool leave_notify (GdkEventCrossing *ev);
- bool processor_key_press_event (GdkEventKey *);
- bool processor_key_release_event (GdkEventKey *);
bool processor_button_press_event (GdkEventButton *, ProcessorEntry *);
bool processor_button_release_event (GdkEventButton *, ProcessorEntry *);
void redisplay_processors ();
@@ -300,11 +310,8 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
typedef std::vector<boost::shared_ptr<ARDOUR::Processor> > ProcSelection;
void cut_processors (const ProcSelection&);
- void cut_processors ();
void copy_processors (const ProcSelection&);
- void copy_processors ();
void delete_processors (const ProcSelection&);
- void delete_processors ();
void paste_processors ();
void paste_processors (boost::shared_ptr<ARDOUR::Processor> before);
void processors_up ();
diff --git a/gtk2_ardour/route_processor_selection.cc b/gtk2_ardour/route_processor_selection.cc
index b3a6620f6b..9022119729 100644
--- a/gtk2_ardour/route_processor_selection.cc
+++ b/gtk2_ardour/route_processor_selection.cc
@@ -25,8 +25,10 @@
#include "ardour/processor.h"
#include "ardour/route.h"
-#include "route_processor_selection.h"
#include "gui_thread.h"
+#include "mixer_strip.h"
+#include "route_processor_selection.h"
+#include "route_ui.h"
#include "i18n.h"
@@ -68,6 +70,9 @@ RouteRedirectSelection::clear_processors ()
void
RouteRedirectSelection::clear_routes ()
{
+ for (RouteUISelection::iterator i = routes.begin(); i != routes.end(); ++i) {
+ (*i)->set_selected (false);
+ }
routes.clear ();
drop_connections ();
RoutesChanged ();
@@ -90,48 +95,45 @@ RouteRedirectSelection::set (XMLNode* node)
}
void
-RouteRedirectSelection::add (boost::shared_ptr<Route> r)
+RouteRedirectSelection::add (RouteUI* r)
{
if (find (routes.begin(), routes.end(), r) == routes.end()) {
- routes.push_back (r);
- r->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&RouteRedirectSelection::removed, this, boost::weak_ptr<Route>(r)), gui_context());
- RoutesChanged();
- }
-}
+ if (routes.insert (r).second) {
+ r->set_selected (true);
-void
-RouteRedirectSelection::removed (boost::weak_ptr<Route> wr)
-{
- boost::shared_ptr<Route> r (wr.lock());
+ MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
+
+ if (ms) {
+ ms->CatchDeletion.connect (*this, invalidator (*this), ui_bind (&RouteRedirectSelection::remove, this, _1), gui_context());
+ }
- if (!r) {
- return;
+ RoutesChanged();
+ }
}
-
- remove (r);
}
void
-RouteRedirectSelection::remove (boost::shared_ptr<Route> r)
+RouteRedirectSelection::remove (RouteUI* r)
{
ENSURE_GUI_THREAD (*this, &RouteRedirectSelection::remove, r);
- list<boost::shared_ptr<Route> >::iterator i;
+ RouteUISelection::iterator i;
if ((i = find (routes.begin(), routes.end(), r)) != routes.end()) {
routes.erase (i);
+ (*i)->set_selected (false);
RoutesChanged ();
}
}
void
-RouteRedirectSelection::set (boost::shared_ptr<Route> r)
+RouteRedirectSelection::set (RouteUI* r)
{
clear_routes ();
add (r);
}
bool
-RouteRedirectSelection::selected (boost::shared_ptr<Route> r)
+RouteRedirectSelection::selected (RouteUI* r)
{
return find (routes.begin(), routes.end(), r) != routes.end();
}
diff --git a/gtk2_ardour/route_processor_selection.h b/gtk2_ardour/route_processor_selection.h
index df43019e91..08616f0d50 100644
--- a/gtk2_ardour/route_processor_selection.h
+++ b/gtk2_ardour/route_processor_selection.h
@@ -24,13 +24,13 @@
#include "pbd/signals.h"
#include "processor_selection.h"
-#include "route_selection.h"
+#include "route_ui_selection.h"
class RouteRedirectSelection : public PBD::ScopedConnectionList, public sigc::trackable
{
public:
ProcessorSelection processors;
- RouteSelection routes;
+ RouteUISelection routes;
RouteRedirectSelection() {}
@@ -45,17 +45,17 @@ class RouteRedirectSelection : public PBD::ScopedConnectionList, public sigc::tr
void set (XMLNode* node);
void add (XMLNode* node);
- void set (boost::shared_ptr<ARDOUR::Route>);
- void add (boost::shared_ptr<ARDOUR::Route>);
- void remove (boost::shared_ptr<ARDOUR::Route>);
+ void set (RouteUI*);
+ void add (RouteUI*);
+ void remove (RouteUI*);
void clear_processors ();
void clear_routes ();
- bool selected (boost::shared_ptr<ARDOUR::Route>);
+ bool selected (RouteUI*);
private:
- void removed (boost::weak_ptr<ARDOUR::Route>);
+ void removed (RouteUI*);
};
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index 007c35a5b6..552439b993 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -1936,3 +1936,9 @@ RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
send_blink_connection.disconnect ();
}
}
+
+RouteGroup*
+RouteUI::route_group() const
+{
+ return _route->route_group();
+}
diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h
index 8c774522ee..1240de8716 100644
--- a/gtk2_ardour/route_ui.h
+++ b/gtk2_ardour/route_ui.h
@@ -36,6 +36,7 @@
#include "ardour/track.h"
#include "axis_view.h"
+#include "selectable.h"
namespace ARDOUR {
class AudioTrack;
@@ -70,6 +71,7 @@ class RouteUI : public virtual AxisView
bool has_audio_outputs () const;
boost::shared_ptr<ARDOUR::Route> route() const { return _route; }
+ ARDOUR::RouteGroup* route_group() const;
boost::shared_ptr<ARDOUR::Track> track() const;
boost::shared_ptr<ARDOUR::AudioTrack> audio_track() const;
diff --git a/gtk2_ardour/route_selection.h b/gtk2_ardour/route_ui_selection.h
index c11feabc13..b26e1c6f54 100644
--- a/gtk2_ardour/route_selection.h
+++ b/gtk2_ardour/route_ui_selection.h
@@ -17,17 +17,14 @@
*/
-#ifndef __ardour_gtk_route_selection_h__
-#define __ardour_gtk_route_selection_h__
+#ifndef __ardour_gtk_route_ui_selection_h__
+#define __ardour_gtk_route_ui_selection_h__
-#include <boost/shared_ptr.hpp>
-#include <list>
+#include <set>
-namespace ARDOUR {
- class Route;
-}
+class RouteUI;
-struct RouteSelection : std::list<boost::shared_ptr<ARDOUR::Route> > {};
+struct RouteUISelection : std::set<RouteUI*> {};
-#endif /* __ardour_gtk_route_selection_h__ */
+#endif /* __ardour_gtk_route_ui_selection_h__ */
diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h
index 59315df055..790274c626 100644
--- a/gtk2_ardour/time_axis_view.h
+++ b/gtk2_ardour/time_axis_view.h
@@ -131,7 +131,7 @@ class TimeAxisView : public virtual AxisView
/** @return true if hidden, otherwise false */
bool hidden () const { return _hidden; }
- virtual void set_selected (bool);
+ void set_selected (bool);
/**
* potential handler for entered events
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index a0a1861001..1aabd02f1a 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -148,6 +148,7 @@ gtk2_ardour_sources = [
'midi_tracer.cc',
'missing_file_dialog.cc',
'missing_plugin_dialog.cc',
+ 'mixer_actor.cc',
'mixer_group_tabs.cc',
'mixer_strip.cc',
'mixer_ui.cc',