mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 16:46:35 +01:00
allow for mandatory control protocols, plus some ongoing work on automation control point selection (unfinished)
git-svn-id: svn://localhost/trunk/ardour2@516 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
50ee09e80f
commit
9c6984dbbb
16 changed files with 212 additions and 101 deletions
|
|
@ -61,7 +61,7 @@ AddRouteDialog::AddRouteDialog ()
|
|||
: Dialog (_("ardour: add track/bus")),
|
||||
track_button (_("Tracks")),
|
||||
bus_button (_("Busses")),
|
||||
routes_adjustment (1, 1, 32, 1, 4),
|
||||
routes_adjustment (1, 1, 128, 1, 4),
|
||||
routes_spinner (routes_adjustment)
|
||||
{
|
||||
if (channel_combo_strings.empty()) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/control_protocol_manager.h>
|
||||
#include <ardour/control_protocol.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
@ -472,24 +473,27 @@ ARDOUR_UI::build_control_surface_menu ()
|
|||
|
||||
for (i = ControlProtocolManager::instance().control_protocol_info.begin(); i != ControlProtocolManager::instance().control_protocol_info.end(); ++i) {
|
||||
|
||||
string action_name = "Toggle";
|
||||
action_name += legalize_for_path ((*i)->name);
|
||||
action_name += "Surface";
|
||||
|
||||
string action_label = (*i)->name;
|
||||
|
||||
Glib::RefPtr<Action> act = ActionManager::register_toggle_action (editor->editor_actions, action_name.c_str(), action_label.c_str(),
|
||||
(bind (mem_fun (*this, &ARDOUR_UI::toggle_control_protocol), *i)));
|
||||
if (!(*i)->mandatory) {
|
||||
|
||||
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
|
||||
|
||||
if ((*i)->protocol || (*i)->requested) {
|
||||
tact->set_active ();
|
||||
string action_name = "Toggle";
|
||||
action_name += legalize_for_path ((*i)->name);
|
||||
action_name += "Surface";
|
||||
|
||||
string action_label = (*i)->name;
|
||||
|
||||
Glib::RefPtr<Action> act = ActionManager::register_toggle_action (editor->editor_actions, action_name.c_str(), action_label.c_str(),
|
||||
(bind (mem_fun (*this, &ARDOUR_UI::toggle_control_protocol), *i)));
|
||||
|
||||
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
|
||||
|
||||
if ((*i)->protocol || (*i)->requested) {
|
||||
tact->set_active ();
|
||||
}
|
||||
|
||||
ui += "<menuitem action='";
|
||||
ui += action_name;
|
||||
ui += "'/>\n";
|
||||
}
|
||||
|
||||
ui += "<menuitem action='";
|
||||
ui += action_name;
|
||||
ui += "'/>\n";
|
||||
}
|
||||
|
||||
ui += "</menu>\n</menu>\n</menubar>\n";
|
||||
|
|
|
|||
|
|
@ -536,6 +536,31 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
|
|||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::reset_objects (PointSelection& selection)
|
||||
{
|
||||
for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
|
||||
reset_objects_one ((**i), selection);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection& selection)
|
||||
{
|
||||
AutomationList& alist (line.the_list());
|
||||
|
||||
_session.add_undo (alist.get_memento());
|
||||
|
||||
for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
|
||||
|
||||
if (&(*i).track != this) {
|
||||
continue;
|
||||
}
|
||||
|
||||
alist.reset_range ((*i).start, (*i).end);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ class AutomationTimeAxisView : public TimeAxisView {
|
|||
bool cut_copy_clear (Selection&, Editing::CutCopyOp);
|
||||
bool cut_copy_clear_objects (PointSelection&, Editing::CutCopyOp);
|
||||
bool paste (jack_nframes_t, float times, Selection&, size_t nth);
|
||||
void reset_objects (PointSelection&);
|
||||
|
||||
void add_ghost (GhostRegion*);
|
||||
void remove_ghost (GhostRegion*);
|
||||
|
|
@ -105,6 +106,7 @@ class AutomationTimeAxisView : public TimeAxisView {
|
|||
bool cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp);
|
||||
bool cut_copy_clear_objects_one (AutomationLine&, PointSelection&, Editing::CutCopyOp);
|
||||
bool paste_one (AutomationLine&, jack_nframes_t, float times, Selection&, size_t nth);
|
||||
void reset_objects_one (AutomationLine&, PointSelection&);
|
||||
|
||||
virtual void set_automation_state (ARDOUR::AutoState) = 0;
|
||||
bool ignore_state_request;
|
||||
|
|
|
|||
|
|
@ -3143,19 +3143,25 @@ Editor::set_selected_control_point_from_click (Selection::Operation op, bool wit
|
|||
return;
|
||||
}
|
||||
|
||||
if (with_undo) {
|
||||
begin_reversible_command (_("set selected control point"));
|
||||
}
|
||||
/* select this point and any others that it represents */
|
||||
|
||||
switch (op) {
|
||||
case Selection::Set:
|
||||
break;
|
||||
case Selection::Toggle:
|
||||
break;
|
||||
case Selection::Extend:
|
||||
break;
|
||||
}
|
||||
bool commit;
|
||||
|
||||
if (with_undo) {
|
||||
begin_reversible_command (_("select control points"));
|
||||
}
|
||||
|
||||
double y1, y2;
|
||||
jack_nframes_t x1, x2;
|
||||
|
||||
x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
|
||||
x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
|
||||
y1 = clicked_control_point->get_x() - 10;
|
||||
y2 = clicked_control_point->get_y() + 10;
|
||||
|
||||
commit = select_all_within (x1, x2, y1, y2, op);
|
||||
|
||||
if (with_undo && commit) {
|
||||
commit_reversible_command ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -841,6 +841,7 @@ class Editor : public PublicEditor
|
|||
|
||||
/* EDITING OPERATIONS */
|
||||
|
||||
void reset_point_selection ();
|
||||
void toggle_region_mute ();
|
||||
void toggle_region_opaque ();
|
||||
void raise_region ();
|
||||
|
|
|
|||
|
|
@ -52,77 +52,78 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
|
|||
|
||||
switch (ev->direction) {
|
||||
case GDK_SCROLL_UP:
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
|
||||
//if (ev->state == GDK_CONTROL_MASK) {
|
||||
/* XXX
|
||||
the ev->x will be out of step with the canvas
|
||||
if we're in mid zoom, so we have to get the damn mouse
|
||||
pointer again
|
||||
*/
|
||||
track_canvas.get_pointer (x, y);
|
||||
track_canvas.window_to_world (x, y, wx, wy);
|
||||
wx += horizontal_adjustment.get_value();
|
||||
wy += vertical_adjustment.get_value();
|
||||
|
||||
GdkEvent event;
|
||||
event.type = GDK_BUTTON_RELEASE;
|
||||
event.button.x = wx;
|
||||
event.button.y = wy;
|
||||
|
||||
jack_nframes_t where = event_frame (&event, 0, 0);
|
||||
temporal_zoom_to_frame (true, where);
|
||||
return true;
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
|
||||
if (!current_stepping_trackview) {
|
||||
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
|
||||
if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
|
||||
return false;
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
|
||||
//if (ev->state == GDK_CONTROL_MASK) {
|
||||
/* XXX
|
||||
the ev->x will be out of step with the canvas
|
||||
if we're in mid zoom, so we have to get the damn mouse
|
||||
pointer again
|
||||
*/
|
||||
track_canvas.get_pointer (x, y);
|
||||
track_canvas.window_to_world (x, y, wx, wy);
|
||||
wx += horizontal_adjustment.get_value();
|
||||
wy += vertical_adjustment.get_value();
|
||||
|
||||
GdkEvent event;
|
||||
event.type = GDK_BUTTON_RELEASE;
|
||||
event.button.x = wx;
|
||||
event.button.y = wy;
|
||||
|
||||
jack_nframes_t where = event_frame (&event, 0, 0);
|
||||
temporal_zoom_to_frame (true, where);
|
||||
return true;
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
|
||||
if (!current_stepping_trackview) {
|
||||
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
|
||||
if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
gettimeofday (&last_track_height_step_timestamp, 0);
|
||||
current_stepping_trackview->step_height (true);
|
||||
return true;
|
||||
} else {
|
||||
scroll_tracks_up_line ();
|
||||
return true;
|
||||
}
|
||||
gettimeofday (&last_track_height_step_timestamp, 0);
|
||||
current_stepping_trackview->step_height (true);
|
||||
return true;
|
||||
} else {
|
||||
scroll_tracks_up_line ();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case GDK_SCROLL_DOWN:
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
|
||||
//if (ev->state == GDK_CONTROL_MASK) {
|
||||
track_canvas.get_pointer (x, y);
|
||||
track_canvas.window_to_world (x, y, wx, wy);
|
||||
wx += horizontal_adjustment.get_value();
|
||||
wy += vertical_adjustment.get_value();
|
||||
|
||||
GdkEvent event;
|
||||
event.type = GDK_BUTTON_RELEASE;
|
||||
event.button.x = wx;
|
||||
event.button.y = wy;
|
||||
|
||||
jack_nframes_t where = event_frame (&event, 0, 0);
|
||||
temporal_zoom_to_frame (false, where);
|
||||
return true;
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
|
||||
if (!current_stepping_trackview) {
|
||||
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
|
||||
if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
|
||||
return false;
|
||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
|
||||
//if (ev->state == GDK_CONTROL_MASK) {
|
||||
track_canvas.get_pointer (x, y);
|
||||
track_canvas.window_to_world (x, y, wx, wy);
|
||||
wx += horizontal_adjustment.get_value();
|
||||
wy += vertical_adjustment.get_value();
|
||||
|
||||
GdkEvent event;
|
||||
event.type = GDK_BUTTON_RELEASE;
|
||||
event.button.x = wx;
|
||||
event.button.y = wy;
|
||||
|
||||
jack_nframes_t where = event_frame (&event, 0, 0);
|
||||
temporal_zoom_to_frame (false, where);
|
||||
return true;
|
||||
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
|
||||
if (!current_stepping_trackview) {
|
||||
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
|
||||
if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
gettimeofday (&last_track_height_step_timestamp, 0);
|
||||
current_stepping_trackview->step_height (false);
|
||||
return true;
|
||||
} else {
|
||||
scroll_tracks_down_line ();
|
||||
return true;
|
||||
}
|
||||
gettimeofday (&last_track_height_step_timestamp, 0);
|
||||
current_stepping_trackview->step_height (false);
|
||||
return true;
|
||||
} else {
|
||||
scroll_tracks_down_line ();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* no left/right handling yet */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -547,6 +548,12 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C
|
|||
clicked_regionview = 0;
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_UP:
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
|
|||
case PanAutomationControlPointItem:
|
||||
case RedirectAutomationControlPointItem:
|
||||
if ((cp = static_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) {
|
||||
set_selected_control_point_from_click (Keyboard::selection_type (event->button.state), true);
|
||||
set_selected_control_point_from_click (Keyboard::selection_type (event->button.state), false);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2495,13 +2495,26 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
|
|||
cp->line.point_drag (*cp, cx_frames , fraction, push);
|
||||
|
||||
set_verbose_canvas_cursor_text (cp->line.get_verbose_cursor_string (fraction));
|
||||
|
||||
drag_info.first_move = false;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
ControlPoint* cp = reinterpret_cast<ControlPoint *> (drag_info.data);
|
||||
control_point_drag_motion_callback (item, event);
|
||||
|
||||
if (drag_info.first_move) {
|
||||
|
||||
/* just a click */
|
||||
|
||||
if ((event->type == GDK_BUTTON_RELEASE) && (event->button.button == 1) && Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
|
||||
reset_point_selection ();
|
||||
}
|
||||
|
||||
} else {
|
||||
control_point_drag_motion_callback (item, event);
|
||||
}
|
||||
cp->line.end_drag (cp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1351,18 +1351,27 @@ Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top,
|
|||
}
|
||||
(*iter)->get_selectables (start, end, top, bot, touched);
|
||||
}
|
||||
|
||||
cerr << "select all within found " << touched.size() << endl;
|
||||
|
||||
begin_reversible_command (_("select all within"));
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
cerr << "toggle\n";
|
||||
selection->add (touched);
|
||||
break;
|
||||
case Selection::Set:
|
||||
cerr << "set\n";
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
cerr << "extend\n";
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
|
||||
cerr << "selection now has " << selection->points.size() << endl;
|
||||
|
||||
commit_reversible_command ();
|
||||
return !touched.empty();
|
||||
}
|
||||
|
|
@ -3148,6 +3157,23 @@ Editor::duplicate_selection (float times)
|
|||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::reset_point_selection ()
|
||||
{
|
||||
/* reset all selected points to the relevant default value */
|
||||
|
||||
cerr << "point selection has " << selection->points.size() << " entries\n";
|
||||
|
||||
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
|
||||
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
|
||||
|
||||
if (atv) {
|
||||
atv->reset_objects (selection->points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::center_playhead ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -633,6 +633,8 @@ Selection::add (list<Selectable*>& selectables)
|
|||
if (!autos.empty()) {
|
||||
add (autos);
|
||||
}
|
||||
|
||||
cerr << "Selection @ " << this << " has " << points.size() << " points\n";
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -651,6 +653,6 @@ Selection::add (vector<AutomationSelectable*>& autos)
|
|||
points.push_back (**i);
|
||||
delete *i;
|
||||
}
|
||||
|
||||
|
||||
PointsChanged ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,10 +83,11 @@ class ControlProtocol : public sigc::trackable, public BasicUI {
|
|||
|
||||
extern "C" {
|
||||
struct ControlProtocolDescriptor {
|
||||
const char* name; /* descriptive */
|
||||
const char* id; /* unique and version-specific */
|
||||
void* ptr; /* protocol can store a value here */
|
||||
void* module; /* not for public access */
|
||||
const char* name; /* descriptive */
|
||||
const char* id; /* unique and version-specific */
|
||||
void* ptr; /* protocol can store a value here */
|
||||
void* module; /* not for public access */
|
||||
int mandatory; /* if non-zero, always load and do not make optional */
|
||||
ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
|
||||
void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ struct ControlProtocolInfo {
|
|||
std::string name;
|
||||
std::string path;
|
||||
bool requested;
|
||||
bool mandatory;
|
||||
};
|
||||
|
||||
class ControlProtocolManager : public sigc::trackable, public Stateful
|
||||
|
|
@ -35,6 +36,7 @@ struct ControlProtocolInfo {
|
|||
void set_session (Session&);
|
||||
void discover_control_protocols (std::string search_path);
|
||||
void foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*>);
|
||||
void load_mandatory_protocols ();
|
||||
|
||||
ControlProtocol* instantiate (ControlProtocolInfo&);
|
||||
int teardown (ControlProtocolInfo&);
|
||||
|
|
|
|||
|
|
@ -163,8 +163,10 @@ ControlProtocol::route_get_rec_enable (uint32_t table_index)
|
|||
AudioTrack* at = dynamic_cast<AudioTrack*>(r);
|
||||
|
||||
if (at) {
|
||||
at->record_enabled ();
|
||||
return at->record_enabled ();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ ControlProtocolManager::set_session (Session& s)
|
|||
_session->going_away.connect (mem_fun (*this, &ControlProtocolManager::drop_session));
|
||||
|
||||
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
|
||||
if ((*i)->requested) {
|
||||
if ((*i)->requested || (*i)->mandatory) {
|
||||
instantiate (**i);
|
||||
(*i)->requested = false;
|
||||
}
|
||||
|
|
@ -102,6 +102,10 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (cpi.mandatory) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
|
||||
|
||||
{
|
||||
|
|
@ -124,6 +128,21 @@ static bool protocol_filter (const string& str, void *arg)
|
|||
return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocolManager::load_mandatory_protocols ()
|
||||
{
|
||||
if (_session == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
|
||||
if ((*i)->mandatory && ((*i)->protocol == 0)) {
|
||||
info << string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name) << endmsg;
|
||||
instantiate (**i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocolManager::discover_control_protocols (string path)
|
||||
{
|
||||
|
|
@ -156,13 +175,13 @@ ControlProtocolManager::control_protocol_discover (string path)
|
|||
info->path = path;
|
||||
info->protocol = 0;
|
||||
info->requested = false;
|
||||
info->mandatory = descriptor->mandatory;
|
||||
|
||||
control_protocol_info.push_back (info);
|
||||
|
||||
cerr << "discovered control surface protocol \"" << info->name << '"' << endl;
|
||||
|
||||
dlclose (descriptor->module);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ static ControlProtocolDescriptor generic_midi_descriptor = {
|
|||
id : "uri://ardour.org/surfaces/generic_midi:0",
|
||||
ptr : 0,
|
||||
module : 0,
|
||||
mandatory : 0,
|
||||
initialize : new_generic_midi_protocol,
|
||||
destroy : delete_generic_midi_protocol
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ static ControlProtocolDescriptor tranzport_descriptor = {
|
|||
id : "uri://ardour.org/surfaces/tranzport:0",
|
||||
ptr : 0,
|
||||
module : 0,
|
||||
mandatory : 1,
|
||||
initialize : new_tranzport_protocol,
|
||||
destroy : delete_tranzport_protocol
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue