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:
Paul Davis 2006-05-19 20:10:35 +00:00
parent 50ee09e80f
commit 9c6984dbbb
16 changed files with 212 additions and 101 deletions

View file

@ -61,7 +61,7 @@ AddRouteDialog::AddRouteDialog ()
: Dialog (_("ardour: add track/bus")), : Dialog (_("ardour: add track/bus")),
track_button (_("Tracks")), track_button (_("Tracks")),
bus_button (_("Busses")), bus_button (_("Busses")),
routes_adjustment (1, 1, 32, 1, 4), routes_adjustment (1, 1, 128, 1, 4),
routes_spinner (routes_adjustment) routes_spinner (routes_adjustment)
{ {
if (channel_combo_strings.empty()) { if (channel_combo_strings.empty()) {

View file

@ -34,6 +34,7 @@
#include <ardour/session.h> #include <ardour/session.h>
#include <ardour/control_protocol_manager.h> #include <ardour/control_protocol_manager.h>
#include <ardour/control_protocol.h>
#include "i18n.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) { for (i = ControlProtocolManager::instance().control_protocol_info.begin(); i != ControlProtocolManager::instance().control_protocol_info.end(); ++i) {
string action_name = "Toggle"; if (!(*i)->mandatory) {
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); string action_name = "Toggle";
action_name += legalize_for_path ((*i)->name);
if ((*i)->protocol || (*i)->requested) { action_name += "Surface";
tact->set_active ();
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"; ui += "</menu>\n</menu>\n</menubar>\n";

View file

@ -536,6 +536,31 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
return ret; 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 bool
AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op) AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
{ {

View file

@ -64,6 +64,7 @@ class AutomationTimeAxisView : public TimeAxisView {
bool cut_copy_clear (Selection&, Editing::CutCopyOp); bool cut_copy_clear (Selection&, Editing::CutCopyOp);
bool cut_copy_clear_objects (PointSelection&, Editing::CutCopyOp); bool cut_copy_clear_objects (PointSelection&, Editing::CutCopyOp);
bool paste (jack_nframes_t, float times, Selection&, size_t nth); bool paste (jack_nframes_t, float times, Selection&, size_t nth);
void reset_objects (PointSelection&);
void add_ghost (GhostRegion*); void add_ghost (GhostRegion*);
void remove_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_one (AutomationLine&, Selection&, Editing::CutCopyOp);
bool cut_copy_clear_objects_one (AutomationLine&, PointSelection&, 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); 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; virtual void set_automation_state (ARDOUR::AutoState) = 0;
bool ignore_state_request; bool ignore_state_request;

View file

@ -3143,19 +3143,25 @@ Editor::set_selected_control_point_from_click (Selection::Operation op, bool wit
return; return;
} }
if (with_undo) { /* select this point and any others that it represents */
begin_reversible_command (_("set selected control point"));
}
switch (op) { bool commit;
case Selection::Set:
break;
case Selection::Toggle:
break;
case Selection::Extend:
break;
}
if (with_undo) { 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 (); commit_reversible_command ();
} }
} }

View file

@ -841,6 +841,7 @@ class Editor : public PublicEditor
/* EDITING OPERATIONS */ /* EDITING OPERATIONS */
void reset_point_selection ();
void toggle_region_mute (); void toggle_region_mute ();
void toggle_region_opaque (); void toggle_region_opaque ();
void raise_region (); void raise_region ();

View file

@ -52,77 +52,78 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
switch (ev->direction) { switch (ev->direction) {
case GDK_SCROLL_UP: case GDK_SCROLL_UP:
if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
//if (ev->state == GDK_CONTROL_MASK) { //if (ev->state == GDK_CONTROL_MASK) {
/* XXX /* XXX
the ev->x will be out of step with the canvas 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 if we're in mid zoom, so we have to get the damn mouse
pointer again pointer again
*/ */
track_canvas.get_pointer (x, y); track_canvas.get_pointer (x, y);
track_canvas.window_to_world (x, y, wx, wy); track_canvas.window_to_world (x, y, wx, wy);
wx += horizontal_adjustment.get_value(); wx += horizontal_adjustment.get_value();
wy += vertical_adjustment.get_value(); wy += vertical_adjustment.get_value();
GdkEvent event; GdkEvent event;
event.type = GDK_BUTTON_RELEASE; event.type = GDK_BUTTON_RELEASE;
event.button.x = wx; event.button.x = wx;
event.button.y = wy; event.button.y = wy;
jack_nframes_t where = event_frame (&event, 0, 0); jack_nframes_t where = event_frame (&event, 0, 0);
temporal_zoom_to_frame (true, where); temporal_zoom_to_frame (true, where);
return true; return true;
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
if (!current_stepping_trackview) { if (!current_stepping_trackview) {
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); 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)))) { if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
return false; 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); break;
current_stepping_trackview->step_height (true);
return true;
} else {
scroll_tracks_up_line ();
return true;
}
break;
case GDK_SCROLL_DOWN: case GDK_SCROLL_DOWN:
if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
//if (ev->state == GDK_CONTROL_MASK) { //if (ev->state == GDK_CONTROL_MASK) {
track_canvas.get_pointer (x, y); track_canvas.get_pointer (x, y);
track_canvas.window_to_world (x, y, wx, wy); track_canvas.window_to_world (x, y, wx, wy);
wx += horizontal_adjustment.get_value(); wx += horizontal_adjustment.get_value();
wy += vertical_adjustment.get_value(); wy += vertical_adjustment.get_value();
GdkEvent event; GdkEvent event;
event.type = GDK_BUTTON_RELEASE; event.type = GDK_BUTTON_RELEASE;
event.button.x = wx; event.button.x = wx;
event.button.y = wy; event.button.y = wy;
jack_nframes_t where = event_frame (&event, 0, 0); jack_nframes_t where = event_frame (&event, 0, 0);
temporal_zoom_to_frame (false, where); temporal_zoom_to_frame (false, where);
return true; return true;
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
if (!current_stepping_trackview) { if (!current_stepping_trackview) {
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); 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)))) { if (!(current_stepping_trackview = dynamic_cast<AudioTimeAxisView*> (trackview_by_y_position (ev->y)))) {
return false; 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); break;
current_stepping_trackview->step_height (false);
return true;
} else {
scroll_tracks_down_line ();
return true;
}
break;
default: default:
/* no left/right handling yet */ /* no left/right handling yet */
break; break;
} }
return false; return false;
} }
@ -547,6 +548,12 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C
clicked_regionview = 0; clicked_regionview = 0;
break; break;
case GDK_SCROLL_UP:
break;
case GDK_SCROLL_DOWN:
break;
default: default:
break; break;
} }

View file

@ -328,7 +328,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
case PanAutomationControlPointItem: case PanAutomationControlPointItem:
case RedirectAutomationControlPointItem: case RedirectAutomationControlPointItem:
if ((cp = static_cast<ControlPoint *> (item->get_data ("control_point"))) != 0) { 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; break;
@ -2495,13 +2495,26 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
cp->line.point_drag (*cp, cx_frames , fraction, push); cp->line.point_drag (*cp, cx_frames , fraction, push);
set_verbose_canvas_cursor_text (cp->line.get_verbose_cursor_string (fraction)); set_verbose_canvas_cursor_text (cp->line.get_verbose_cursor_string (fraction));
drag_info.first_move = false;
} }
void void
Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event) Editor::control_point_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
{ {
ControlPoint* cp = reinterpret_cast<ControlPoint *> (drag_info.data); 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); cp->line.end_drag (cp);
} }

View file

@ -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); (*iter)->get_selectables (start, end, top, bot, touched);
} }
cerr << "select all within found " << touched.size() << endl;
begin_reversible_command (_("select all within")); begin_reversible_command (_("select all within"));
switch (op) { switch (op) {
case Selection::Toggle: case Selection::Toggle:
cerr << "toggle\n";
selection->add (touched); selection->add (touched);
break; break;
case Selection::Set: case Selection::Set:
cerr << "set\n";
selection->set (touched); selection->set (touched);
break; break;
case Selection::Extend: case Selection::Extend:
cerr << "extend\n";
/* not defined yet */ /* not defined yet */
break; break;
} }
cerr << "selection now has " << selection->points.size() << endl;
commit_reversible_command (); commit_reversible_command ();
return !touched.empty(); return !touched.empty();
} }
@ -3148,6 +3157,23 @@ Editor::duplicate_selection (float times)
commit_reversible_command (); 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 void
Editor::center_playhead () Editor::center_playhead ()
{ {

View file

@ -633,6 +633,8 @@ Selection::add (list<Selectable*>& selectables)
if (!autos.empty()) { if (!autos.empty()) {
add (autos); add (autos);
} }
cerr << "Selection @ " << this << " has " << points.size() << " points\n";
} }
void void
@ -651,6 +653,6 @@ Selection::add (vector<AutomationSelectable*>& autos)
points.push_back (**i); points.push_back (**i);
delete *i; delete *i;
} }
PointsChanged (); PointsChanged ();
} }

View file

@ -83,10 +83,11 @@ class ControlProtocol : public sigc::trackable, public BasicUI {
extern "C" { extern "C" {
struct ControlProtocolDescriptor { struct ControlProtocolDescriptor {
const char* name; /* descriptive */ const char* name; /* descriptive */
const char* id; /* unique and version-specific */ const char* id; /* unique and version-specific */
void* ptr; /* protocol can store a value here */ void* ptr; /* protocol can store a value here */
void* module; /* not for public access */ void* module; /* not for public access */
int mandatory; /* if non-zero, always load and do not make optional */
ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*); ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*); void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);

View file

@ -22,6 +22,7 @@ struct ControlProtocolInfo {
std::string name; std::string name;
std::string path; std::string path;
bool requested; bool requested;
bool mandatory;
}; };
class ControlProtocolManager : public sigc::trackable, public Stateful class ControlProtocolManager : public sigc::trackable, public Stateful
@ -35,6 +36,7 @@ struct ControlProtocolInfo {
void set_session (Session&); void set_session (Session&);
void discover_control_protocols (std::string search_path); void discover_control_protocols (std::string search_path);
void foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*>); void foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*>);
void load_mandatory_protocols ();
ControlProtocol* instantiate (ControlProtocolInfo&); ControlProtocol* instantiate (ControlProtocolInfo&);
int teardown (ControlProtocolInfo&); int teardown (ControlProtocolInfo&);

View file

@ -163,8 +163,10 @@ ControlProtocol::route_get_rec_enable (uint32_t table_index)
AudioTrack* at = dynamic_cast<AudioTrack*>(r); AudioTrack* at = dynamic_cast<AudioTrack*>(r);
if (at) { if (at) {
at->record_enabled (); return at->record_enabled ();
} }
return false;
} }

View file

@ -45,7 +45,7 @@ ControlProtocolManager::set_session (Session& s)
_session->going_away.connect (mem_fun (*this, &ControlProtocolManager::drop_session)); _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) { 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); instantiate (**i);
(*i)->requested = false; (*i)->requested = false;
} }
@ -102,6 +102,10 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
return 0; return 0;
} }
if (cpi.mandatory) {
return 0;
}
cpi.descriptor->destroy (cpi.descriptor, cpi.protocol); 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)); 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 void
ControlProtocolManager::discover_control_protocols (string path) ControlProtocolManager::discover_control_protocols (string path)
{ {
@ -156,13 +175,13 @@ ControlProtocolManager::control_protocol_discover (string path)
info->path = path; info->path = path;
info->protocol = 0; info->protocol = 0;
info->requested = false; info->requested = false;
info->mandatory = descriptor->mandatory;
control_protocol_info.push_back (info); control_protocol_info.push_back (info);
cerr << "discovered control surface protocol \"" << info->name << '"' << endl; cerr << "discovered control surface protocol \"" << info->name << '"' << endl;
dlclose (descriptor->module); dlclose (descriptor->module);
} }
return 0; return 0;

View file

@ -28,6 +28,7 @@ static ControlProtocolDescriptor generic_midi_descriptor = {
id : "uri://ardour.org/surfaces/generic_midi:0", id : "uri://ardour.org/surfaces/generic_midi:0",
ptr : 0, ptr : 0,
module : 0, module : 0,
mandatory : 0,
initialize : new_generic_midi_protocol, initialize : new_generic_midi_protocol,
destroy : delete_generic_midi_protocol destroy : delete_generic_midi_protocol
}; };

View file

@ -29,9 +29,9 @@ static ControlProtocolDescriptor tranzport_descriptor = {
id : "uri://ardour.org/surfaces/tranzport:0", id : "uri://ardour.org/surfaces/tranzport:0",
ptr : 0, ptr : 0,
module : 0, module : 0,
mandatory : 1,
initialize : new_tranzport_protocol, initialize : new_tranzport_protocol,
destroy : delete_tranzport_protocol destroy : delete_tranzport_protocol
}; };