#include "editor_xpms"
static const gchar *_snap_type_strings[] = {
- N_("None"),
N_("CD Frames"),
N_("SMPTE Frames"),
N_("SMPTE Seconds"),
N_("Beats"),
N_("Bars"),
N_("Marks"),
- N_("Edit Point"),
N_("Region starts"),
N_("Region ends"),
N_("Region syncs"),
};
static const gchar *_snap_mode_strings[] = {
- N_("Normal"),
+ N_("No Grid"),
+ N_("Grid"),
N_("Magnetic"),
0
};
N_("Center"),
N_("Playhead"),
N_("Mouse"),
- N_("Marker"),
+ N_("Edit Point"),
0
};
+#ifdef USE_RUBBERBAND
+static const gchar *_rb_opt_strings[] = {
+ N_("Mushy"),
+ N_("Smooth"),
+ N_("Balanced multitimbral mixture"),
+ N_("Unpitched percussion with stable notes"),
+ N_("Crisp monophonic instrumental"),
+ N_("Unpitched solo percussion"),
+ 0
+};
+#endif
+
/* Soundfile drag-n-drop */
Gdk::Cursor* Editor::cross_hair_cursor = 0;
Gdk::Cursor* Editor::midi_erase_cursor = 0;
Gdk::Cursor* Editor::wait_cursor = 0;
Gdk::Cursor* Editor::timebar_cursor = 0;
+Gdk::Cursor* Editor::transparent_cursor = 0;
void
show_me_the_size (Requisition* r, const char* what)
minsec_label (_("Mins:Secs")),
bbt_label (_("Bars:Beats")),
smpte_label (_("Timecode")),
- frame_label (_("Frames")),
+ frame_label (_("Samples")),
tempo_label (_("Tempo")),
meter_label (_("Meter")),
mark_label (_("Location Markers")),
range_mark_label (_("Range Markers")),
transport_mark_label (_("Loop/Punch Ranges")),
+ cd_mark_label (_("CD Markers")),
- edit_packer (3, 3, false),
+ edit_packer (3, 3, true),
/* the values here don't matter: layout widgets
reset them as needed.
/* nudge */
- nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true)
+ nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true),
+ meters_running(false)
{
constructed = false;
clicked_routeview = 0;
clicked_crossfadeview = 0;
clicked_control_point = 0;
- latest_regionview = 0;
last_update_frame = 0;
drag_info.item = 0;
current_mixer_strip = 0;
snap_mode_strings = I18N (_snap_mode_strings);
zoom_focus_strings = I18N (_zoom_focus_strings);
edit_point_strings = I18N (_edit_point_strings);
-
- snap_type = SnapToFrame;
- set_snap_to (snap_type);
-
- snap_mode = SnapNormal;
- set_snap_mode (snap_mode);
-
- _edit_point = EditAtMouse;
- set_edit_point_preference (_edit_point);
-
+#ifdef USE_RUBBERBAND
+ rb_opt_strings = I18N (_rb_opt_strings);
+#endif
+
snap_threshold = 5.0;
bbt_beat_subdivision = 4;
canvas_width = 0;
verbose_cursor_on = true;
route_removal = false;
show_automatic_regions_in_region_list = true;
- region_list_sort_type = (Editing::RegionListSortType) 0;
+
+ region_list_sort_type = (Editing::RegionListSortType) 0;
have_pending_keyboard_selection = false;
_follow_playhead = true;
_xfade_visibility = true;
entered_marker = 0;
clear_entered_track = false;
_new_regionviews_show_envelope = false;
- current_timestretch = 0;
+ current_timefx = 0;
in_edit_group_row_change = false;
last_canvas_frame = 0;
playhead_cursor = 0;
_dragging_playhead = false;
_dragging_edit_point = false;
_dragging_hscrollbar = false;
+ select_new_marker = false;
+ zoomed_to_region = false;
scrubbing_direction = 0;
set_midi_edit_mode (MidiEditPencil, true);
set_mouse_mode (MouseObject, true);
+ last_visual_state.frames_per_unit = 0;
+
frames_per_unit = 2048; /* too early to use reset_zoom () */
reset_hscrollbar_stepping ();
initialize_canvas ();
edit_controls_vbox.set_spacing (0);
- horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
+ horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled), false);
vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling), true);
track_canvas.set_hadjustment (horizontal_adjustment);
mark_label.set_size_request (-1, (int)timebar_height);
mark_label.set_alignment (1.0, 0.5);
mark_label.set_padding (5,0);
+ cd_mark_label.set_name ("EditorTimeButton");
+ cd_mark_label.set_size_request (-1, (int)timebar_height);
+ cd_mark_label.set_alignment (1.0, 0.5);
+ cd_mark_label.set_padding (5,0);
range_mark_label.set_name ("EditorTimeButton");
range_mark_label.set_size_request (-1, (int)timebar_height);
range_mark_label.set_alignment (1.0, 0.5);
CellRendererToggle* route_list_visible_cell = dynamic_cast<CellRendererToggle*>(route_list_display.get_column_cell_renderer (0));
route_list_visible_cell->property_activatable() = true;
route_list_visible_cell->property_radio() = false;
-
+
route_display_model->signal_row_deleted().connect (mem_fun (*this, &Editor::route_list_delete));
route_display_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_list_change));
region_list_display.append_column (_("Regions"), region_list_columns.name);
region_list_display.set_headers_visible (false);
+ CellRendererText* region_name_cell = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
+ region_name_cell->property_editable() = true;
+ region_name_cell->signal_edited().connect (mem_fun (*this, &Editor::region_name_edit));
+
region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter));
TreeViewColumn* tv_col = region_list_display.get_column(0);
nlabel = manage (new Label (_("Edit Groups")));
nlabel->set_angle (-90);
the_notebook.append_page (*edit_group_display_packer, *nlabel);
- nlabel = manage (new Label (_("Chunks")));
- nlabel->set_angle (-90);
- the_notebook.append_page (named_selection_scroller, *nlabel);
+
+ if (!Profile->get_sae()) {
+ nlabel = manage (new Label (_("Chunks")));
+ nlabel->set_angle (-90);
+ the_notebook.append_page (named_selection_scroller, *nlabel);
+ }
the_notebook.set_show_tabs (true);
the_notebook.set_scrollable (true);
/* register actions now so that set_state() can find them and set toggles/checks etc */
register_actions ();
-
+
+ snap_type = SnapToBeat;
+ set_snap_to (snap_type);
+ snap_mode = SnapOff;
+ set_snap_mode (snap_mode);
+ _edit_point = EditAtMouse;
+ set_edit_point_preference (_edit_point);
+
XMLNode* node = ARDOUR_UI::instance()->editor_settings();
set_state (*node);
present ();
}
-void
-Editor::tie_vertical_scrolling ()
-{
- double y1 = vertical_adjustment.get_value();
-
- playhead_cursor->set_y_axis (y1);
- if (logo_item) {
- logo_item->property_y() = y1;
- }
-
- controls_layout.get_vadjustment()->set_value (y1);
-
-#ifdef GTKOSX
- /* the way idle updates and immediate window flushing work on GTK-Quartz
- requires that we force an immediate redraw right here. The controls
- layout will do the same all by itself, as does the canvas widget, but
- most of the time, the canvas itself hasn't updated itself because its
- idle handler hasn't run. consequently, the call that its layout makes
- to gdk_window_process_updates() finds nothing to do. here, we force
- the update to happen, then request a flush of the new window state.
- */
- track_canvas.update_now ();
- gdk_window_process_updates (GTK_LAYOUT(track_canvas.gobj())->bin_window, true);
-#endif
-}
-
void
Editor::instant_save ()
{
/* register for undo history */
session->register_with_memento_command_factory(_id, this);
+
+ start_updating ();
}
void
speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
}
+ {
+ RefPtr<Bitmap> bits;
+ char pix[4] = { 0, 0, 0, 0 };
+ bits = Bitmap::create (pix, 2, 2);
+ Gdk::Color c;
+ transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
+ }
+
+ {
+ RefPtr<Bitmap> bits;
+ char pix[4] = { 0, 0, 0, 0 };
+ bits = Bitmap::create (pix, 2, 2);
+ Gdk::Color c;
+ transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
+ }
+
grabber_cursor = new Gdk::Cursor (HAND2);
cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
trimmer_cursor = new Gdk::Cursor (SB_H_DOUBLE_ARROW);
fade_context_menu.popup (button, time);
}
-/* Pop up the general track context menu for when the user clicks pretty much anywhere in a track or bus */
void
-Editor::popup_track_context_menu (int button, int32_t time, nframes_t frame)
+Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, nframes_t frame)
{
- build_track_context_menu (frame)->popup (button, time);
+ using namespace Menu_Helpers;
+ Menu* (Editor::*build_menu_function)(nframes_t);
+ Menu *menu;
+
+ switch (item_type) {
+ case RegionItem:
+ case RegionViewName:
+ case RegionViewNameHighlight:
+ if (with_selection) {
+ build_menu_function = &Editor::build_track_selection_context_menu;
+ } else {
+ build_menu_function = &Editor::build_track_region_context_menu;
+ }
+ break;
+
+ case SelectionItem:
+ if (with_selection) {
+ build_menu_function = &Editor::build_track_selection_context_menu;
+ } else {
+ build_menu_function = &Editor::build_track_context_menu;
+ }
+ break;
+
+ case CrossfadeViewItem:
+ build_menu_function = &Editor::build_track_crossfade_context_menu;
+ break;
+
+ case StreamItem:
+ if (clicked_routeview->get_diskstream()) {
+ build_menu_function = &Editor::build_track_context_menu;
+ } else {
+ build_menu_function = &Editor::build_track_bus_context_menu;
+ }
+ break;
+
+ default:
+ /* probably shouldn't happen but if it does, we don't care */
+ return;
+ }
+
+ menu = (this->*build_menu_function)(frame);
+ menu->set_name ("ArdourContextMenu");
+
+ /* now handle specific situations */
+
+ switch (item_type) {
+ case RegionItem:
+ case RegionViewName:
+ case RegionViewNameHighlight:
+ if (!with_selection) {
+ if (region_edit_menu_split_item) {
+ if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
+ ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
+ } else {
+ ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
+ }
+ }
+ /*
+ if (region_edit_menu_split_multichannel_item) {
+ if (clicked_regionview && clicked_regionview->region().n_channels() > 1) {
+ // GTK2FIX find the action, change its sensitivity
+ // region_edit_menu_split_multichannel_item->set_sensitive (true);
+ } else {
+ // GTK2FIX see above
+ // region_edit_menu_split_multichannel_item->set_sensitive (false);
+ }
+ }*/
+ }
+ break;
+
+ case SelectionItem:
+ break;
+
+ case CrossfadeViewItem:
+ break;
+
+ case StreamItem:
+ break;
+
+ default:
+ /* probably shouldn't happen but if it does, we don't care */
+ return;
+ }
+
+ if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
+
+ /* Bounce to disk */
+
+ using namespace Menu_Helpers;
+ MenuList& edit_items = menu->items();
+
+ edit_items.push_back (SeparatorElem());
+
+ switch (clicked_routeview->audio_track()->freeze_state()) {
+ case AudioTrack::NoFreeze:
+ edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
+ break;
+
+ case AudioTrack::Frozen:
+ edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
+ break;
+
+ case AudioTrack::UnFrozen:
+ edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
+ break;
+ }
+
+ }
+
+ menu->popup (button, time);
+}
+
+Menu*
+Editor::build_track_context_menu (nframes_t ignored)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& edit_items = track_context_menu.items();
+ edit_items.clear();
+
+ add_dstream_context_items (edit_items);
+ return &track_context_menu;
}
Menu*
-Editor::build_track_context_menu (nframes_t frame)
+Editor::build_track_bus_context_menu (nframes_t ignored)
{
using namespace Menu_Helpers;
- Menu* menu = manage (new Menu);
- MenuList& edit_items = menu->items();
+ MenuList& edit_items = track_context_menu.items();
edit_items.clear();
- /* Build the general `track' context menu, adding what is appropriate given
- the current selection */
+ add_bus_context_items (edit_items);
+ return &track_context_menu;
+}
+
+Menu*
+Editor::build_track_region_context_menu (nframes_t frame)
+{
+ using namespace Menu_Helpers;
+ MenuList& edit_items = track_region_context_menu.items();
+ edit_items.clear();
+
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
+
+ if (rtv) {
+ boost::shared_ptr<Diskstream> ds;
+ boost::shared_ptr<Playlist> pl;
+
+ if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
+ Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed()));
+ for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+ add_region_context_items (rtv->view(), (*i), edit_items);
+ }
+ delete regions;
+ }
+ }
+
+ add_dstream_context_items (edit_items);
+
+ return &track_region_context_menu;
+}
+
+Menu*
+Editor::build_track_crossfade_context_menu (nframes_t frame)
+{
+ using namespace Menu_Helpers;
+ MenuList& edit_items = track_crossfade_context_menu.items();
+ edit_items.clear ();
- /* XXX: currently crossfades can't be selected, so we can't use the selection
- to decide which crossfades to mention in the menu. I believe this will
- change at some point. For now we have to use clicked_trackview to decide. */
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_axisview);
if (atv) {
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) != 0)) {
+ Playlist::RegionList* regions = pl->regions_at (frame);
AudioPlaylist::Crossfades xfades;
+
apl->crossfades_at (frame, xfades);
bool many = xfades.size() > 1;
for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
}
- }
- }
- if (!selection->time.empty()) {
- add_selection_context_items (edit_items);
- }
+ for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+ add_region_context_items (atv->audio_view(), (*i), edit_items);
+ }
- if (!selection->regions.empty()) {
- add_region_context_items (edit_items);
+ delete regions;
+ }
}
- if (!selection->tracks.empty()) {
- add_bus_or_audio_track_context_items (edit_items);
- }
-
- menu->set_name ("ArdourContextMenu");
+ add_dstream_context_items (edit_items);
- return menu;
+ return &track_crossfade_context_menu;
}
#ifdef FFT_ANALYSIS
}
#endif /* FFT_ANALYSIS */
+Menu*
+Editor::build_track_selection_context_menu (nframes_t ignored)
+{
+ using namespace Menu_Helpers;
+ MenuList& edit_items = track_selection_context_menu.items();
+ edit_items.clear ();
+
+ add_selection_context_items (edit_items);
+ // edit_items.push_back (SeparatorElem());
+ // add_dstream_context_items (edit_items);
+
+ return &track_selection_context_menu;
+}
/** Add context menu items relevant to crossfades.
* @param edit_items List to add the items to.
}
}
-/** Add context menu items relevant to regions.
- * @param edit_items List to add the items to.
- */
void
-Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
+Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> region, Menu_Helpers::MenuList& edit_items)
{
using namespace Menu_Helpers;
- sigc::connection fooc;
- Menu *region_menu = manage (new Menu);
- MenuList& items = region_menu->items();
+ Menu *region_menu = manage (new Menu);
+ MenuList& items = region_menu->items();
region_menu->set_name ("ArdourContextMenu");
- items.push_back (MenuElem (_("Edit..."), mem_fun(*this, &Editor::edit_region)));
- items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
- items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
+ boost::shared_ptr<AudioRegion> ar;
+ boost::shared_ptr<MidiRegion> mr;
- Menu* sync_point_menu = manage (new Menu);
- MenuList& sync_point_items = sync_point_menu->items();
- sync_point_menu->set_name("ArdourContextMenu");
-
- sync_point_items.push_back (MenuElem (_("Define"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
- sync_point_items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_region_sync)));
+ if (region) {
+ ar = boost::dynamic_pointer_cast<AudioRegion> (region);
+ mr = boost::dynamic_pointer_cast<MidiRegion> (region);
+ }
- items.push_back (MenuElem (_("Sync points"), *sync_point_menu));
+ /* when this particular menu pops up, make the relevant region
+ become selected.
+ */
- add_item_with_sensitivity (items, MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)), selection->regions.size() == 1);
-
- add_item_with_sensitivity (items, MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)), selection->regions.size() == 1);
+ region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
+
+ items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
+ items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
+ items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
+ items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
+ items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::play_selected_region)));
+ items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
#ifdef FFT_ANALYSIS
- items.push_back (MenuElem (_("Analyze region"), mem_fun(*this, &Editor::analyze_region_selection)));
+ if (ar)
+ items.push_back (MenuElem (_("Analyze region"), mem_fun(*this, &Editor::analyze_region_selection)));
#endif
items.push_back (SeparatorElem());
+ sigc::connection fooc;
+
items.push_back (CheckMenuElem (_("Lock")));
- region_lock_item = static_cast<CheckMenuItem*>(&items.back());
+ CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
-
-#if FIXUP_REGION_MENU
if (region->locked()) {
fooc.block (true);
region_lock_item->set_active();
fooc.block (false);
}
-#endif
-
- items.push_back (CheckMenuElem (_("Lock Position")));
- region_lock_position_item = static_cast<CheckMenuItem*>(&items.back());
- fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_position_lock));
-#if FIXUP_REGION_MENU
- if (region->locked()) {
- fooc.block (true);
- region_lock_position_item->set_active();
- fooc.block (false);
- }
-#endif
-
items.push_back (CheckMenuElem (_("Mute")));
- region_mute_item = static_cast<CheckMenuItem*>(&items.back());
+ CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
-#if FIXUP_REGION_MENU
if (region->muted()) {
fooc.block (true);
region_mute_item->set_active();
fooc.block (false);
}
-#endif
if (!Profile->get_sae()) {
items.push_back (CheckMenuElem (_("Opaque")));
- region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
+ CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
-#if FIXUP_REGION_MENU
if (region->opaque()) {
fooc.block (true);
region_opaque_item->set_active();
fooc.block (false);
}
-#endif
}
- /* We allow "Original position" if at least one region is not at its
- natural position
- */
- RegionSelection::iterator i = selection->regions.begin();
- while (i != selection->regions.end() && (*i)->region()->at_natural_position() == true) {
- ++i;
+ items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
+ if (region->at_natural_position()) {
+ items.back().set_sensitive (false);
}
-
- add_item_with_sensitivity (items, MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)), i != selection->regions.end());
items.push_back (SeparatorElem());
-
- /* Find out if we have a selected audio region */
- i = selection->regions.begin();
- while (i != selection->regions.end() && boost::dynamic_pointer_cast<AudioRegion>((*i)->region()) == 0) {
- ++i;
- }
- const bool have_selected_audio_region = (i != selection->regions.end());
-
- if (have_selected_audio_region) {
-
- Menu* envelopes_menu = manage (new Menu);
-
- envelopes_menu->set_name ("ArdourContextMenu");
-
-#if FIXUP_REGION_MENU
-
- XXX NEED TO RESOLVE ONE v. MANY REGION ISSUE
+
+ if (ar) {
- MenuList& envelopes_items = envelopes_menu->items();
-
RegionView* rv = sv->find_view (ar);
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
-
+
if (!Profile->get_sae()) {
- envelopes_items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
+ items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
- envelopes_items.push_back (CheckMenuElem (_("Envelope Visible")));
- region_envelope_visible_item = static_cast<CheckMenuItem*> (&items.back());
+ items.push_back (CheckMenuElem (_("Envelope Visible")));
+ CheckMenuItem* region_envelope_visible_item = static_cast<CheckMenuItem*> (&items.back());
fooc = region_envelope_visible_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_visibility));
if (arv->envelope_visible()) {
fooc.block (true);
fooc.block (false);
}
- envelopes_items.push_back (CheckMenuElem (_("Envelope Active")));
- region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
+ items.push_back (CheckMenuElem (_("Envelope Active")));
+ CheckMenuItem* region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active));
if (ar->envelope_active()) {
items.push_back (SeparatorElem());
}
-#endif
- items.push_back (MenuElem (_("Envelopes"), *envelopes_menu));
-
-#if FIXUP_REGION_MENU
if (ar->scale_amplitude() != 1.0f) {
- items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_regions)));
+ items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
} else {
- items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_regions)));
+ items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
}
-#endif
- }
-
- /* Find out if we have a selected MIDI region */
- i = selection->regions.begin();
- while (i != selection->regions.end() && boost::dynamic_pointer_cast<MidiRegion>((*i)->region()) == 0) {
- ++i;
- }
- const bool have_selected_midi_region = (i != selection->regions.end());
-
- if (have_selected_midi_region) {
- items.push_back (MenuElem (_("Quantize"), mem_fun(*this, &Editor::quantize_regions)));
+ } else if (mr) {
+ items.push_back (MenuElem (_("Quantize"), mem_fun(*this, &Editor::quantize_region)));
items.push_back (SeparatorElem());
-
}
+ items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
+ items.push_back (SeparatorElem());
+
/* range related stuff */
-
- add_item_with_sensitivity (items, MenuElem (_("Add range markers"), mem_fun (*this, &Editor::add_location_from_audio_region)), selection->regions.size() == 1);
-
- add_item_with_sensitivity (items, MenuElem (_("Set range selection"), mem_fun (*this, &Editor::set_selection_from_audio_region)), selection->regions.size() == 1);
-
+
+ items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_audio_region)));
+ items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_region)));
items.push_back (SeparatorElem());
/* Nudge region */
MenuList& nudge_items = nudge_menu->items();
nudge_menu->set_name ("ArdourContextMenu");
- nudge_items.push_back (MenuElem (_("Nudge forward"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
- nudge_items.push_back (MenuElem (_("Nudge backward"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
- nudge_items.push_back (MenuElem (_("Nudge forward by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
- nudge_items.push_back (MenuElem (_("Nudge backward by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
+ nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
+ nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
+ nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
+ nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
items.push_back (MenuElem (_("Nudge"), *nudge_menu));
+ items.push_back (SeparatorElem());
Menu *trim_menu = manage (new Menu);
MenuList& trim_items = trim_menu->items();
trim_items.push_back (MenuElem (_("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch)));
items.push_back (MenuElem (_("Trim"), *trim_menu));
+ items.push_back (SeparatorElem());
+
items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
+ region_edit_menu_split_item = &items.back();
+
items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
- items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
- items.push_back (MenuElem (_("Fill track"), (mem_fun(*this, &Editor::region_fill_track))));
+ region_edit_menu_split_multichannel_item = &items.back();
+
+ items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), false))));
+ items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
+ items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_selected_regions)));
+ items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
/* OK, stick the region submenu at the top of the list, and then add
the standard items.
*/
- string const menu_item_name = selection->regions.size() > 1 ? _("Regions") : _("Region");
+ /* we have to hack up the region name because "_" has a special
+ meaning for menu titles.
+ */
+
+ string::size_type pos = 0;
+ string menu_item_name = region->name();
+
+ while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
+ menu_item_name.replace (pos, 1, "__");
+ pos += 2;
+ }
+
edit_items.push_back (MenuElem (menu_item_name, *region_menu));
+ edit_items.push_back (SeparatorElem());
}
/** Add context menu items relevant to selection ranges.
items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection)));
}
-/** Add context menu items relevant to busses or audio tracks.
- * @param edit_items List to add the items to.
- */
+
void
-Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items)
+Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
{
using namespace Menu_Helpers;
- /* We add every possible action here, and de-sensitize things
- that aren't allowed. The sensitivity logic is a bit spread out;
- on the one hand I'm using things like can_cut_copy (), which is
- reasonably complicated and so perhaps better near the function that
- it expresses sensitivity for, and on the other hand checks
- in this function as well. You can't really have can_* for everything
- or the number of methods would get silly. */
-
- bool const one_selected_region = selection->regions.size() == 1;
-
- /* Count the number of selected audio tracks */
- int n_audio_tracks = 0;
- for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
- RouteTimeAxisView const * r = dynamic_cast<RouteTimeAxisView*>(*i);
- if (r && r->is_audio_track()) {
- n_audio_tracks++;
- }
- }
-
/* Playback */
Menu *play_menu = manage (new Menu);
play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
- add_item_with_sensitivity (play_items, MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)), one_selected_region);
-
- add_item_with_sensitivity (play_items, MenuElem (_("Loop region"), mem_fun(*this, &Editor::loop_selected_region)), one_selected_region);
+ play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
+ play_items.push_back (SeparatorElem());
+ play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
edit_items.push_back (MenuElem (_("Play"), *play_menu));
Menu *select_menu = manage (new Menu);
MenuList& select_items = select_menu->items();
select_menu->set_name ("ArdourContextMenu");
-
- string str = selection->tracks.size() == 1 ? _("Select all in track") : _("Select all in tracks");
-
- select_items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::select_all_in_selected_tracks), Selection::Set)));
-
- select_items.push_back (MenuElem (_("Select all"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
-
- str = selection->tracks.size() == 1 ? _("Invert selection in track") : _("Invert selection in tracks");
-
- select_items.push_back (MenuElem (str, mem_fun(*this, &Editor::invert_selection_in_selected_tracks)));
+ select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
+ select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
+ select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
select_items.push_back (SeparatorElem());
-
- if (n_audio_tracks) {
- select_items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
- select_items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
- }
-
+ select_items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
+ select_items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
+ select_items.push_back (SeparatorElem());
select_items.push_back (MenuElem (_("Select All After Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
select_items.push_back (MenuElem (_("Select All Before Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
select_items.push_back (MenuElem (_("Select All After Playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
Menu *cutnpaste_menu = manage (new Menu);
MenuList& cutnpaste_items = cutnpaste_menu->items();
cutnpaste_menu->set_name ("ArdourContextMenu");
-
+
cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
- add_item_with_sensitivity (cutnpaste_items, MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)), can_cut_copy ());
-
- add_item_with_sensitivity (cutnpaste_items, MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)), can_cut_copy ());
+ cutnpaste_items.push_back (SeparatorElem());
+
+ cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
+ cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
+
+ cutnpaste_items.push_back (SeparatorElem());
+
+ cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
+
+ edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
+
+ /* Adding new material */
- if (n_audio_tracks) {
- cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
- cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
-
- cutnpaste_items.push_back (SeparatorElem());
-
- cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
- cutnpaste_items.push_back (MenuElem (_("Align relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
- cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
- } else {
- cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
- }
+ edit_items.push_back (SeparatorElem());
+ edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
+ edit_items.push_back (MenuElem (_("Insert Existing Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
+ /* Nudge track */
+
+ Menu *nudge_menu = manage (new Menu());
+ MenuList& nudge_items = nudge_menu->items();
+ nudge_menu->set_name ("ArdourContextMenu");
+
edit_items.push_back (SeparatorElem());
- edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
+ nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
+ nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
- if (n_audio_tracks) {
+ edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
+}
- Menu *track_menu = manage (new Menu);
- MenuList& track_items = track_menu->items();
- track_menu->set_name ("ArdourContextMenu");
-
- /* Adding new material */
+void
+Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
+{
+ using namespace Menu_Helpers;
+
+ /* Playback */
+
+ Menu *play_menu = manage (new Menu);
+ MenuList& play_items = play_menu->items();
+ play_menu->set_name ("ArdourContextMenu");
- add_item_with_sensitivity (track_items, MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)), n_audio_tracks == 1);
- add_item_with_sensitivity (track_items, MenuElem (_("Insert Existing Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)), n_audio_tracks == 1);
-
- /* Nudge */
+ play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
+ play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
+ edit_items.push_back (MenuElem (_("Play"), *play_menu));
- Menu *nudge_menu = manage (new Menu());
- MenuList& nudge_items = nudge_menu->items();
- nudge_menu->set_name ("ArdourContextMenu");
+ /* Selection */
- str = selection->tracks.size() == 1 ? _("Nudge track after edit cursor forward") : _("Nudge tracks after edit cursor forward");
-
- nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), true, true))));
+ Menu *select_menu = manage (new Menu);
+ MenuList& select_items = select_menu->items();
+ select_menu->set_name ("ArdourContextMenu");
+
+ select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
+ select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
+ select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
+ select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
+ select_items.push_back (SeparatorElem());
+ select_items.push_back (MenuElem (_("Select all after edit point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
+ select_items.push_back (MenuElem (_("Select all before edit point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
+ select_items.push_back (MenuElem (_("Select all after playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
+ select_items.push_back (MenuElem (_("Select all before playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
- str = selection->tracks.size() == 1 ? _("Nudge track backward") : _("Nudge tracks backward");
-
- nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), false, false))));
+ edit_items.push_back (MenuElem (_("Select"), *select_menu));
- str = selection->tracks.size() == 1 ? _("Nudge track after edit cursor backward") : _("Nudge tracks after edit cursor backward");
-
- nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), true, false))));
-
- track_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
+ /* Cut-n-Paste */
- /* Freeze */
- track_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_routes)));
- track_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_routes)));
+ Menu *cutnpaste_menu = manage (new Menu);
+ MenuList& cutnpaste_items = cutnpaste_menu->items();
+ cutnpaste_menu->set_name ("ArdourContextMenu");
+
+ cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
+ cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
+ cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
- str = selection->tracks.size() == 1 ? _("Track") : _("Tracks");
- edit_items.push_back (MenuElem (str, *track_menu));
- }
+ Menu *nudge_menu = manage (new Menu());
+ MenuList& nudge_items = nudge_menu->items();
+ nudge_menu->set_name ("ArdourContextMenu");
+
+ edit_items.push_back (SeparatorElem());
+ nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
+ nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
+
+ edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
}
/* CURSOR SETTING AND MARKS AND STUFF */
void
Editor::set_snap_to (SnapType st)
{
+ unsigned int snap_ind = (unsigned int)st;
snap_type = st;
- string str = snap_type_strings[(int) st];
+
+ if ( snap_ind > snap_type_strings.size() - 1 ) {
+ snap_ind = 0;
+ snap_type = (SnapType)snap_ind;
+ }
+
+ string str = snap_type_strings[snap_ind];
if (str != snap_type_selector.get_active_text()) {
snap_type_selector.set_active_text (str);
void
Editor::set_edit_point_preference (EditPoint ep)
{
+ bool changed = _edit_point != ep;
+
_edit_point = ep;
string str = edit_point_strings[(int)ep];
edit_point_selector.set_active_text (str);
}
+ if (!changed) {
+ return;
+ }
+
+ if (Profile->get_sae()) {
+
+ switch (zoom_focus) {
+ case ZoomFocusMouse:
+ case ZoomFocusPlayhead:
+ case ZoomFocusEdit:
+ switch (_edit_point) {
+ case EditAtMouse:
+ set_zoom_focus (ZoomFocusMouse);
+ break;
+ case EditAtPlayhead:
+ set_zoom_focus (ZoomFocusPlayhead);
+ break;
+ case EditAtSelectedMarker:
+ set_zoom_focus (ZoomFocusEdit);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
instant_save ();
}
Location* before = 0;
Location* after = 0;
- if (!session) {
+ if (!session || snap_mode == SnapOff) {
return;
}
nframes64_t presnap = start;
switch (snap_type) {
- case SnapToFrame:
- break;
-
case SnapToCDFrame:
if (direction) {
start = (nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
start = session->tempo_map().round_to_beat_subdivision (start, 3);
break;
- case SnapToEditPoint:
- start = get_preferred_edit_position ();
- break;
-
case SnapToMark:
if (for_mark) {
return;
}
default:
+ /* handled at entry */
return;
}
{
string pixmap_path;
+#ifdef GTKOSX
+ const guint32 FUDGE = 38; // Combo's are stupid - they steal space from the entry for the button
+#else
const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button
-
+#endif
/* Mode Buttons (tool selection) */
mouse_move_button.add (*(manage (new Image (::get_icon("tool_object")))));
mouse_move_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_move_button);
- mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm")))));
- mouse_select_button.set_relief(Gtk::RELIEF_NONE);
- mouse_mode_buttons.push_back (&mouse_select_button);
- mouse_gain_button.add (*(manage (new Image (::get_icon("tool_gain")))));
- mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
- mouse_mode_buttons.push_back (&mouse_gain_button);
+
+ if (!Profile->get_sae()) {
+ mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm")))));
+ mouse_select_button.set_relief(Gtk::RELIEF_NONE);
+ mouse_mode_buttons.push_back (&mouse_select_button);
+
+ mouse_gain_button.add (*(manage (new Image (::get_icon("tool_gain")))));
+ mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
+ mouse_mode_buttons.push_back (&mouse_gain_button);
+ }
+
mouse_zoom_button.add (*(manage (new Image (::get_icon("tool_zoom")))));
mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
mouse_mode_buttons.push_back (&mouse_zoom_button);
mode_box->set_spacing(4);
mouse_mode_button_box.set_spacing(1);
mouse_mode_button_box.pack_start(mouse_move_button, true, true);
- mouse_mode_button_box.pack_start(mouse_select_button, true, true);
+ if (!Profile->get_sae()) {
+ mouse_mode_button_box.pack_start(mouse_select_button, true, true);
+ }
mouse_mode_button_box.pack_start(mouse_zoom_button, true, true);
- mouse_mode_button_box.pack_start(mouse_gain_button, true, true);
+ if (!Profile->get_sae()) {
+ mouse_mode_button_box.pack_start(mouse_gain_button, true, true);
+ }
mouse_mode_button_box.pack_start(mouse_timefx_button, true, true);
mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
mouse_mode_button_box.pack_start(mouse_note_button, true, true);
ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session"));
zoom_focus_selector.set_name ("ZoomFocusSelector");
- Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Playhead", FUDGE, 0);
+ Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, _("Playhead"), FUDGE, 0);
set_popdown_strings (zoom_focus_selector, zoom_focus_strings);
zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
ARDOUR_UI::instance()->tooltips().set_tip (zoom_focus_selector, _("Zoom focus"));
snap_box.set_border_width (2);
snap_type_selector.set_name ("SnapTypeSelector");
- Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10);
+ Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, _("SMPTE Seconds"), 2+FUDGE, 10);
set_popdown_strings (snap_type_selector, snap_type_strings);
snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Snap/Grid Units"));
snap_mode_selector.set_name ("SnapModeSelector");
- Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "Magnetic Snap", 2+FUDGE, 10);
+ Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, _("Magnetic Snap"), 2+FUDGE, 10);
set_popdown_strings (snap_mode_selector, snap_mode_strings);
snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
ARDOUR_UI::instance()->tooltips().set_tip (snap_mode_selector, _("Snap/Grid Mode"));
edit_point_selector.set_name ("SnapModeSelector");
- Gtkmm2ext::set_size_request_to_display_given_text (edit_point_selector, "Playhead", 2+FUDGE, 10);
+ Gtkmm2ext::set_size_request_to_display_given_text (edit_point_selector, _("Playhead"), 2+FUDGE, 10);
set_popdown_strings (edit_point_selector, edit_point_strings);
edit_point_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_point_selection_done));
ARDOUR_UI::instance()->tooltips().set_tip (edit_point_selector, _("Edit point"));
/* Pack everything in... */
- HBox* hbox = new HBox;
+ HBox* hbox = manage (new HBox);
hbox->set_spacing(10);
- tools_tearoff = new TearOff (*hbox);
+ tools_tearoff = manage (new TearOff (*hbox));
tools_tearoff->set_name ("MouseModeBase");
tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
/* Pack everything in... */
- midi_tools_tearoff = new TearOff (midi_tool_button_box);
+ midi_tools_tearoff = manage (new TearOff (midi_tool_button_box));
midi_tools_tearoff->set_name ("MouseModeBase");
/*
}
void
-Editor::duplicate_dialog (bool dup_region)
+Editor::duplicate_dialog (bool with_dialog)
{
- if (selection->regions.empty() && (selection->time.length() == 0)) {
- return;
- }
-
- ArdourDialog win ("duplicate dialog");
- Label label (_("Duplicate how many times?"));
- Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
- SpinButton spinner (adjustment);
-
- win.get_vbox()->set_spacing (12);
- win.get_vbox()->pack_start (label);
-
- /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
- place, visually. so do this by hand.
- */
+ float times = 1.0f;
- win.get_vbox()->pack_start (spinner);
- spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
+ if (mouse_mode == MouseRange) {
+ if (selection->time.length() == 0) {
+ return;
+ }
+ }
- label.show ();
- spinner.show ();
+
+ if (mouse_mode != MouseRange) {
- win.add_button (Stock::OK, RESPONSE_ACCEPT);
- win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
+ ensure_entered_region_selected (true);
- win.set_position (WIN_POS_MOUSE);
+ if (selection->regions.empty()) {
+ return;
+ }
+ }
- spinner.grab_focus ();
+ if (with_dialog) {
- switch (win.run ()) {
- case RESPONSE_ACCEPT:
- break;
- default:
- return;
+ ArdourDialog win ("duplicate dialog");
+ Label label (_("Duplicate how many times?"));
+ Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
+ SpinButton spinner (adjustment);
+
+ win.get_vbox()->set_spacing (12);
+ win.get_vbox()->pack_start (label);
+
+ /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
+ place, visually. so do this by hand.
+ */
+
+ win.get_vbox()->pack_start (spinner);
+ spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
+
+ label.show ();
+ spinner.show ();
+
+ win.add_button (Stock::OK, RESPONSE_ACCEPT);
+ win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
+
+ win.set_position (WIN_POS_MOUSE);
+
+ spinner.grab_focus ();
+
+ switch (win.run ()) {
+ case RESPONSE_ACCEPT:
+ break;
+ default:
+ return;
+ }
+
+ times = adjustment.get_value();
}
- float times = adjustment.get_value();
-
- if (!selection->regions.empty()) {
- duplicate_some_regions (selection->regions, times);
- } else {
+ if (mouse_mode == MouseRange) {
duplicate_selection (times);
+ } else {
+ duplicate_some_regions (selection->regions, times);
}
}
verbose_canvas_cursor->property_text() = txt.c_str();
}
+void
+Editor::set_edit_mode (EditMode m)
+{
+ Config->set_edit_mode (m);
+}
+
+void
+Editor::cycle_edit_mode ()
+{
+ switch (Config->get_edit_mode()) {
+ case Slide:
+ Config->set_edit_mode (Splice);
+ break;
+ case Splice:
+ Config->set_edit_mode (Slide);
+ break;
+ }
+}
+
void
Editor::edit_mode_selection_done ()
{
Editor::snap_type_selection_done ()
{
string choice = snap_type_selector.get_active_text();
- SnapType snaptype = SnapToFrame;
+ SnapType snaptype = SnapToBeat;
if (choice == _("Beats/3")) {
snaptype = SnapToAThirdBeat;
snaptype = SnapToBar;
} else if (choice == _("Marks")) {
snaptype = SnapToMark;
- } else if (choice == _("Edit Point")) {
- snaptype = SnapToEditPoint;
} else if (choice == _("Region starts")) {
snaptype = SnapToRegionStart;
} else if (choice == _("Region ends")) {
snaptype = SnapToSeconds;
} else if (choice == _("Minutes")) {
snaptype = SnapToMinutes;
- } else if (choice == _("None")) {
- snaptype = SnapToFrame;
}
RefPtr<RadioAction> ract = snap_type_action (snaptype);
string choice = snap_mode_selector.get_active_text();
SnapMode mode = SnapNormal;
- if (choice == _("Normal")) {
+ if (choice == _("No Grid")) {
+ mode = SnapOff;
+ } else if (choice == _("Grid")) {
mode = SnapNormal;
} else if (choice == _("Magnetic")) {
mode = SnapMagnetic;
}
}
+void
+Editor::cycle_edit_point (bool with_marker)
+{
+ switch (_edit_point) {
+ case EditAtMouse:
+ set_edit_point_preference (EditAtPlayhead);
+ break;
+ case EditAtPlayhead:
+ if (with_marker) {
+ set_edit_point_preference (EditAtSelectedMarker);
+ } else {
+ set_edit_point_preference (EditAtMouse);
+ }
+ break;
+ case EditAtSelectedMarker:
+ set_edit_point_preference (EditAtMouse);
+ break;
+ }
+}
+
void
Editor::edit_point_selection_done ()
{
EditPoint ep = EditAtSelectedMarker;
if (choice == _("Marker")) {
- _edit_point = EditAtSelectedMarker;
+ set_edit_point_preference (EditAtSelectedMarker);
} else if (choice == _("Playhead")) {
- _edit_point = EditAtPlayhead;
+ set_edit_point_preference (EditAtPlayhead);
} else {
- _edit_point = EditAtMouse;
+ set_edit_point_preference (EditAtMouse);
}
RefPtr<RadioAction> ract = edit_point_action (ep);
return key_press_focus_accelerator_handler (*this, ev);
}
+bool
+Editor::on_key_release_event (GdkEventKey* ev)
+{
+ return Gtk::Window::on_key_release_event (ev);
+ // return key_press_focus_accelerator_handler (*this, ev);
+}
+
void
Editor::reset_x_origin (nframes_t frame)
{
}
void
-Editor::set_frames_per_unit (double fpu)
+Editor::swap_visual_state ()
{
- nframes_t frames;
+ if (last_visual_state.frames_per_unit == 0) {
+ // never set
+ return;
+ }
+ /* note: the correct functionality here is very dependent on the ordering of
+ setting zoom focus, horizontal position and finally zoom. this is because
+ it is set_frames_per_unit() that overwrites last_visual_state.
+ */
+
+ set_zoom_focus (last_visual_state.zoom_focus);
+ reposition_and_zoom (last_visual_state.leftmost_frame, last_visual_state.frames_per_unit);
+ zoomed_to_region = false;
+}
+
+void
+Editor::set_frames_per_unit (double fpu)
+{
/* this is the core function that controls the zoom level of the canvas. it is called
whenever one or more calls are made to reset_zoom(). it executes in an idle handler.
*/
fpu = 2.0;
}
- // convert fpu to frame count
-
- frames = (nframes_t) floor (fpu * canvas_width);
/* don't allow zooms that fit more than the maximum number
of frames into an 800 pixel wide space.
if (fpu == frames_per_unit) {
return;
}
+
+ last_visual_state.frames_per_unit = frames_per_unit;
+ last_visual_state.leftmost_frame = leftmost_frame;
+ last_visual_state.zoom_focus = zoom_focus;
frames_per_unit = fpu;
+ post_zoom ();
+}
+
+void
+Editor::post_zoom ()
+{
+ // convert fpu to frame count
+
+ nframes_t frames = (nframes_t) floor (frames_per_unit * canvas_width);
+
+ if (frames_per_unit != zoom_range_clock.current_duration()) {
+ zoom_range_clock.set (frames);
+ }
if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
if (!selection->tracks.empty()) {
reset_hscrollbar_stepping ();
reset_scrolling_region ();
-
+
if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
instant_save ();
{
pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::TimeOrigin);
pending_visual_change.time_origin = where;
-
+
if (pending_visual_change.idle_handler_id < 0) {
pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
}
VisualChange::Type p = pending_visual_change.pending;
pending_visual_change.pending = (VisualChange::Type) 0;
-
+
if (p & VisualChange::ZoomLevel) {
set_frames_per_unit (pending_visual_change.frames_per_unit);
update_tempo_based_rulers ();
}
if (p & VisualChange::TimeOrigin) {
- if (pending_visual_change.time_origin != leftmost_frame) {
+
+ nframes_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
+
+ if (time_origin != pending_visual_change.time_origin) {
horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit);
- /* the signal handler will do the rest */
} else {
update_fixed_rulers();
redisplay_tempo (true);
};
void
-Editor::sort_track_selection ()
+Editor::sort_track_selection (TrackSelection* sel)
{
EditorOrderTimeAxisSorter cmp;
- selection->tracks.sort (cmp);
+
+ if (sel) {
+ sel->sort (cmp);
+ } else {
+ selection->tracks.sort (cmp);
+ }
}
nframes64_t
-Editor::get_preferred_edit_position()
+Editor::get_preferred_edit_position (bool ignore_playhead)
{
bool ignored;
nframes64_t where = 0;
+ EditPoint ep = _edit_point;
- switch (_edit_point) {
+ if (entered_marker) {
+ return entered_marker->position();
+ }
+
+ if (ignore_playhead && ep == EditAtPlayhead) {
+ ep = EditAtSelectedMarker;
+ }
+
+ switch (ep) {
case EditAtPlayhead:
where = session->audible_frame();
break;
case EditAtSelectedMarker:
if (!selection->markers.empty()) {
- bool whocares;
- Location* loc = find_location_from_marker (selection->markers.front(), whocares);
+ bool is_start;
+ Location* loc = find_location_from_marker (selection->markers.front(), is_start);
if (loc) {
- where = loc->start();
+ if (is_start) {
+ where = loc->start();
+ } else {
+ where = loc->end();
+ }
break;
}
}
return rs;
}
+
+RegionSelection
+Editor::get_regions_after (nframes64_t where, const TrackSelection& ts) const
+{
+ RegionSelection rs;
+ const TrackSelection* tracks;
+
+ if (ts.empty()) {
+ tracks = &track_views;
+ } else {
+ tracks = &ts;
+ }
+
+ for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
+
+ if (atv) {
+ boost::shared_ptr<Diskstream> ds;
+ boost::shared_ptr<Playlist> pl;
+
+ if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
+
+ Playlist::RegionList* regions = pl->regions_touched ((nframes_t) floor ( (double)where * ds->speed()), max_frames);
+
+ for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+
+ RegionView* rv = atv->audio_view()->find_view (*i);
+
+ if (rv) {
+ rs.push_back (rv);
+ }
+ }
+
+ delete regions;
+ }
+ }
+ }
+
+ return rs;
+}
+
RegionSelection&
Editor::get_regions_for_action ()
{
tmp_regions = get_regions_at (where, selection->tracks);
return tmp_regions;
}
+
+void
+Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
+{
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ RouteTimeAxisView* tatv;
+
+ if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
+
+ boost::shared_ptr<Playlist> pl;
+ vector<boost::shared_ptr<Region> > results;
+ RegionView* marv;
+ boost::shared_ptr<Diskstream> ds;
+
+ if ((ds = tatv->get_diskstream()) == 0) {
+ /* bus */
+ continue;
+ }
+
+ if ((pl = (ds->playlist())) != 0) {
+ pl->get_region_list_equivalent_regions (region, results);
+ }
+
+ for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
+ if ((marv = tatv->view()->find_view (*ir)) != 0) {
+ regions.push_back (marv);
+ }
+ }
+
+ }
+ }
+}