Re-work main right-click context menu to operate on the selection, and remove some confusion about what region(s) will be affected by menu selections.

git-svn-id: svn://localhost/ardour2/trunk@1831 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2007-05-10 11:53:35 +00:00
parent 4342f2aeb0
commit aa3bb18b17
13 changed files with 484 additions and 675 deletions

View file

@ -292,9 +292,7 @@ Editor::Editor ()
new_transport_marker_menu = 0; new_transport_marker_menu = 0;
editor_mixer_strip_width = Wide; editor_mixer_strip_width = Wide;
show_editor_mixer_when_tracks_arrive = false; show_editor_mixer_when_tracks_arrive = false;
region_edit_menu_split_item = 0;
temp_location = 0; temp_location = 0;
region_edit_menu_split_multichannel_item = 0;
leftmost_frame = 0; leftmost_frame = 0;
ignore_mouse_mode_toggle = false; ignore_mouse_mode_toggle = false;
current_stepping_trackview = 0; current_stepping_trackview = 0;
@ -1217,6 +1215,7 @@ Editor::build_cursors ()
timebar_cursor = new Gdk::Cursor(LEFT_PTR); timebar_cursor = new Gdk::Cursor(LEFT_PTR);
} }
/** Pop up a context menu for when the user clicks on a fade in or fade out */
void void
Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type) Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
{ {
@ -1278,179 +1277,28 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
fade_context_menu.popup (button, time); 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 void
Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, nframes_t frame) Editor::popup_track_context_menu (int button, int32_t time, nframes_t frame)
{ {
using namespace Menu_Helpers; build_track_context_menu (frame)->popup (button, time);
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->is_track()) {
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 (edit_cursor->current_frame)) {
ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, true);
} else {
ActionManager::set_sensitive (ActionManager::edit_cursor_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 (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* Menu*
Editor::build_track_context_menu (nframes_t ignored) Editor::build_track_context_menu (nframes_t frame)
{ {
using namespace Menu_Helpers; using namespace Menu_Helpers;
MenuList& edit_items = track_context_menu.items(); Menu* menu = manage (new Menu);
MenuList& edit_items = menu->items();
edit_items.clear(); edit_items.clear();
add_dstream_context_items (edit_items); /* Build the general `track' context menu, adding what is appropriate given
return &track_context_menu; the current selection */
}
Menu*
Editor::build_track_bus_context_menu (nframes_t ignored)
{
using namespace Menu_Helpers;
MenuList& edit_items = track_context_menu.items();
edit_items.clear();
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();
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_axisview);
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_at ((nframes_t) floor ( (double)frame * ds->speed()));
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
add_region_context_items (atv->audio_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); AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_axisview);
if (atv) { if (atv) {
@ -1460,9 +1308,7 @@ Editor::build_track_crossfade_context_menu (nframes_t frame)
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) != 0)) { 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; AudioPlaylist::Crossfades xfades;
apl->crossfades_at (frame, xfades); apl->crossfades_at (frame, xfades);
bool many = xfades.size() > 1; bool many = xfades.size() > 1;
@ -1470,18 +1316,24 @@ Editor::build_track_crossfade_context_menu (nframes_t frame)
for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) { for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many); add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
} }
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
add_region_context_items (atv->audio_view(), (*i), edit_items);
}
delete regions;
} }
}
if (!selection->time.empty()) {
add_selection_context_items (edit_items);
} }
add_dstream_context_items (edit_items); if (!selection->regions.empty()) {
add_region_context_items (edit_items);
}
return &track_crossfade_context_menu; if (!selection->tracks.empty()) {
add_bus_or_audio_track_context_items (edit_items);
}
menu->set_name ("ArdourContextMenu");
return menu;
} }
#ifdef FFT_ANALYSIS #ifdef FFT_ANALYSIS
@ -1523,20 +1375,9 @@ Editor::analyze_range_selection()
#endif /* FFT_ANALYSIS */ #endif /* FFT_ANALYSIS */
/** Add context menu items relevant to crossfades.
Menu* * @param edit_items List to add the items to.
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);
add_dstream_context_items (edit_items);
return &track_selection_context_menu;
}
void void
Editor::add_crossfade_context_items (AudioStreamView* view, boost::shared_ptr<Crossfade> xfade, Menu_Helpers::MenuList& edit_items, bool many) Editor::add_crossfade_context_items (AudioStreamView* view, boost::shared_ptr<Crossfade> xfade, Menu_Helpers::MenuList& edit_items, bool many)
{ {
@ -1594,36 +1435,48 @@ Editor::xfade_edit_right_region ()
} }
} }
/** Add an element to a menu, settings its sensitivity.
* @param m Menu to add to.
* @param e Element to add.
* @param s true to make sensitive, false to make insensitive
*/
void void
Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region> region, Menu_Helpers::MenuList& edit_items) Editor::add_item_with_sensitivity (Menu_Helpers::MenuList& m, Menu_Helpers::MenuElem e, bool s) const
{
m.push_back (e);
if (!s) {
m.back().set_sensitive (false);
}
}
/** 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)
{ {
using namespace Menu_Helpers; using namespace Menu_Helpers;
Menu *region_menu = manage (new Menu); Menu *region_menu = manage (new Menu);
MenuList& items = region_menu->items(); MenuList& items = region_menu->items();
region_menu->set_name ("ArdourContextMenu"); region_menu->set_name ("ArdourContextMenu");
boost::shared_ptr<AudioRegion> ar; items.push_back (MenuElem (_("Edit..."), mem_fun(*this, &Editor::edit_region)));
if (region) {
ar = boost::dynamic_pointer_cast<AudioRegion> (region);
}
/* when this particular menu pops up, make the relevant region
become selected.
*/
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 (_("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 (_("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 (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_cursor)));
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::audition_selected_region))); Menu* sync_point_menu = manage (new Menu);
items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region))); 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_cursor)));
sync_point_items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_region_sync)));
items.push_back (MenuElem (_("Sync points"), *sync_point_menu));
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);
items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection))); items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
#ifdef FFT_ANALYSIS #ifdef FFT_ANALYSIS
@ -1632,83 +1485,59 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region>
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
sigc::connection fooc; items.push_back (MenuElem (_("Lock"), bind (mem_fun (*this, &Editor::set_region_lock), true)));
items.push_back (MenuElem (_("Unlock"), bind (mem_fun (*this, &Editor::set_region_lock), false)));
items.push_back (MenuElem (_("Mute"), bind (mem_fun (*this, &Editor::set_region_mute), true)));
items.push_back (MenuElem (_("Unmute"), bind (mem_fun (*this, &Editor::set_region_mute), false)));
items.push_back (MenuElem (_("Opaque"), bind (mem_fun (*this, &Editor::set_region_opaque), true)));
items.push_back (MenuElem (_("Transparent"), bind (mem_fun (*this, &Editor::set_region_opaque), false)));
items.push_back (CheckMenuElem (_("Lock"))); /* We allow "Original position" if at least one region is not at its
region_lock_item = static_cast<CheckMenuItem*>(&items.back()); natural position */
fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock)); RegionSelection::iterator i = selection->regions.begin();
if (region->locked()) { while (i != selection->regions.end() && (*i)->region()->at_natural_position() == true) {
fooc.block (true); ++i;
region_lock_item->set_active();
fooc.block (false);
}
items.push_back (CheckMenuElem (_("Mute")));
region_mute_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
if (region->muted()) {
fooc.block (true);
region_mute_item->set_active();
fooc.block (false);
} }
items.push_back (CheckMenuElem (_("Opaque"))); add_item_with_sensitivity (items, MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)), i != selection->regions.end());
region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
if (region->opaque()) {
fooc.block (true);
region_opaque_item->set_active();
fooc.block (false);
}
items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
if (region->at_natural_position()) {
items.back().set_sensitive (false);
}
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
if (ar) {
RegionView* rv = sv->find_view (ar);
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
items.push_back (CheckMenuElem (_("Envelope Visible")));
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);
region_envelope_visible_item->set_active (true);
fooc.block (false);
}
items.push_back (CheckMenuElem (_("Envelope Active")));
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()) {
fooc.block (true);
region_envelope_active_item->set_active (true);
fooc.block (false);
}
items.push_back (SeparatorElem()); /* Find out if we have a selected audio region */
i = selection->regions.begin();
if (ar->scale_amplitude() != 1.0f) { while (i != selection->regions.end() && boost::dynamic_pointer_cast<AudioRegion>((*i)->region()) == 0) {
items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region))); ++i;
} else {
items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
}
} }
items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region))); bool const have_selected_audio_region = (i != selection->regions.end());
if (have_selected_audio_region) {
Menu* envelopes_menu = manage (new Menu);
MenuList& envelopes_items = envelopes_menu->items();
envelopes_menu->set_name ("ArdourContextMenu");
envelopes_items.push_back (MenuElem (_("Reset"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
envelopes_items.push_back (MenuElem (_("Visible"), bind (mem_fun (*this, &Editor::set_gain_envelope_visibility), true)));
envelopes_items.push_back (MenuElem (_("Invisible"), bind (mem_fun (*this, &Editor::set_gain_envelope_visibility), false)));
envelopes_items.push_back (MenuElem (_("Active"), bind (mem_fun (*this, &Editor::set_gain_envelope_active), true)));
envelopes_items.push_back (MenuElem (_("Inactive"), bind (mem_fun (*this, &Editor::set_gain_envelope_active), false)));
items.push_back (MenuElem (_("Envelopes"), *envelopes_menu));
items.push_back (MenuElem (_("Denormalize"), mem_fun (*this, &Editor::denormalize_regions)));
items.push_back (MenuElem (_("Normalize"), mem_fun (*this, &Editor::normalize_regions)));
}
items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_regions)));
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
/* range related stuff */ /* range related stuff */
items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_audio_region))); add_item_with_sensitivity (items, MenuElem (_("Add range markers"), mem_fun (*this, &Editor::add_location_from_audio_region)), selection->regions.size() == 1);
items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_audio_region)));
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 (SeparatorElem()); items.push_back (SeparatorElem());
/* Nudge region */ /* Nudge region */
@ -1717,13 +1546,12 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region>
MenuList& nudge_items = nudge_menu->items(); MenuList& nudge_items = nudge_menu->items();
nudge_menu->set_name ("ArdourContextMenu"); nudge_menu->set_name ("ArdourContextMenu");
nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false)))); nudge_items.push_back (MenuElem (_("Nudge forward"), (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 backward"), (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 forward 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)))); nudge_items.push_back (MenuElem (_("Nudge backward by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
items.push_back (MenuElem (_("Nudge"), *nudge_menu)); items.push_back (MenuElem (_("Nudge"), *nudge_menu));
items.push_back (SeparatorElem());
Menu *trim_menu = manage (new Menu); Menu *trim_menu = manage (new Menu);
MenuList& trim_items = trim_menu->items(); MenuList& trim_items = trim_menu->items();
@ -1733,39 +1561,24 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region>
trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor))); trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
items.push_back (MenuElem (_("Trim"), *trim_menu)); items.push_back (MenuElem (_("Trim"), *trim_menu));
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region)))); 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 (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
region_edit_menu_split_multichannel_item = &items.back();
items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true)))); 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)))); items.push_back (MenuElem (_("Fill track"), (mem_fun(*this, &Editor::region_fill_track))));
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region))); items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_selected_regions)));
/* OK, stick the region submenu at the top of the list, and then add /* OK, stick the region submenu at the top of the list, and then add
the standard items. the standard items.
*/ */
/* we have to hack up the region name because "_" has a special string const menu_item_name = selection->regions.size() > 1 ? _("Regions") : _("Region");
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 (MenuElem (menu_item_name, *region_menu));
edit_items.push_back (SeparatorElem());
} }
/** Add context menu items relevant to selection ranges.
* @param edit_items List to add the items to.
*/
void void
Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items) Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
{ {
@ -1789,7 +1602,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection))); items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection))); items.push_back (MenuElem (_("Add range markers"), mem_fun (*this, &Editor::add_location_from_selection)));
items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop))); items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch))); items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
items.push_back (SeparatorElem()); items.push_back (SeparatorElem());
@ -1805,11 +1618,33 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
edit_items.push_back (SeparatorElem()); edit_items.push_back (SeparatorElem());
} }
/** Add context menu items relevant to busses or audio tracks.
* @param edit_items List to add the items to.
*/
void void
Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) Editor::add_bus_or_audio_track_context_items (Menu_Helpers::MenuList& edit_items)
{ {
using namespace Menu_Helpers; 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 */ /* Playback */
Menu *play_menu = manage (new Menu); Menu *play_menu = manage (new Menu);
@ -1818,9 +1653,9 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
play_items.push_back (MenuElem (_("Play from edit cursor"), mem_fun(*this, &Editor::play_from_edit_cursor))); play_items.push_back (MenuElem (_("Play from edit cursor"), mem_fun(*this, &Editor::play_from_edit_cursor)));
play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start))); play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region))); add_item_with_sensitivity (play_items, MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)), one_selected_region);
play_items.push_back (SeparatorElem());
play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region))); add_item_with_sensitivity (play_items, MenuElem (_("Loop region"), mem_fun(*this, &Editor::loop_selected_region)), one_selected_region);
edit_items.push_back (MenuElem (_("Play"), *play_menu)); edit_items.push_back (MenuElem (_("Play"), *play_menu));
@ -1829,21 +1664,33 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
Menu *select_menu = manage (new Menu); Menu *select_menu = manage (new Menu);
MenuList& select_items = select_menu->items(); MenuList& select_items = select_menu->items();
select_menu->set_name ("ArdourContextMenu"); 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 (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
select_items.push_back (SeparatorElem()); select_items.push_back (SeparatorElem());
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))); if (n_audio_tracks) {
select_items.push_back (SeparatorElem()); 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 (_("Select all after edit cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, true))); select_items.push_back (MenuElem (_("Select all after edit cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, true)));
select_items.push_back (MenuElem (_("Select all before edit cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, false))); select_items.push_back (MenuElem (_("Select all before edit cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, 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 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))); select_items.push_back (MenuElem (_("Select all before playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
select_items.push_back (MenuElem (_("Select all between cursors"), bind (mem_fun(*this, &Editor::select_all_selectables_between_cursors), playhead_cursor, edit_cursor)));
select_items.push_back (SeparatorElem()); if (n_audio_tracks) {
select_items.push_back (MenuElem (_("Select all between cursors"), bind (mem_fun(*this, &Editor::select_all_selectables_between_cursors), playhead_cursor, edit_cursor)));
}
edit_items.push_back (MenuElem (_("Select"), *select_menu)); edit_items.push_back (MenuElem (_("Select"), *select_menu));
@ -1852,98 +1699,68 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
Menu *cutnpaste_menu = manage (new Menu); Menu *cutnpaste_menu = manage (new Menu);
MenuList& cutnpaste_items = cutnpaste_menu->items(); MenuList& cutnpaste_items = cutnpaste_menu->items();
cutnpaste_menu->set_name ("ArdourContextMenu"); cutnpaste_menu->set_name ("ArdourContextMenu");
add_item_with_sensitivity (cutnpaste_items, MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)), can_cut_copy ());
cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut))); add_item_with_sensitivity (cutnpaste_items, MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)), can_cut_copy ());
cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f))); if (n_audio_tracks) {
cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste))); 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 (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 (_("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)));
} else {
cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f))); cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
}
edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu)); edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
if (n_audio_tracks) {
/* Adding new material */ Menu *track_menu = manage (new Menu);
MenuList& track_items = track_menu->items();
track_menu->set_name ("ArdourContextMenu");
/* Adding new material */
edit_items.push_back (SeparatorElem()); 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);
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))); 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 */
/* Nudge track */ Menu *nudge_menu = manage (new Menu());
MenuList& nudge_items = nudge_menu->items();
nudge_menu->set_name ("ArdourContextMenu");
Menu *nudge_menu = manage (new Menu()); str = selection->tracks.size() == 1 ? _("Nudge track forward") : _("Nude tracks forward");
MenuList& nudge_items = nudge_menu->items(); nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), false, true))));
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 cursor 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 cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu)); 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))));
void str = selection->tracks.size() == 1 ? _("Nudge track backward") : _("Nudge tracks backward");
Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
{ nudge_items.push_back (MenuElem (str, (bind (mem_fun(*this, &Editor::nudge_selected_tracks), false, false))));
using namespace Menu_Helpers;
/* Playback */ 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));
Menu *play_menu = manage (new Menu); /* Freeze */
MenuList& play_items = play_menu->items(); track_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_routes)));
play_menu->set_name ("ArdourContextMenu"); track_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_routes)));
play_items.push_back (MenuElem (_("Play from edit cursor"), mem_fun(*this, &Editor::play_from_edit_cursor)));
play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
edit_items.push_back (MenuElem (_("Play"), *play_menu));
/* Selection */ str = selection->tracks.size() == 1 ? _("Track") : _("Tracks");
edit_items.push_back (MenuElem (str, *track_menu));
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 cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, true)));
select_items.push_back (MenuElem (_("Select all before edit cursor"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), edit_cursor, 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)));
edit_items.push_back (MenuElem (_("Select"), *select_menu));
/* Cut-n-Paste */
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)));
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 cursor 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 cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
} }
/* CURSOR SETTING AND MARKS AND STUFF */ /* CURSOR SETTING AND MARKS AND STUFF */
@ -3460,15 +3277,9 @@ Editor::popup_snapshot_context_menu (int button, int32_t time, Glib::ustring sna
const bool modification_allowed = (session->snap_name() != snapshot_name && session->name() != snapshot_name); const bool modification_allowed = (session->snap_name() != snapshot_name && session->name() != snapshot_name);
items.push_back (MenuElem (_("Remove"), bind (mem_fun (*this, &Editor::remove_snapshot), snapshot_name))); add_item_with_sensitivity (items, MenuElem (_("Remove"), bind (mem_fun (*this, &Editor::remove_snapshot), snapshot_name)), modification_allowed);
if (!modification_allowed) {
items.back().set_sensitive (false);
}
items.push_back (MenuElem (_("Rename"), bind (mem_fun (*this, &Editor::rename_snapshot), snapshot_name))); add_item_with_sensitivity (items, MenuElem (_("Rename"), bind (mem_fun (*this, &Editor::rename_snapshot), snapshot_name)), modification_allowed);
if (!modification_allowed) {
items.back().set_sensitive (false);
}
snapshot_context_menu.popup (button, time); snapshot_context_menu.popup (button, time);
} }

View file

@ -140,7 +140,7 @@ class Editor : public PublicEditor
void set_mouse_mode (Editing::MouseMode, bool force=true); void set_mouse_mode (Editing::MouseMode, bool force=true);
void step_mouse_mode (bool next); void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () { return mouse_mode; } Editing::MouseMode current_mouse_mode () const { return mouse_mode; }
void add_imageframe_time_axis(const std::string & track_name, void*) ; void add_imageframe_time_axis(const std::string & track_name, void*) ;
void add_imageframe_marker_time_axis(const std::string & track_name, TimeAxisView* marked_track, void*) ; void add_imageframe_marker_time_axis(const std::string & track_name, TimeAxisView* marked_track, void*) ;
@ -216,9 +216,9 @@ class Editor : public PublicEditor
bool extend_selection_to_track (TimeAxisView&); bool extend_selection_to_track (TimeAxisView&);
void play_selection (); void play_selection ();
void select_all_in_track (Selection::Operation op); void select_all_in_selected_tracks (Selection::Operation op);
void select_all (Selection::Operation op); void select_all (Selection::Operation op);
void invert_selection_in_track (); void invert_selection_in_selected_tracks ();
void invert_selection (); void invert_selection ();
/* tempo */ /* tempo */
@ -412,7 +412,12 @@ class Editor : public PublicEditor
TimeAxisView* clicked_axisview; TimeAxisView* clicked_axisview;
RouteTimeAxisView* clicked_routeview; RouteTimeAxisView* clicked_routeview;
/** The last RegionView that was clicked on, or 0 if the last click was not
* on a RegionView. This is set up by the canvas event handlers in
* editor_canvas_events.cc
*/
RegionView* clicked_regionview; RegionView* clicked_regionview;
RegionView* latest_regionview; RegionView* latest_regionview;
uint32_t clicked_selection; uint32_t clicked_selection;
CrossfadeView* clicked_crossfadeview; CrossfadeView* clicked_crossfadeview;
@ -446,32 +451,17 @@ class Editor : public PublicEditor
bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false); bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false);
void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set); void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, boost::weak_ptr<ARDOUR::Region>);
void collect_new_region_view (RegionView *); void collect_new_region_view (RegionView *);
Gtk::Menu track_context_menu; void popup_track_context_menu (int, int, nframes_t);
Gtk::Menu track_region_context_menu;
Gtk::Menu track_selection_context_menu;
Gtk::Menu track_crossfade_context_menu;
Gtk::MenuItem* region_edit_menu_split_item;
Gtk::MenuItem* region_edit_menu_split_multichannel_item;
Gtk::Menu * track_region_edit_playlist_menu;
Gtk::Menu * track_edit_playlist_submenu;
Gtk::Menu * track_selection_edit_playlist_submenu;
void popup_track_context_menu (int, int, ItemType, bool, nframes_t);
Gtk::Menu* build_track_context_menu (nframes_t); Gtk::Menu* build_track_context_menu (nframes_t);
Gtk::Menu* build_track_bus_context_menu (nframes_t); void add_bus_or_audio_track_context_items (Gtk::Menu_Helpers::MenuList&);
Gtk::Menu* build_track_region_context_menu (nframes_t frame); void add_region_context_items (Gtk::Menu_Helpers::MenuList&);
Gtk::Menu* build_track_crossfade_context_menu (nframes_t);
Gtk::Menu* build_track_selection_context_menu (nframes_t);
void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&);
void add_bus_context_items (Gtk::Menu_Helpers::MenuList&);
void add_region_context_items (AudioStreamView*, boost::shared_ptr<ARDOUR::Region>, Gtk::Menu_Helpers::MenuList&);
void add_crossfade_context_items (AudioStreamView*, boost::shared_ptr<ARDOUR::Crossfade>, Gtk::Menu_Helpers::MenuList&, bool many); void add_crossfade_context_items (AudioStreamView*, boost::shared_ptr<ARDOUR::Crossfade>, Gtk::Menu_Helpers::MenuList&, bool many);
void add_selection_context_items (Gtk::Menu_Helpers::MenuList&); void add_selection_context_items (Gtk::Menu_Helpers::MenuList&);
void add_item_with_sensitivity (Gtk::Menu_Helpers::MenuList&, Gtk::Menu_Helpers::MenuElem, bool) const;
void handle_new_route (ARDOUR::Session::RouteList&); void handle_new_route (ARDOUR::Session::RouteList&);
void remove_route (TimeAxisView *); void remove_route (TimeAxisView *);
bool route_removal; bool route_removal;
@ -862,6 +852,7 @@ class Editor : public PublicEditor
list<boost::shared_ptr<ARDOUR::Region> > tmp_region_list; list<boost::shared_ptr<ARDOUR::Region> > tmp_region_list;
void cut_copy (Editing::CutCopyOp); void cut_copy (Editing::CutCopyOp);
bool can_cut_copy () const;
void cut_copy_points (Editing::CutCopyOp); void cut_copy_points (Editing::CutCopyOp);
void cut_copy_regions (Editing::CutCopyOp); void cut_copy_regions (Editing::CutCopyOp);
void cut_copy_ranges (Editing::CutCopyOp); void cut_copy_ranges (Editing::CutCopyOp);
@ -872,9 +863,9 @@ class Editor : public PublicEditor
/* EDITING OPERATIONS */ /* EDITING OPERATIONS */
void reset_point_selection (); void reset_point_selection ();
void toggle_region_mute (); void set_region_mute (bool);
void toggle_region_lock (); void set_region_lock (bool);
void toggle_region_opaque (); void set_region_opaque (bool);
void raise_region (); void raise_region ();
void raise_region_to_top (); void raise_region_to_top ();
void lower_region (); void lower_region ();
@ -890,8 +881,8 @@ class Editor : public PublicEditor
void align_selection_relative (ARDOUR::RegionPoint point, nframes_t position); void align_selection_relative (ARDOUR::RegionPoint point, nframes_t position);
void align_region (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position); void align_region (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
void align_region_internal (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position); void align_region_internal (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, nframes_t position);
void remove_selected_regions ();
void remove_clicked_region (); void remove_clicked_region ();
void destroy_clicked_region ();
void edit_region (); void edit_region ();
void duplicate_some_regions (RegionSelection&, float times); void duplicate_some_regions (RegionSelection&, float times);
void duplicate_selection (float times); void duplicate_selection (float times);
@ -901,9 +892,9 @@ class Editor : public PublicEditor
void audition_playlist_region_standalone (boost::shared_ptr<ARDOUR::Region>); void audition_playlist_region_standalone (boost::shared_ptr<ARDOUR::Region>);
void audition_playlist_region_via_route (boost::shared_ptr<ARDOUR::Region>, ARDOUR::Route&); void audition_playlist_region_via_route (boost::shared_ptr<ARDOUR::Region>, ARDOUR::Route&);
void split_multichannel_region(); void split_multichannel_region();
void reverse_region (); void reverse_regions ();
void normalize_region (); void normalize_regions ();
void denormalize_region (); void denormalize_regions ();
void audition_region_from_region_list (); void audition_region_from_region_list ();
void hide_region_from_region_list (); void hide_region_from_region_list ();
@ -1670,8 +1661,8 @@ class Editor : public PublicEditor
static void* _freeze_thread (void*); static void* _freeze_thread (void*);
void* freeze_thread (); void* freeze_thread ();
void freeze_route (); void freeze_routes ();
void unfreeze_route (); void unfreeze_routes ();
/* edit-group solo + mute */ /* edit-group solo + mute */
@ -1734,7 +1725,7 @@ class Editor : public PublicEditor
/* nudging tracks */ /* nudging tracks */
void nudge_track (bool use_edit_cursor, bool forwards); void nudge_selected_tracks (bool use_edit_cursor, bool forwards);
/* xfades */ /* xfades */
@ -1827,8 +1818,8 @@ class Editor : public PublicEditor
bool _new_regionviews_show_envelope; bool _new_regionviews_show_envelope;
void toggle_gain_envelope_visibility (); void set_gain_envelope_visibility (bool);
void toggle_gain_envelope_active (); void set_gain_envelope_active (bool);
void reset_region_gain_envelopes (); void reset_region_gain_envelopes ();
Gtk::CheckMenuItem* region_envelope_visible_item; Gtk::CheckMenuItem* region_envelope_visible_item;

View file

@ -248,9 +248,9 @@ Editor::register_actions ()
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "insert-region", _("Insert Region"), mem_fun(*this, &Editor::keyboard_insert_region_list_selection)); act = ActionManager::register_action (editor_actions, "insert-region", _("Insert Region"), mem_fun(*this, &Editor::keyboard_insert_region_list_selection));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "reverse-region", _("Reverse Region"), mem_fun(*this, &Editor::reverse_region)); act = ActionManager::register_action (editor_actions, "reverse-region", _("Reverse Regions"), mem_fun(*this, &Editor::reverse_regions));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "normalize-region", _("Normalize Region"), mem_fun(*this, &Editor::normalize_region)); act = ActionManager::register_action (editor_actions, "normalize-region", _("Normalize Regions"), mem_fun(*this, &Editor::normalize_regions));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "crop", _("crop"), mem_fun(*this, &Editor::crop_region_to_selection)); act = ActionManager::register_action (editor_actions, "crop", _("crop"), mem_fun(*this, &Editor::crop_region_to_selection));
ActionManager::session_sensitive_actions.push_back (act); ActionManager::session_sensitive_actions.push_back (act);

View file

@ -87,19 +87,20 @@ Editor::export_range (nframes_t start, nframes_t end)
} }
} }
/** Export the first selected region */
void void
Editor::export_region () Editor::export_region ()
{ {
if (clicked_regionview == 0) { if (selection->regions.empty()) {
return; return;
} }
ExportDialog* dialog = new ExportRegionDialog (*this, clicked_regionview->region()); boost::shared_ptr<Region> r = selection->regions.front()->region();
ExportDialog* dialog = new ExportRegionDialog (*this, r);
dialog->connect_to_session (session); dialog->connect_to_session (session);
dialog->set_range ( dialog->set_range (r->first_frame(), r->last_frame());
clicked_regionview->region()->first_frame(),
clicked_regionview->region()->last_frame());
dialog->start_export(); dialog->start_export();
} }

View file

@ -330,22 +330,8 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
switch (item_type) { switch (item_type) {
case RegionItem: case RegionItem:
if (mouse_mode != MouseRange) {
commit = set_selected_regionview_from_click (press, op, true);
} else if (event->type == GDK_BUTTON_PRESS) {
commit = set_selected_track_from_click (press, op, false);
}
break;
case RegionViewNameHighlight: case RegionViewNameHighlight:
case RegionViewName: case RegionViewName:
if (mouse_mode != MouseRange) {
commit = set_selected_regionview_from_click (press, op, true);
} else if (event->type == GDK_BUTTON_PRESS) {
commit = set_selected_track_from_click (press, op, false);
}
break;
case FadeInHandleItem: case FadeInHandleItem:
case FadeInItem: case FadeInItem:
case FadeOutHandleItem: case FadeOutHandleItem:
@ -356,7 +342,11 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
commit = set_selected_track_from_click (press, op, false); commit = set_selected_track_from_click (press, op, false);
} }
break; break;
case CrossfadeViewItem:
commit = set_selected_track_from_click (press, op, false);
break;
case GainAutomationControlPointItem: case GainAutomationControlPointItem:
case PanAutomationControlPointItem: case PanAutomationControlPointItem:
case RedirectAutomationControlPointItem: case RedirectAutomationControlPointItem:
@ -825,21 +815,13 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break; break;
case StreamItem: case StreamItem:
popup_track_context_menu (1, event->button.time, item_type, false, where);
break;
case RegionItem: case RegionItem:
case RegionViewNameHighlight: case RegionViewNameHighlight:
case RegionViewName: case RegionViewName:
popup_track_context_menu (1, event->button.time, item_type, false, where);
break;
case SelectionItem: case SelectionItem:
popup_track_context_menu (1, event->button.time, item_type, true, where);
break;
case AutomationTrackItem: case AutomationTrackItem:
popup_track_context_menu (1, event->button.time, item_type, false, where); case CrossfadeViewItem:
popup_track_context_menu (1, event->button.time, where);
break; break;
case MarkerBarItem: case MarkerBarItem:
@ -862,10 +844,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
tm_marker_context_menu (&event->button, item); tm_marker_context_menu (&event->button, item);
break; break;
case CrossfadeViewItem:
popup_track_context_menu (1, event->button.time, item_type, false, where);
break;
/* <CMT Additions> */ /* <CMT Additions> */
case ImageFrameItem: case ImageFrameItem:
popup_imageframe_edit_menu(1, event->button.time, item, true) ; popup_imageframe_edit_menu(1, event->button.time, item, true) ;

View file

@ -143,6 +143,8 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions)
_new_regionviews_show_envelope = false; _new_regionviews_show_envelope = false;
} }
/** Remove `clicked_regionview' */
void void
Editor::remove_clicked_region () Editor::remove_clicked_region ()
{ {
@ -160,47 +162,29 @@ Editor::remove_clicked_region ()
commit_reversible_command (); commit_reversible_command ();
} }
/** Remove the selected regions */
void void
Editor::destroy_clicked_region () Editor::remove_selected_regions ()
{ {
uint32_t selected = selection->regions.size(); if (selection->regions.empty()) {
if (!session || !selected) {
return; return;
} }
vector<string> choices; /* XXX: should be called remove regions if we're removing more than one */
string prompt; begin_reversible_command (_("remove region"));
prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\ for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
It cannot be undone\n\ boost::shared_ptr<Region> region = (*i)->region ();
Do you really want to destroy %1 ?"), boost::shared_ptr<Playlist> playlist = region->playlist ();
(selected > 1 ?
_("these regions") : _("this region")));
choices.push_back (_("No, do nothing."));
if (selected > 1) {
choices.push_back (_("Yes, destroy them."));
} else {
choices.push_back (_("Yes, destroy it."));
}
Gtkmm2ext::Choice prompter (prompt, choices);
if (prompter.run() == 0) { /* first choice */ XMLNode &before = playlist->get_state();
return; playlist->remove_region (region);
XMLNode &after = playlist->get_state();
session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
} }
if (selected) { commit_reversible_command ();
list<boost::shared_ptr<Region> > r;
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
r.push_back ((*i)->region());
}
session->destroy_regions (r);
}
} }
boost::shared_ptr<Region> boost::shared_ptr<Region>
@ -1534,13 +1518,11 @@ Editor::insert_region_list_selection (float times)
RouteTimeAxisView *tv = 0; RouteTimeAxisView *tv = 0;
boost::shared_ptr<Playlist> playlist; boost::shared_ptr<Playlist> playlist;
if (clicked_routeview != 0) { if (selection->tracks.empty()) {
tv = clicked_routeview; return;
} else if (!selection->tracks.empty()) { }
if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
return; if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
}
} else {
return; return;
} }
@ -1748,14 +1730,11 @@ Editor::lower_region_to_bottom ()
selection->foreach_region (&Region::lower_to_bottom); selection->foreach_region (&Region::lower_to_bottom);
} }
/** Show the region editor for the selected regions */
void void
Editor::edit_region () Editor::edit_region ()
{ {
if (clicked_regionview == 0) { selection->foreach_regionview (&RegionView::show_region_editor);
return;
}
clicked_regionview->show_region_editor ();
} }
void void
@ -1832,6 +1811,7 @@ Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Ro
/* XXX how to unset the solo state ? */ /* XXX how to unset the solo state ? */
} }
/** Start an audition of the first selected region */
void void
Editor::audition_selected_region () Editor::audition_selected_region ()
{ {
@ -2270,39 +2250,50 @@ Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t
commit_reversible_command (); commit_reversible_command ();
} }
/** Set the sync position of the selection using the position of the edit cursor */
void void
Editor::set_region_sync_from_edit_cursor () Editor::set_region_sync_from_edit_cursor ()
{ {
if (clicked_regionview == 0) { /* Check that at the edit cursor is in at least one of the selected regions */
return; RegionSelection::const_iterator i = selection->regions.begin();
while (i != selection->regions.end() && !(*i)->region()->covers (edit_cursor->current_frame)) {
++i;
} }
if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) { /* Give the user a hint if not */
if (i == selection->regions.end()) {
error << _("Place the edit cursor at the desired sync point") << endmsg; error << _("Place the edit cursor at the desired sync point") << endmsg;
return; return;
} }
boost::shared_ptr<Region> region (clicked_regionview->region());
begin_reversible_command (_("set sync from edit cursor")); begin_reversible_command (_("set sync from edit cursor"));
XMLNode &before = region->playlist()->get_state();
region->set_sync_position (edit_cursor->current_frame); for (RegionSelection::iterator j = selection->regions.begin(); j != selection->regions.end(); ++j) {
XMLNode &after = region->playlist()->get_state(); boost::shared_ptr<Region> r = (*j)->region();
session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after)); XMLNode &before = r->playlist()->get_state();
r->set_sync_position (edit_cursor->current_frame);
XMLNode &after = r->playlist()->get_state();
session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
}
commit_reversible_command (); commit_reversible_command ();
} }
/** Remove the sync positions of the selection */
void void
Editor::remove_region_sync () Editor::remove_region_sync ()
{ {
if (clicked_regionview) { begin_reversible_command (_("remove sync"));
boost::shared_ptr<Region> region (clicked_regionview->region());
begin_reversible_command (_("remove sync")); for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
XMLNode &before = region->playlist()->get_state(); boost::shared_ptr<Region> r = (*i)->region();
region->clear_sync_position (); XMLNode &before = r->playlist()->get_state();
XMLNode &after = region->playlist()->get_state(); r->clear_sync_position ();
session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after)); XMLNode &after = r->playlist()->get_state();
commit_reversible_command (); session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
} }
commit_reversible_command ();
} }
void void
@ -2447,66 +2438,80 @@ Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint poi
session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after)); session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
} }
/** Trim the end of the selected regions to the position of the edit cursor */
void void
Editor::trim_region_to_edit_cursor () Editor::trim_region_to_edit_cursor ()
{ {
if (clicked_regionview == 0) { if (selection->regions.empty()) {
return; return;
} }
boost::shared_ptr<Region> region (clicked_regionview->region());
float speed = 1.0f;
RouteTimeAxisView *rtav;
if ( clicked_axisview != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(clicked_axisview)) != 0 ) {
if (rtav->get_diskstream() != 0) {
speed = rtav->get_diskstream()->speed();
}
}
begin_reversible_command (_("trim to edit")); begin_reversible_command (_("trim to edit"));
XMLNode &before = region->playlist()->get_state();
region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this); for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
XMLNode &after = region->playlist()->get_state(); boost::shared_ptr<Region> region ((*i)->region());
session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
float speed = 1.0f;
RouteTimeAxisView *rtav;
/* XXX I don't think clicked_axisview should be used here! */
if ( clicked_axisview != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(clicked_axisview)) != 0 ) {
if (rtav->get_diskstream() != 0) {
speed = rtav->get_diskstream()->speed();
}
}
XMLNode &before = region->playlist()->get_state();
region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
XMLNode &after = region->playlist()->get_state();
session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
}
commit_reversible_command (); commit_reversible_command ();
} }
/** Trim the start of the selected regions to the position of the edit cursor */
void void
Editor::trim_region_from_edit_cursor () Editor::trim_region_from_edit_cursor ()
{ {
if (clicked_regionview == 0) { if (selection->regions.empty()) {
return; return;
} }
boost::shared_ptr<Region> region (clicked_regionview->region());
float speed = 1.0f;
RouteTimeAxisView *rtav;
if ( clicked_axisview != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(clicked_axisview)) != 0 ) {
if (rtav->get_diskstream() != 0) {
speed = rtav->get_diskstream()->speed();
}
}
begin_reversible_command (_("trim to edit")); begin_reversible_command (_("trim to edit"));
XMLNode &before = region->playlist()->get_state();
region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this); for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
XMLNode &after = region->playlist()->get_state(); boost::shared_ptr<Region> region ((*i)->region());
session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
float speed = 1.0f;
RouteTimeAxisView *rtav;
/* XXX: not sure about clicked_axisview here */
if ( clicked_axisview != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(clicked_axisview)) != 0 ) {
if (rtav->get_diskstream() != 0) {
speed = rtav->get_diskstream()->speed();
}
}
XMLNode &before = region->playlist()->get_state();
region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
XMLNode &after = region->playlist()->get_state();
session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
}
commit_reversible_command (); commit_reversible_command ();
} }
/** Unfreeze selected routes */
void void
Editor::unfreeze_route () Editor::unfreeze_routes ()
{ {
if (clicked_routeview == 0 || !clicked_routeview->is_track()) { for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
return; AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*i);
if (atv && atv->is_audio_track()) {
atv->audio_track()->unfreeze ();
}
} }
clicked_routeview->track()->unfreeze ();
} }
void* void*
@ -2519,7 +2524,15 @@ Editor::_freeze_thread (void* arg)
void* void*
Editor::freeze_thread () Editor::freeze_thread ()
{ {
clicked_routeview->audio_track()->freeze (*current_interthread_info); for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*i);
if (atv && atv->is_audio_track()) {
atv->audio_track()->freeze (*current_interthread_info);
}
}
current_interthread_info->done = true;
return 0; return 0;
} }
@ -2530,13 +2543,10 @@ Editor::freeze_progress_timeout (void *arg)
return !(current_interthread_info->done || current_interthread_info->cancel); return !(current_interthread_info->done || current_interthread_info->cancel);
} }
/** Freeze selected routes */
void void
Editor::freeze_route () Editor::freeze_routes ()
{ {
if (clicked_routeview == 0 || !clicked_routeview->is_track()) {
return;
}
InterThreadInfo itt; InterThreadInfo itt;
if (interthread_progress_window == 0) { if (interthread_progress_window == 0) {
@ -2624,18 +2634,50 @@ Editor::bounce_range_selection ()
commit_reversible_command (); commit_reversible_command ();
} }
/** Cut selected regions, automation points or a time range */
void void
Editor::cut () Editor::cut ()
{ {
cut_copy (Cut); cut_copy (Cut);
} }
/** Copy selected regions, automation points or a time range */
void void
Editor::copy () Editor::copy ()
{ {
cut_copy (Copy); cut_copy (Copy);
} }
/** @return true if a Cut, Copy or Clear is possible */
bool
Editor::can_cut_copy () const
{
switch (current_mouse_mode()) {
case MouseObject:
if (!selection->regions.empty() || !selection->points.empty()) {
return true;
}
break;
case MouseRange:
if (!selection->time.empty()) {
return true;
}
break;
default:
break;
}
return false;
}
/** Cut, copy or clear selected regions, automation points or a time range.
* @param op Operation (Cut, Copy or Clear)
*/
void void
Editor::cut_copy (CutCopyOp op) Editor::cut_copy (CutCopyOp op)
{ {
@ -2703,6 +2745,9 @@ Editor::cut_copy (CutCopyOp op)
} }
} }
/** Cut, copy or clear selected automation points.
* @param op Operation (Cut, Copy or Clear)
*/
void void
Editor::cut_copy_points (CutCopyOp op) Editor::cut_copy_points (CutCopyOp op)
{ {
@ -2734,6 +2779,10 @@ struct PlaylistMapping {
PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {} PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
}; };
/** Cut, copy or clear selected regions.
* @param op Operation (Cut, Copy or Clear)
*/
void void
Editor::cut_copy_regions (CutCopyOp op) Editor::cut_copy_regions (CutCopyOp op)
{ {
@ -3109,7 +3158,7 @@ Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
} }
void void
Editor::nudge_track (bool use_edit_cursor, bool forwards) Editor::nudge_selected_tracks (bool use_edit_cursor, bool forwards)
{ {
boost::shared_ptr<Playlist> playlist; boost::shared_ptr<Playlist> playlist;
nframes_t distance; nframes_t distance;
@ -3176,7 +3225,7 @@ Editor::remove_last_capture ()
} }
void void
Editor::normalize_region () Editor::normalize_regions ()
{ {
if (!session) { if (!session) {
return; return;
@ -3206,7 +3255,7 @@ Editor::normalize_region ()
void void
Editor::denormalize_region () Editor::denormalize_regions ()
{ {
if (!session) { if (!session) {
return; return;
@ -3232,7 +3281,7 @@ Editor::denormalize_region ()
void void
Editor::reverse_region () Editor::reverse_regions ()
{ {
if (!session) { if (!session) {
return; return;
@ -3317,10 +3366,6 @@ Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
void void
Editor::external_edit_region () Editor::external_edit_region ()
{ {
if (!clicked_regionview) {
return;
}
/* more to come */ /* more to come */
} }
@ -3368,71 +3413,75 @@ Editor::reset_region_gain_envelopes ()
session->commit_reversible_command (); session->commit_reversible_command ();
} }
/** Set whether or not gain envelopes are visible for the selected regions.
* @param yn true to make visible, false to make invisible.
*/
void void
Editor::toggle_gain_envelope_visibility () Editor::set_gain_envelope_visibility (bool yn)
{ {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) { if (arv) {
bool x = region_envelope_visible_item->get_active(); if (arv->envelope_visible() != yn) {
if (x != arv->envelope_visible()) { arv->set_envelope_visible (yn);
arv->set_envelope_visible (x); }
}
}
}
/** Set whether or not gain envelopes are active for the selected regions.
* @param yn true to make active, false to make inactive.
*/
void
Editor::set_gain_envelope_active (bool yn)
{
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
if (arv->audio_region()->envelope_active() != yn) {
arv->audio_region()->set_envelope_active (yn);
}
}
}
}
/** Set the locked state of all selected regions to a particular value.
* @param yn true to make locked, false to make unlocked.
*/
void
Editor::set_region_lock (bool yn)
{
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
if (arv->audio_region()->locked() != yn) {
arv->audio_region()->set_locked (yn);
} }
} }
} }
} }
void void
Editor::toggle_gain_envelope_active () Editor::set_region_mute (bool yn)
{ {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) { if (arv) {
bool x = region_envelope_active_item->get_active(); if (arv->audio_region()->muted() != yn) {
if (x != arv->audio_region()->envelope_active()) { arv->audio_region()->set_muted (yn);
arv->audio_region()->set_envelope_active (x);
} }
} }
} }
} }
void void
Editor::toggle_region_lock () Editor::set_region_opaque (bool yn)
{ {
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i); AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) { if (arv) {
bool x = region_lock_item->get_active(); if (arv->audio_region()->opaque() != yn) {
if (x != arv->audio_region()->locked()) { arv->audio_region()->set_opaque (yn);
arv->audio_region()->set_locked (x);
}
}
}
}
void
Editor::toggle_region_mute ()
{
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
bool x = region_mute_item->get_active();
if (x != arv->audio_region()->muted()) {
arv->audio_region()->set_muted (x);
}
}
}
}
void
Editor::toggle_region_opaque ()
{
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
bool x = region_opaque_item->get_active();
if (x != arv->audio_region()->opaque()) {
arv->audio_region()->set_opaque (x);
} }
} }
} }

View file

@ -582,43 +582,6 @@ Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> regi
commit_reversible_command () ; commit_reversible_command () ;
} }
bool
Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, boost::weak_ptr<Region> weak_r)
{
RegionView* rv;
boost::shared_ptr<Region> r (weak_r.lock());
if (!r) {
return true;
}
boost::shared_ptr<AudioRegion> ar;
if ((ar = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
return true;
}
if ((rv = sv->find_view (ar)) == 0) {
return true;
}
/* don't reset the selection if its something other than
a single other region.
*/
if (selection->regions.size() > 1) {
return true;
}
begin_reversible_command (_("set selected regions"));
selection->set (rv);
commit_reversible_command () ;
return true;
}
void void
Editor::track_selection_changed () Editor::track_selection_changed ()
{ {
@ -685,16 +648,17 @@ Editor::point_selection_changed ()
} }
} }
/** Select everything in the selected tracks
* @param Selection operation to apply.
*/
void void
Editor::select_all_in_track (Selection::Operation op) Editor::select_all_in_selected_tracks (Selection::Operation op)
{ {
list<Selectable *> touched; list<Selectable *> touched;
if (!clicked_routeview) { for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
return; (*i)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
} }
clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
switch (op) { switch (op) {
case Selection::Toggle: case Selection::Toggle:
@ -741,16 +705,16 @@ Editor::select_all (Selection::Operation op)
commit_reversible_command (); commit_reversible_command ();
} }
/** Invert the selection in the selected tracks */
void void
Editor::invert_selection_in_track () Editor::invert_selection_in_selected_tracks ()
{ {
list<Selectable *> touched; list<Selectable *> touched;
if (!clicked_routeview) { for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
return; (*i)->get_inverted_selectables (*selection, touched);
} }
clicked_routeview->get_inverted_selectables (*selection, touched);
selection->set (touched); selection->set (touched);
} }

View file

@ -91,7 +91,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
virtual void redo (uint32_t n = 1) = 0; virtual void redo (uint32_t n = 1) = 0;
virtual void set_mouse_mode (Editing::MouseMode, bool force = false) = 0; virtual void set_mouse_mode (Editing::MouseMode, bool force = false) = 0;
virtual void step_mouse_mode (bool next) = 0; virtual void step_mouse_mode (bool next) = 0;
virtual Editing::MouseMode current_mouse_mode () = 0; virtual Editing::MouseMode current_mouse_mode () const = 0;
virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0; virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0;
virtual void add_imageframe_marker_time_axis(const std::string & track_name, TimeAxisView* marked_track, void*) = 0; virtual void add_imageframe_marker_time_axis(const std::string & track_name, TimeAxisView* marked_track, void*) = 0;
virtual void connect_to_image_compositor() = 0; virtual void connect_to_image_compositor() = 0;

View file

@ -1048,6 +1048,9 @@ RouteTimeAxisView::set_selected_regionviews (RegionSelection& regions)
} }
} }
/** Add the selectable things that we have to a list.
* @param results List to add things to.
*/
void void
RouteTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results) RouteTimeAxisView::get_selectables (nframes_t start, nframes_t end, double top, double bot, list<Selectable*>& results)
{ {

View file

@ -45,6 +45,10 @@ namespace ARDOUR {
class AutomationList; class AutomationList;
} }
/// Lists of selected things
/** The Selection class holds lists of selected items (tracks, regions, etc. etc.). */
class Selection : public sigc::trackable class Selection : public sigc::trackable
{ {
public: public:
@ -149,6 +153,7 @@ class Selection : public sigc::trackable
void clear_points (); void clear_points ();
void foreach_region (void (ARDOUR::Region::*method)(void)); void foreach_region (void (ARDOUR::Region::*method)(void));
void foreach_regionview (void (RegionView::*method)(void));
template<class A> void foreach_region (void (ARDOUR::Region::*method)(A), A arg); template<class A> void foreach_region (void (ARDOUR::Region::*method)(A), A arg);
private: private:

View file

@ -38,6 +38,13 @@ Selection::foreach_region (void (ARDOUR::Region::*method)(void)) {
} }
} }
inline void
Selection::foreach_regionview (void (RegionView::*method)(void)) {
for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
((*i)->*(method))();
}
}
template<class A> inline void template<class A> inline void
Selection::foreach_region (void (ARDOUR::Region::*method)(A), A arg) { Selection::foreach_region (void (ARDOUR::Region::*method)(A), A arg) {
for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {

View file

@ -741,6 +741,7 @@ AudioTrack::bounce (InterThreadInfo& itt)
{ {
vector<boost::shared_ptr<Source> > srcs; vector<boost::shared_ptr<Source> > srcs;
_session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt); _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
itt.done = true;
} }
@ -749,6 +750,7 @@ AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt)
{ {
vector<boost::shared_ptr<Source> > srcs; vector<boost::shared_ptr<Source> > srcs;
_session.write_one_audio_track (*this, start, end, false, srcs, itt); _session.write_one_audio_track (*this, start, end, false, srcs, itt);
itt.done = true;
} }
void void

View file

@ -4164,8 +4164,6 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
g_atomic_int_set (&processing_prohibited, 0); g_atomic_int_set (&processing_prohibited, 0);
itt.done = true;
return ret; return ret;
} }