#include <sigc++/bind.h>
+#include <pbd/convert.h>
#include <pbd/error.h>
#include <gtkmm/image.h>
#include <gtkmm2ext/utils.h>
#include <ardour/audio_track.h>
-#include <ardour/diskstream.h>
+#include <ardour/audio_diskstream.h>
#include <ardour/plugin_manager.h>
#include <ardour/location.h>
#include <ardour/audioplaylist.h>
#include <ardour/tempo.h>
#include <ardour/utils.h>
+#include <control_protocol/control_protocol.h>
+
#include "ardour_ui.h"
#include "editor.h"
#include "grouped_buttons.h"
using namespace std;
using namespace sigc;
using namespace ARDOUR;
+using namespace PBD;
using namespace Gtk;
using namespace Glib;
using namespace Gtkmm2ext;
using namespace Editing;
+using PBD::internationalize;
+using PBD::atoi;
+
const double Editor::timebar_height = 15.0;
#include "editor_xpms"
cerr << "size of " << what << " = " << r->width << " x " << r->height << endl;
}
+void
+check_adjustment (Gtk::Adjustment* adj)
+{
+ cerr << "CHANGE adj = "
+ << adj->get_lower () << ' '
+ << adj->get_upper () << ' '
+ << adj->get_value () << ' '
+ << adj->get_step_increment () << ' '
+ << adj->get_page_increment () << ' '
+ << adj->get_page_size () << ' '
+ << endl;
+
+}
+
Editor::Editor (AudioEngine& eng)
: engine (eng),
reset them as needed.
*/
- vertical_adjustment (0.0, 0.0, 400.0, 10),
- horizontal_adjustment (0.0, 0.0, 1200.0, 20),
+ vertical_adjustment (0.0, 0.0, 10.0, 400.0),
+ horizontal_adjustment (0.0, 0.0, 20.0, 1200.0),
/* tool bar related */
route_list_menu = 0;
region_list_menu = 0;
marker_menu = 0;
+ range_marker_menu = 0;
marker_menu_item = 0;
tm_marker_menu = 0;
transport_marker_menu = 0;
_new_regionviews_show_envelope = false;
current_timestretch = 0;
in_edit_group_row_change = false;
-
+ last_canvas_frame = 0;
edit_cursor = 0;
playhead_cursor = 0;
+ button_release_can_deselect = true;
location_marker_color = color_map[cLocationMarker];
location_range_color = color_map[cLocationRange];
set_mouse_mode (MouseObject, true);
frames_per_unit = 2048; /* too early to use set_frames_per_unit */
+ reset_hscrollbar_stepping ();
+
zoom_focus = ZoomFocusLeft;
zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
edit_group_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
edit_group_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
edit_group_display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
+ edit_group_display.get_column (0)->set_expand (true);
+ edit_group_display.get_column (1)->set_expand (false);
+ edit_group_display.get_column (2)->set_expand (false);
edit_group_display.set_headers_visible (true);
/* name is directly editable */
region_list_display.set_model (region_list_model);
region_list_display.append_column (_("Regions"), region_list_columns.name);
region_list_display.set_headers_visible (false);
+ region_list_display.set_hover_expand (true);
region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter));
signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
+ /* allow external control surfaces/protocols to do various things */
+
+ ControlProtocol::ZoomToSession.connect (mem_fun (*this, &Editor::temporal_zoom_session));
+ ControlProtocol::ZoomIn.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), false));
+ ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true));
+ ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll));
constructed = true;
instant_save ();
}
}
}
-gint
-Editor::left_track_canvas (GdkEventCrossing *ev)
-{
- set_entered_track (0);
- set_entered_regionview (0);
- return FALSE;
-}
-
-
void
Editor::show_window ()
{
which will do the same updates.
*/
- if (session && !no_zoom_repos_update) {
- horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
- }
-
if (!no_zoom_repos_update) {
horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
update_fixed_rulers ();
ZoomChanged (); /* EMIT_SIGNAL */
+ reset_hscrollbar_stepping ();
+ reset_scrolling_region ();
+
if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
{
if (frame != leftmost_frame) {
leftmost_frame = frame;
- double pixel = frame_to_pixel (frame);
- if (pixel >= horizontal_adjustment.get_upper()) {
- horizontal_adjustment.set_upper (frame_to_pixel (frame + (current_page_frames())));
+
+ jack_nframes_t rightmost_frame = leftmost_frame + current_page_frames ();
+
+ if (rightmost_frame > last_canvas_frame) {
+ last_canvas_frame = rightmost_frame;
+ reset_scrolling_region ();
}
+
horizontal_adjustment.set_value (frame/frames_per_unit);
- XOriginChanged (); /* EMIT_SIGNAL */
}
}
temporal_zoom (fpu);
}
+void
+Editor::control_scroll (float fraction)
+{
+ ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::control_scroll), fraction));
+
+ if (!session) {
+ return;
+ }
+
+ double step = fraction * current_page_frames();
+ jack_nframes_t target;
+
+ if ((fraction < 0.0f) && (session->transport_frame() < (jack_nframes_t) fabs(step))) {
+ target = 0;
+ } else if ((fraction > 0.0f) && (max_frames - session->transport_frame() < step)) {
+ target = (max_frames - (current_page_frames()*2)); // allow room for slop in where the PH is on the screen
+ } else {
+ target = (session->transport_frame() + (jack_nframes_t) floor ((fraction * current_page_frames())));
+ }
+
+ /* move visuals, we'll catch up with it later */
+
+ playhead_cursor->set_position (target);
+
+ if (target > (current_page_frames() / 2)) {
+ /* try to center PH in window */
+ reposition_x_origin (target - (current_page_frames()/2));
+ } else {
+ reposition_x_origin (0);
+ }
+
+ /* cancel the existing */
+
+ control_scroll_connection.disconnect ();
+
+ /* add the next one */
+
+ control_scroll_connection = Glib::signal_timeout().connect (bind (mem_fun (*this, &Editor::deferred_control_scroll), target), 50);
+}
+
+bool
+Editor::deferred_control_scroll (jack_nframes_t target)
+{
+ session->request_locate (target);
+ return false;
+}
+
void
Editor::canvas_horizontally_scrolled ()
{
leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
-
+
update_fixed_rulers ();
if (!edit_hscroll_dragging) {
Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
{
if (!repos_zoom_queued) {
- Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
+ Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
repos_zoom_queued = true;
}
}
}
}
-void
-Editor::fake_handle_new_audio_region (AudioRegion *region)
-{
- Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
-}
-
-void
-Editor::fake_handle_audio_region_removed (AudioRegion *region)
-{
- Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
-}
-
-void
-Editor::fake_handle_new_duration ()
-{
- Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
-}
-
void
Editor::start_scrolling ()
{
scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
(mem_fun(*this, &Editor::update_current_screen));
-
- slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
- (mem_fun(*this, &Editor::update_slower));
}
void
void
Editor::handle_new_duration ()
{
- reset_scrolling_region ();
+ ENSURE_GUI_THREAD (mem_fun (*this, &Editor::handle_new_duration));
- if (session) {
- horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
- horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
+ jack_nframes_t new_end = session->get_maximum_extent() + (jack_nframes_t) floorf (current_page_frames() * 0.10f);
+
+ if (new_end > last_canvas_frame) {
+ last_canvas_frame = new_end;
+ reset_scrolling_region ();
}
+
+ horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
}
void
session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
- session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
- session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
- session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
+ session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::handle_new_audio_region)));
+ session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::handle_audio_region_removed)));
+ session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::handle_new_duration)));
session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::add_edit_group)));
session_connections.push_back (session->edit_group_removed.connect (mem_fun(*this, &Editor::edit_groups_changed)));
session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
update_crossfade_model ();
update_layering_model ();
- reset_scrolling_region ();
+ handle_new_duration ();
redisplay_regions ();
redisplay_named_selections ();
leftmost_frame = 0;
- horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
horizontal_adjustment.set_value (0);
restore_ruler_visibility ();
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
- DiskStream* ds;
+ AudioDiskstream* ds;
Playlist* pl;
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
- DiskStream* ds;
+ AudioDiskstream* ds;
Playlist* pl;
AudioPlaylist* apl;
items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
items.push_back (SeparatorElem());
+
+ /* range related stuff */
+
+ items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_audio_region)));
+ items.push_back (MenuElem (_("Set Range"), mem_fun (*this, &Editor::set_selection_from_audio_region)));
+ items.push_back (SeparatorElem());
+
/* Nudge region */
Menu *nudge_menu = manage (new Menu());
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)));
+ 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());
edit_items.push_back (MenuElem (_("Select"), *select_menu));
instant_save ();
}
-void
-Editor::add_location_from_selection ()
-{
- if (selection->time.empty()) {
- return;
- }
-
- if (session == 0 || clicked_trackview == 0) {
- return;
- }
-
- jack_nframes_t start = selection->time[clicked_selection].start;
- jack_nframes_t end = selection->time[clicked_selection].end;
-
- Location *location = new Location (start, end, "selection");
-
- session->begin_reversible_command (_("add marker"));
- session->add_undo (session->locations()->get_memento());
- session->locations()->add (location, true);
- session->add_redo_no_execute (session->locations()->get_memento());
- session->commit_reversible_command ();
-}
-
-void
-Editor::add_location_from_playhead_cursor ()
-{
- jack_nframes_t where = session->audible_frame();
-
- Location *location = new Location (where, where, "mark", Location::IsMark);
- session->begin_reversible_command (_("add marker"));
- session->add_undo (session->locations()->get_memento());
- session->locations()->add (location, true);
- session->add_redo_no_execute (session->locations()->get_memento());
- session->commit_reversible_command ();
-}
-
-
int
Editor::set_state (const XMLNode& node)
{
yoff = atoi(geometry->property("y_off")->value());
}
- set_geometry_hints (vpacker, g, Gdk::HINT_BASE_SIZE);
set_default_size (g.base_width, g.base_height);
move (x, y);
}
if ((prop = node.property ("zoom"))) {
- set_frames_per_unit (atof (prop->value()));
+ set_frames_per_unit (PBD::atof (prop->value()));
}
if ((prop = node.property ("snap-to"))) {
toolbar_frame.add (toolbar_base);
}
-gint
-Editor::_autoscroll_canvas (void *arg)
-{
- return ((Editor *) arg)->autoscroll_canvas ();
-}
-
-gint
-Editor::autoscroll_canvas ()
-{
- jack_nframes_t new_frame;
- bool keep_calling = true;
-
- if (autoscroll_direction < 0) {
- if (leftmost_frame < autoscroll_distance) {
- new_frame = 0;
- } else {
- new_frame = leftmost_frame - autoscroll_distance;
- }
- } else {
- if (leftmost_frame > max_frames - autoscroll_distance) {
- new_frame = max_frames;
- } else {
- new_frame = leftmost_frame + autoscroll_distance;
- }
- }
-
- if (new_frame != leftmost_frame) {
- reposition_x_origin (new_frame);
- }
-
- if (new_frame == 0 || new_frame == max_frames) {
- /* we are done */
- return FALSE;
- }
-
- autoscroll_cnt++;
-
- if (autoscroll_cnt == 1) {
-
- /* connect the timeout so that we get called repeatedly */
-
- autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
- keep_calling = false;
-
- } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
-
- /* after about a while, speed up a bit by changing the timeout interval */
-
- autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
- keep_calling = false;
-
- } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
-
- /* after about another while, speed up some more */
-
- autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
- keep_calling = false;
-
- } else if (autoscroll_cnt >= 30) {
-
- /* we've been scrolling for a while ... crank it up */
-
- autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
- }
-
- return keep_calling;
-}
-
-void
-Editor::start_canvas_autoscroll (int dir)
-{
- if (!session) {
- return;
- }
-
- stop_canvas_autoscroll ();
-
- autoscroll_direction = dir;
- autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
- autoscroll_cnt = 0;
-
- /* do it right now, which will start the repeated callbacks */
-
- autoscroll_canvas ();
-}
-
-void
-Editor::stop_canvas_autoscroll ()
-{
- if (autoscroll_timeout_tag >= 0) {
- gtk_timeout_remove (autoscroll_timeout_tag);
- autoscroll_timeout_tag = -1;
- }
-}
-
int
Editor::convert_drop_to_paths (vector<ustring>& paths,
const RefPtr<Gdk::DragContext>& context,
for (vector<ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
if ((*i).substr (0,7) == "file://") {
string p = *i;
- url_decode (p);
+ PBD::url_decode (p);
paths.push_back (p.substr (7));
}
}
}
}
-void
-Editor::set_selected_track_from_click (Selection::Operation op, bool with_undo, bool no_remove)
+bool
+Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool with_undo, bool no_remove)
{
+ bool commit = false;
+
if (!clicked_trackview) {
- return;
+ return false;
}
- if (with_undo) {
- begin_reversible_command (_("set selected trackview"));
- }
-
switch (op) {
case Selection::Toggle:
if (selection->selected (clicked_trackview)) {
if (!no_remove) {
selection->remove (clicked_trackview);
+ commit = true;
}
} else {
- selection->toggle (clicked_trackview);
+ selection->add (clicked_trackview);
+ commit = false;
}
break;
+
case Selection::Set:
if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
/* no commit necessary */
- return;
}
selection->set (clicked_trackview);
/* not defined yet */
break;
}
-
- if (with_undo) {
- commit_reversible_command ();
- }
+
+ return commit;
}
-void
-Editor::set_selected_control_point_from_click (Selection::Operation op, bool with_undo, bool no_remove)
+bool
+Editor::set_selected_control_point_from_click (bool press, Selection::Operation op, bool with_undo, bool no_remove)
{
if (!clicked_control_point) {
- return;
+ return false;
}
- if (with_undo) {
- begin_reversible_command (_("set selected control point"));
- }
+ /* select this point and any others that it represents */
- switch (op) {
- case Selection::Set:
- break;
- case Selection::Toggle:
- break;
- case Selection::Extend:
- break;
- }
- if (with_undo) {
- commit_reversible_command ();
- }
+ double y1, y2;
+ jack_nframes_t x1, x2;
+
+ x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
+ x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
+ y1 = clicked_control_point->get_x() - 10;
+ y2 = clicked_control_point->get_y() + 10;
+
+ return select_all_within (x1, x2, y1, y2, op);
}
void
-Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl)
+Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set<AudioTimeAxisView*>& relevant_tracks)
{
- set<AudioTimeAxisView*> relevant_tracks;
-
/* step one: get all selected tracks and all tracks in the relevant edit groups */
for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
/* no active group, or no group */
- relevant_tracks.insert (atv);
+ relevant_tracks.insert (&base);
}
}
+}
- /* step two: apply operation to each track */
+void
+Editor::mapover_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl)
+{
+ set<AudioTimeAxisView*> relevant_tracks;
+
+ if (!clicked_audio_trackview) {
+ return;
+ }
+
+ get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks);
uint32_t sz = relevant_tracks.size();
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
- DiskStream* ds;
-
+ AudioDiskstream* ds;
+
if ((ds = atv.get_diskstream()) == 0) {
/* bus */
return;
}
+
+ if (&atv == &basis->get_time_axis_view()) {
+ /* looking in same track as the original */
+ return;
+ }
+
if ((pl = ds->playlist()) != 0) {
pl->get_equivalent_regions (basis->region, results);
}
}
-void
-Editor::set_selected_regionview_from_click (Selection::Operation op, bool no_track_remove)
+bool
+Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
{
- cerr << "In SSRfC\n";
-
vector<AudioRegionView*> all_equivalent_regions;
+ bool commit = false;
- if (!clicked_regionview) {
- return;
+ if (!clicked_regionview || !clicked_audio_trackview) {
+ return false;
}
- mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click),
- clicked_regionview, &all_equivalent_regions));
-
+ if (op == Selection::Toggle || op == Selection::Set) {
+
+ mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click),
+ clicked_regionview, &all_equivalent_regions));
+
+
+ /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
+
+ all_equivalent_regions.push_back (clicked_regionview);
+
+ switch (op) {
+ case Selection::Toggle:
+
+ if (clicked_regionview->get_selected()) {
+ if (press) {
- cerr << "mapover done\n";
+ /* whatever was clicked was selected already; do nothing here but allow
+ the button release to deselect it
+ */
- begin_reversible_command (_("set selected regionview"));
+ button_release_can_deselect = true;
+
+ } else {
+
+ if (button_release_can_deselect) {
+
+ /* just remove this one region, but only on a permitted button release */
+
+ selection->remove (clicked_regionview);
+ commit = true;
+
+ /* no more deselect action on button release till a new press
+ finds an already selected object.
+ */
+
+ button_release_can_deselect = false;
+ }
+ }
- switch (op) {
- case Selection::Toggle:
- selection->toggle (clicked_regionview);
-#if 0
- if (clicked_regionview->get_selected()) {
- if (/* group && group->is_active() && */ selection->audio_regions.size() > 1) {
- /* reduce selection down to just the one clicked */
- selection->set (clicked_regionview);
} else {
- selection->remove (clicked_regionview);
+
+ if (press) {
+ /* add all the equivalent regions, but only on button press */
+
+ if (!all_equivalent_regions.empty()) {
+ commit = true;
+ }
+
+ for (vector<AudioRegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) {
+ selection->add (*i);
+ }
+ }
}
- } else {
- selection->add (all_equivalent_regions);
+ break;
+
+ case Selection::Set:
+ if (!clicked_regionview->get_selected()) {
+ selection->set (all_equivalent_regions);
+ commit = true;
+ } else {
+ /* no commit necessary: clicked on an already selected region */
+ goto out;
+ }
+ break;
+
+ default:
+ /* silly compiler */
+ break;
}
-#endif
- set_selected_track_from_click (op, false, no_track_remove);
- break;
- case Selection::Set:
- // karsten wiese suggested these two lines to make
- // a selected region rise to the top. but this
- // leads to a mismatch between actual layering
- // and visual layering. resolution required ....
- //
- // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
- // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
-
- if (clicked_regionview->get_selected()) {
- /* no commit necessary: we are the one selected. */
- return;
+ } else if (op == Selection::Extend) {
- } else {
-
- selection->set (all_equivalent_regions);
- set_selected_track_from_click (op, false, false);
+ list<Selectable*> results;
+ jack_nframes_t last_frame;
+ jack_nframes_t first_frame;
+
+ /* 1. find the last selected regionview in the track that was clicked in */
+
+ last_frame = 0;
+ first_frame = max_frames;
+
+ for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
+ if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
+
+ if ((*x)->region.last_frame() > last_frame) {
+ last_frame = (*x)->region.last_frame();
+ }
+
+ if ((*x)->region.first_frame() < first_frame) {
+ first_frame = (*x)->region.first_frame();
+ }
+ }
}
- break;
- case Selection::Extend:
- /* not defined yet */
- break;
+ /* 2. figure out the boundaries for our search for new objects */
+
+ switch (clicked_regionview->region.coverage (first_frame, last_frame)) {
+ case OverlapNone:
+ cerr << "no overlap, first = " << first_frame << " last = " << last_frame << " region = "
+ << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
+
+ if (last_frame < clicked_regionview->region.first_frame()) {
+ first_frame = last_frame;
+ last_frame = clicked_regionview->region.last_frame();
+ } else {
+ last_frame = first_frame;
+ first_frame = clicked_regionview->region.first_frame();
+ }
+ break;
+
+ case OverlapExternal:
+ cerr << "external overlap, first = " << first_frame << " last = " << last_frame << " region = "
+ << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
+
+ if (last_frame < clicked_regionview->region.first_frame()) {
+ first_frame = last_frame;
+ last_frame = clicked_regionview->region.last_frame();
+ } else {
+ last_frame = first_frame;
+ first_frame = clicked_regionview->region.first_frame();
+ }
+ break;
+
+ case OverlapInternal:
+ cerr << "internal overlap, first = " << first_frame << " last = " << last_frame << " region = "
+ << clicked_regionview->region.first_frame() << " .. " << clicked_regionview->region.last_frame() << endl;
+
+ if (last_frame < clicked_regionview->region.first_frame()) {
+ first_frame = last_frame;
+ last_frame = clicked_regionview->region.last_frame();
+ } else {
+ last_frame = first_frame;
+ first_frame = clicked_regionview->region.first_frame();
+ }
+ break;
+
+ case OverlapStart:
+ case OverlapEnd:
+ /* nothing to do except add clicked region to selection, since it
+ overlaps with the existing selection in this track.
+ */
+ break;
+ }
+
+ /* 2. find all selectable objects (regionviews in this case) between that one and the end of the
+ one that was clicked.
+ */
+
+ set<AudioTimeAxisView*> relevant_tracks;
+
+ get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks);
+
+ for (set<AudioTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
+ (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
+ }
+
+ /* 3. convert to a vector of audio regions */
+
+ vector<AudioRegionView*> audio_regions;
+
+ for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
+ AudioRegionView* arv;
+
+ if ((arv = dynamic_cast<AudioRegionView*>(*x)) != 0) {
+ audio_regions.push_back (arv);
+ }
+ }
+
+ if (!audio_regions.empty()) {
+ selection->add (audio_regions);
+ commit = true;
+ }
}
- cerr << "case done\n";
- commit_reversible_command () ;
+ out:
+ return commit;
}
void
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
- DiskStream* ds;
+ AudioDiskstream* ds;
if ((ds = tatv->get_diskstream()) == 0) {
/* bus */
switch (op) {
case Selection::Toggle:
/* XXX this is not correct */
- selection->add (all_equivalent_regions);
+ selection->toggle (all_equivalent_regions);
break;
case Selection::Set:
selection->set (all_equivalent_regions);
break;
case Selection::Extend:
- /* not defined yet */
+ selection->add (all_equivalent_regions);
break;
}
Editor::end_location_changed (Location* location)
{
ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
- horizontal_adjustment.set_upper (location->end() / frames_per_unit);
+ reset_scrolling_region ();
}
int