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")),
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()) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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