#include "gtkmm2ext/choice.h"
#include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
-#include "ardour/audio_diskstream.h"
#include "ardour/audio_track.h"
#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
#include "control_protocol/control_protocol.h"
+#include "actions.h"
+#include "actions.h"
+#include "analysis_window.h"
#include "audio_clock.h"
-#include "editor.h"
-#include "debug.h"
-#include "keyboard.h"
-#include "marker.h"
-#include "playlist_selector.h"
#include "audio_region_view.h"
-#include "rgb_macros.h"
-#include "selection.h"
#include "audio_streamview.h"
-#include "time_axis_view.h"
#include "audio_time_axis.h"
-#include "utils.h"
-#include "crossfade_view.h"
+#include "automation_time_axis.h"
+#include "bundle_manager.h"
#include "canvas-noevent-text.h"
-#include "editing.h"
-#include "public_editor.h"
-#include "crossfade_edit.h"
#include "canvas_impl.h"
-#include "actions.h"
-#include "sfdb_ui.h"
-#include "gui_thread.h"
-#include "simpleline.h"
-#include "rhythm_ferret.h"
-#include "actions.h"
-#include "tempo_lines.h"
-#include "analysis_window.h"
-#include "bundle_manager.h"
-#include "global_port_matrix.h"
+#include "crossfade_edit.h"
+#include "crossfade_view.h"
+#include "debug.h"
+#include "editing.h"
+#include "editor.h"
+#include "editor_cursors.h"
#include "editor_drag.h"
#include "editor_group_tabs.h"
-#include "automation_time_axis.h"
-#include "editor_routes.h"
-#include "midi_time_axis.h"
-#include "mixer_strip.h"
-#include "editor_route_groups.h"
-#include "editor_regions.h"
#include "editor_locations.h"
+#include "editor_regions.h"
+#include "editor_route_groups.h"
+#include "editor_routes.h"
#include "editor_snapshots.h"
#include "editor_summary.h"
-#include "region_layering_order_editor.h"
+#include "global_port_matrix.h"
+#include "gui_object.h"
+#include "gui_thread.h"
+#include "keyboard.h"
+#include "marker.h"
+#include "midi_time_axis.h"
+#include "mixer_strip.h"
#include "mouse_cursors.h"
-#include "editor_cursors.h"
+#include "playlist_selector.h"
+#include "public_editor.h"
+#include "region_layering_order_editor.h"
+#include "rgb_macros.h"
+#include "rhythm_ferret.h"
+#include "selection.h"
+#include "sfdb_ui.h"
+#include "simpleline.h"
+#include "tempo_lines.h"
+#include "time_axis_view.h"
+#include "utils.h"
#include "i18n.h"
, toolbar_selection_clock_table (2,3)
, automation_mode_button (_("mode"))
- , global_automation_button (_("automation"))
, _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
, midi_panic_button (_("Panic"))
ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), ui_bind (&Editor::control_scroll, this, _1), gui_context());
+ ControlProtocol::SelectByRID.connect (*this, invalidator (*this), ui_bind (&Editor::control_select, this, _1), gui_context());
BasicUI::AccessAction.connect (*this, invalidator (*this), ui_bind (&Editor::access_action, this, _1, _2), gui_context());
/* problematic: has to return a value and thus cannot be x-thread */
if (current_mixer_strip) {
current_mixer_strip->hide_things ();
+ current_mixer_strip->parameter_changed ("mixer-strip-visibility");
}
}
temporal_zoom (fpu);
}
+void
+Editor::control_select (uint32_t rid)
+{
+ /* handles the (static) signal from the ControlProtocol class that
+ * requests setting the selected track to a given RID
+ */
+
+ if (!_session) {
+ return;
+ }
+
+ boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
+
+ if (!r) {
+ return;
+ }
+
+ TimeAxisView* tav = axis_view_from_route (r);
+
+ if (tav) {
+ selection->set (tav);
+ } else {
+ selection->clear_tracks ();
+ }
+}
+
void
Editor::control_scroll (float fraction)
{
compute_fixed_ruler_scale ();
+ /* Make sure we have auto loop and auto punch ranges */
+
+ Location* loc = _session->locations()->auto_loop_location();
+ if (loc == 0) {
+ loc = new Location (*_session, 0, _session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
+
+ if (loc->start() == loc->end()) {
+ loc->set_end (loc->start() + 1);
+ }
+
+ _session->locations()->add (loc, false);
+ _session->set_auto_loop_location (loc);
+ } else {
+ // force name
+ loc->set_name (_("Loop"));
+ }
+
+ loc = _session->locations()->auto_punch_location();
+
+ if (loc == 0) {
+ loc = new Location (*_session, 0, _session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
+
+ if (loc->start() == loc->end()) {
+ loc->set_end (loc->start() + 1);
+ }
+
+ _session->locations()->add (loc, false);
+ _session->set_auto_punch_location (loc);
+ } else {
+ // force name
+ loc->set_name (_("Punch"));
+ }
+
+ refresh_location_display ();
+
+ /* This must happen after refresh_location_display(), as (amongst other things) we restore
+ the selected Marker; this needs the LocationMarker list to be available.
+ */
XMLNode* node = ARDOUR_UI::instance()->editor_settings();
set_state (*node, Stateful::loading_state_version);
playhead_cursor->canvas_item.show ();
- Location* loc = _session->locations()->auto_loop_location();
- if (loc == 0) {
- loc = new Location (*_session, 0, _session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
-
- if (loc->start() == loc->end()) {
- loc->set_end (loc->start() + 1);
- }
-
- _session->locations()->add (loc, false);
- _session->set_auto_loop_location (loc);
- } else {
- // force name
- loc->set_name (_("Loop"));
- }
-
- loc = _session->locations()->auto_punch_location();
-
- if (loc == 0) {
- loc = new Location (*_session, 0, _session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
-
- if (loc->start() == loc->end()) {
- loc->set_end (loc->start() + 1);
- }
-
- _session->locations()->add (loc, false);
- _session->set_auto_punch_location (loc);
- } else {
- // force name
- loc->set_name (_("Punch"));
- }
-
boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
Config->map_parameters (pc);
_session->config.map_parameters (pc);
- refresh_location_display ();
-
restore_ruler_visibility ();
//tempo_map_changed (PropertyChange (0));
_session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
}
/* register for undo history */
- _session->register_with_memento_command_factory(_id, this);
+ _session->register_with_memento_command_factory(id(), this);
ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
- edit_items.push_back (MenuElem (_("Export Range"), sigc::mem_fun(*this, &Editor::export_selection)));
+ edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
}
{
const XMLProperty* prop;
XMLNode* geometry;
- int x, y, xoff, yoff;
+ int x, y;
Gdk::Geometry g;
- if ((prop = node.property ("id")) != 0) {
- _id = prop->value ();
- }
+ set_id (node);
g.base_width = default_width;
g.base_height = default_height;
x = 1;
y = 1;
- xoff = 0;
- yoff = 21;
if ((geometry = find_named_node (node, "geometry")) != 0) {
if (prop) {
y = atoi (prop->value());
}
-
- if ((prop = geometry->property ("x_off")) == 0) {
- prop = geometry->property ("x-off");
- }
- if (prop) {
- xoff = atoi (prop->value());
- }
- if ((prop = geometry->property ("y_off")) == 0) {
- prop = geometry->property ("y-off");
- }
- if (prop) {
- yoff = atoi (prop->value());
- }
}
set_default_size (g.base_width, g.base_height);
}
if ((prop = node.property ("stationary-playhead"))) {
- bool yn = (prop->value() == "yes");
+ bool yn = string_is_affirmative (prop->value());
set_stationary_playhead (yn);
RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
if (act) {
XMLNode* node = new XMLNode ("Editor");
char buf[32];
- _id.print (buf, sizeof (buf));
+ id().print (buf, sizeof (buf));
node->add_property ("id", buf);
if (is_realized()) {
Glib::RefPtr<Gdk::Window> win = get_window();
- int x, y, xoff, yoff, width, height;
+ int x, y, width, height;
win->get_root_origin(x, y);
- win->get_position(xoff, yoff);
win->get_size(width, height);
XMLNode* geometry = new XMLNode ("geometry");
geometry->add_property("x-pos", string(buf));
snprintf(buf, sizeof(buf), "%d", y);
geometry->add_property("y-pos", string(buf));
- snprintf(buf, sizeof(buf), "%d", xoff);
- geometry->add_property("x-off", string(buf));
- snprintf(buf, sizeof(buf), "%d", yoff);
- geometry->add_property("y-off", string(buf));
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
geometry->add_property("edit-horizontal-pane-pos", string(buf));
geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
/* Midi sound notes */
midi_sound_notes.add (*(manage (new Image (::get_icon("midi_sound_notes")))));
midi_sound_notes.unset_flags (CAN_FOCUS);
+ midi_sound_notes.set_name (X_("MidiSoundNotesButton"));
/* Panic */
XMLProperty* prop;
char buf[32];
XMLNode* node = ARDOUR_UI::instance()->editor_settings();
- int width, height;
enum Pane {
Horizontal = 0x1,
static Pane done;
- XMLNode* geometry;
-
- width = default_width;
- height = default_height;
-
- if ((geometry = find_named_node (*node, "geometry")) != 0) {
-
- prop = geometry->property ("x-size");
- if (prop) {
- width = atoi (prop->value());
- }
- prop = geometry->property ("y-size");
- if (prop) {
- height = atoi (prop->value());
- }
- }
+ XMLNode* geometry = find_named_node (*node, "geometry");
if (which == static_cast<Paned*> (&edit_pane)) {
edit_pane.set_position (post_maximal_horizontal_pane_position);
}
- if (post_maximal_editor_height) {
- editor_summary_pane.set_position (post_maximal_vertical_pane_position -
- abs(post_maximal_editor_height - pre_maximal_editor_height));
- } else {
- editor_summary_pane.set_position (post_maximal_vertical_pane_position);
- }
+ /* Hack: we must do this in an idle handler for it to work; see comment in
+ restore_editing_space()
+ */
+
+ Glib::signal_idle().connect (
+ sigc::bind (
+ sigc::mem_fun (*this, &Editor::idle_reset_vertical_pane_position),
+ post_maximal_vertical_pane_position
+ )
+ );
if (Config->get_keep_tearoffs()) {
_mouse_mode_tearoff->set_visible (true);
}
+bool
+Editor::idle_reset_vertical_pane_position (int p)
+{
+ editor_summary_pane.set_position (p);
+ return false;
+}
+
void
Editor::restore_editing_space ()
{
post_maximal_editor_height = this->get_height();
edit_pane.set_position (pre_maximal_horizontal_pane_position + abs(this->get_width() - pre_maximal_editor_width));
- editor_summary_pane.set_position (pre_maximal_vertical_pane_position + abs(this->get_height() - pre_maximal_editor_height));
+
+ /* This is a bit of a hack, but it seems that if you set the vertical pane position
+ here it gets reset to some wrong value after this method has finished. Doing
+ the setup in an idle callback seems to work.
+ */
+ Glib::signal_idle().connect (
+ sigc::bind (
+ sigc::mem_fun (*this, &Editor::idle_reset_vertical_pane_position),
+ pre_maximal_vertical_pane_position
+ )
+ );
}
/**
}
}
+Editor::VisualState::VisualState ()
+ : gui_state (new GUIObjectState)
+{
+}
+
+Editor::VisualState::~VisualState ()
+{
+ delete gui_state;
+}
+
Editor::VisualState*
Editor::current_visual_state (bool with_tracks)
{
vs->leftmost_frame = leftmost_frame;
vs->zoom_focus = zoom_focus;
- if (with_tracks) {
- for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
- vs->track_states.push_back (TAVState ((*i), &(*i)->get_state()));
- }
+ if (with_tracks) {
+ *(vs->gui_state) = *ARDOUR_UI::instance()->gui_object_state;
}
return vs;
set_zoom_focus (vs.zoom_focus);
reposition_and_zoom (vs.leftmost_frame, vs.frames_per_unit);
+
+ *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
- for (list<TAVState>::iterator i = vs.track_states.begin(); i != vs.track_states.end(); ++i) {
- TrackViewList::iterator t;
-
- /* check if the track still exists - it could have been deleted */
-
- if ((t = find (track_views.begin(), track_views.end(), i->first)) != track_views.end()) {
- (*t)->set_state (*(i->second), Stateful::loading_state_version);
- }
- }
-
-
- if (!vs.track_states.empty()) {
- _routes->update_visibility ();
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->reset_visual_state ();
}
+ _routes->update_visibility ();
_routes->resume_redisplay ();
no_save_visual = false;
DataType dt = route->input()->default_type();
if (dt == ARDOUR::DataType::AUDIO) {
- rtv = new AudioTimeAxisView (*this, _session, route, *track_canvas);
+ rtv = new AudioTimeAxisView (*this, _session, *track_canvas);
+ rtv->set_route (route);
} else if (dt == ARDOUR::DataType::MIDI) {
- rtv = new MidiTimeAxisView (*this, _session, route, *track_canvas);
+ rtv = new MidiTimeAxisView (*this, _session, *track_canvas);
+ rtv->set_route (route);
} else {
throw unknown_type();
}
return true;
}
+void
+Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& items = _control_point_context_menu.items ();
+ items.clear ();
+
+ items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
+ items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
+ if (!can_remove_control_point (item)) {
+ items.back().set_sensitive (false);
+ }
+
+ _control_point_context_menu.popup (event->button.button, event->button.time);
+}