diff options
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/mixer.bindings | 20 | ||||
-rw-r--r-- | gtk2_ardour/mixer_actor.cc | 266 | ||||
-rw-r--r-- | gtk2_ardour/mixer_actor.h | 74 | ||||
-rw-r--r-- | gtk2_ardour/mixer_group_tabs.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/mixer_strip.cc | 159 | ||||
-rw-r--r-- | gtk2_ardour/mixer_strip.h | 14 | ||||
-rw-r--r-- | gtk2_ardour/mixer_ui.cc | 165 | ||||
-rw-r--r-- | gtk2_ardour/mixer_ui.h | 13 | ||||
-rw-r--r-- | gtk2_ardour/processor_box.cc | 131 | ||||
-rw-r--r-- | gtk2_ardour/processor_box.h | 17 | ||||
-rw-r--r-- | gtk2_ardour/route_processor_selection.cc | 40 | ||||
-rw-r--r-- | gtk2_ardour/route_processor_selection.h | 14 | ||||
-rw-r--r-- | gtk2_ardour/route_ui.cc | 6 | ||||
-rw-r--r-- | gtk2_ardour/route_ui.h | 2 | ||||
-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.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 1 |
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', |