drastic overhaul of keyboard handling in mixer window. real bindings, key events handled at window level, actions for all processor ops. still the confusing mess of old crap for the processor box context menu (it will die, i feel it)

git-svn-id: svn://localhost/ardour2/branches/3.0@10442 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis
2011-11-04 17:53:21 +00:00
parent fd2aea1037
commit 8f078d7fd4
17 changed files with 637 additions and 318 deletions

View File

@@ -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>

266
gtk2_ardour/mixer_actor.cc Normal file
View File

@@ -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 ();
}
}
}

74
gtk2_ardour/mixer_actor.h Normal file
View File

@@ -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__ */

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
};

View File

@@ -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)
void
ProcessorBox::processor_operation (ProcessorOperation op)
{
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)
{
bool ret = false;
ProcSelection targets;
@@ -756,57 +723,32 @@ ProcessorBox::processor_key_release_event (GdkEventKey *ev)
}
}
switch (op) {
case ProcessorsSelectAll:
processor_display.select_all ();
break;
switch (ev->keyval) {
case GDK_a:
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
processor_display.select_all ();
ret = true;
case ProcessorsCopy:
copy_processors (targets);
break;
case ProcessorsCut:
cut_processors (targets);
break;
case ProcessorsPaste:
if (targets.empty()) {
paste_processors ();
} else {
paste_processors (targets.front());
}
break;
case GDK_c:
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
copy_processors (targets);
ret = true;
}
break;
case GDK_x:
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
cut_processors (targets);
ret = true;
}
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;
}
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
@@ -1402,14 +1341,6 @@ ProcessorBox::can_cut () const
return false;
}
void
ProcessorBox::cut_processors ()
{
ProcSelection to_be_removed;
get_selected_processors (to_be_removed);
}
void
ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
{
@@ -1451,14 +1382,6 @@ ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
redisplay_processors ();
}
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)
{
@@ -1493,14 +1416,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)
{
@@ -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

View File

@@ -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 ();

View File

@@ -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);
MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
if (ms) {
ms->CatchDeletion.connect (*this, invalidator (*this), ui_bind (&RouteRedirectSelection::remove, this, _1), gui_context());
}
RoutesChanged();
}
}
}
void
RouteRedirectSelection::removed (boost::weak_ptr<Route> wr)
{
boost::shared_ptr<Route> r (wr.lock());
if (!r) {
return;
}
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();
}

View File

@@ -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*);
};

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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',