_track_canvas = _track_canvas_viewport->canvas ();
_track_canvas->set_background_color (UIConfiguration::instance().color ("arrange base"));
+ _track_canvas->use_nsglview ();
/* scroll group for items that should not automatically scroll
* (e.g verbose cursor). It shares the canvas coordinate space.
* uppermost (last) group with hv_scroll_group as a parent
*/
_drag_motion_group = new ArdourCanvas::Container (hv_scroll_group);
- CANVAS_DEBUG_NAME (_drag_motion_group, "Canvas Drag Motion");
+ CANVAS_DEBUG_NAME (_drag_motion_group, "Canvas Drag Motion");
/* TIME BAR CANVAS */
playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event);
+ snapped_cursor = new EditorCursor (*this);
+
_canvas_drop_zone = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, 0.0));
/* this thing is transparent */
_canvas_drop_zone->set_fill (false);
_track_canvas->signal_enter_notify_event().connect (sigc::mem_fun(*this, &Editor::entered_track_canvas), false);
_track_canvas->set_flags (CAN_FOCUS);
+ _track_canvas->PreRender.connect (sigc::mem_fun(*this, &Editor::pre_render));
+
/* set up drag-n-drop */
vector<TargetEntry> target_table;
}
update_fixed_rulers();
- redisplay_tempo (false);
+ redisplay_grid (false);
_summary->set_overlays_dirty ();
}
edit_controls_vbox.size_request (req);
w = req.width;
- if (_group_tabs->is_visible()) {
+ if (_group_tabs->is_visible()) {
_group_tabs->size_request (req);
- w += req.width;
- }
+ w += req.width;
+ }
- /* the controls layout has no horizontal scrolling, its visible
- width is always equal to the total width of its contents.
- */
+ /* the controls layout has no horizontal scrolling, its visible
+ width is always equal to the total width of its contents.
+ */
- controls_layout.property_width() = w;
- controls_layout.property_width_request() = w;
+ controls_layout.property_width() = w;
+ controls_layout.property_width_request() = w;
}
void
h += _canvas_drop_zone->height ();
- /* set the height of the scrollable area (i.e. the sum of all contained widgets)
+ /* set the height of the scrollable area (i.e. the sum of all contained widgets)
* for the controls layout. The size request is set elsewhere.
- */
+ */
- controls_layout.property_height() = h;
+ controls_layout.property_height() = h;
}
}
bool
-Editor::idle_drop_paths (vector<string> paths, framepos_t frame, double ypos, bool copy)
+Editor::idle_drop_paths (vector<string> paths, samplepos_t sample, double ypos, bool copy)
{
- drop_paths_part_two (paths, frame, ypos, copy);
+ drop_paths_part_two (paths, sample, ypos, copy);
return false;
}
void
-Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, double ypos, bool copy)
+Editor::drop_paths_part_two (const vector<string>& paths, samplepos_t sample, double ypos, bool copy)
{
RouteTimeAxisView* tv;
/* drop onto canvas background: create new tracks */
- frame = 0;
+ sample = 0;
InstrumentSelector is; // instantiation builds instrument-list and sets default.
- do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, SMFTrackName, SMFTempoIgnore, frame, is.selected_instrument());
+ do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, SMFTrackName, SMFTempoIgnore, sample, is.selected_instrument());
if (UIConfiguration::instance().get_only_copy_imported_files() || copy) {
do_import (audio_paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack,
- SrcBest, SMFTrackName, SMFTempoIgnore, frame);
+ SrcBest, SMFTrackName, SMFTempoIgnore, sample);
} else {
- do_embed (audio_paths, Editing::ImportDistinctFiles, ImportAsTrack, frame);
+ do_embed (audio_paths, Editing::ImportDistinctFiles, ImportAsTrack, sample);
}
} else if ((tv = dynamic_cast<RouteTimeAxisView*> (tvp.first)) != 0) {
selection->set (tv);
do_import (midi_paths, Editing::ImportSerializeFiles, ImportToTrack,
- SrcBest, SMFTrackName, SMFTempoIgnore, frame);
+ SrcBest, SMFTrackName, SMFTempoIgnore, sample);
if (UIConfiguration::instance().get_only_copy_imported_files() || copy) {
do_import (audio_paths, Editing::ImportSerializeFiles, Editing::ImportToTrack,
- SrcBest, SMFTrackName, SMFTempoIgnore, frame);
+ SrcBest, SMFTrackName, SMFTempoIgnore, sample);
} else {
- do_embed (audio_paths, Editing::ImportSerializeFiles, ImportToTrack, frame);
+ do_embed (audio_paths, Editing::ImportSerializeFiles, ImportToTrack, sample);
}
}
}
ev.button.x = x;
ev.button.y = y;
- MusicFrame when (window_event_sample (&ev, 0, &cy), 0);
+ MusicSample when (window_event_sample (&ev, 0, &cy), 0);
snap_to (when);
bool copy = ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY);
the main event loop with GTK/Quartz. Since import/embed wants
to push up a progress dialog, defer all this till we go idle.
*/
- Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, when.frame, cy, copy));
+ Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, when.sample, cy, copy));
#else
- drop_paths_part_two (paths, when.frame, cy, copy);
+ drop_paths_part_two (paths, when.sample, cy, copy);
#endif
}
controls_layout.get_parent()->translate_coordinates (*toplevel,
alloc.get_x(), alloc.get_y(),
- wx, wy);
+ wx, wy);
scrolling_boundary = ArdourCanvas::Rect (wx, wy, wx + alloc.get_width(), wy + alloc.get_height());
_track_canvas_viewport->get_parent()->translate_coordinates (*toplevel,
alloc.get_x(), alloc.get_y(),
- wx, wy);
+ wx, wy);
scrolling_boundary = ArdourCanvas::Rect (wx, wy, wx + alloc.get_width(), wy + alloc.get_height());
}
toplevel->get_window()->get_pointer (x, y, mask);
- if ((allow_horiz && ((x < scrolling_boundary.x0 && leftmost_frame > 0) || x >= scrolling_boundary.x1)) ||
+ if ((allow_horiz && ((x < scrolling_boundary.x0 && _leftmost_sample > 0) || x >= scrolling_boundary.x1)) ||
(allow_vert && ((y < scrolling_boundary.y0 && vertical_adjustment.get_value() > 0)|| y >= scrolling_boundary.y1))) {
start_canvas_autoscroll (allow_horiz, allow_vert, scrolling_boundary);
}
return autoscroll_connection.connected ();
}
+std::pair <samplepos_t,samplepos_t>
+Editor::session_gui_extents (bool use_extra) const
+{
+ if (!_session) {
+ return std::pair <samplepos_t,samplepos_t>(max_samplepos,0);
+ }
+
+ samplecnt_t session_extent_start = _session->current_start_sample();
+ samplecnt_t session_extent_end = _session->current_end_sample();
+
+ /* calculate the extents of all regions in every playlist
+ * NOTE: we should listen to playlists, and cache these values so we don't calculate them every time.
+ */
+ {
+ boost::shared_ptr<RouteList> rl = _session->get_routes();
+ for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
+ boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*r);
+ if (tr) {
+ boost::shared_ptr<Playlist> pl = tr->playlist();
+ if (pl && !pl->all_regions_empty()) {
+ pair<samplepos_t, samplepos_t> e;
+ e = pl->get_extent();
+ if (e.first < session_extent_start) {
+ session_extent_start = e.first;
+ }
+ if (e.second > session_extent_end) {
+ session_extent_end = e.second;
+ }
+ }
+ }
+ }
+ }
+
+ /* ToDo: also incorporate automation regions (in case the session has no audio/midi but is just used for automating plugins or the like) */
+
+ /* add additional time to the ui extents (user-defined in config) */
+ if (use_extra) {
+ samplecnt_t const extra = UIConfiguration::instance().get_extra_ui_extents_time() * 60 * _session->nominal_sample_rate();
+ session_extent_end += extra;
+ session_extent_start -= extra;
+ }
+
+ /* range-check */
+ if (session_extent_end > max_samplepos) {
+ session_extent_end = max_samplepos;
+ }
+ if (session_extent_start < 0) {
+ session_extent_start = 0;
+ }
+
+ std::pair <samplepos_t,samplepos_t> ret (session_extent_start, session_extent_end);
+ return ret;
+}
+
bool
Editor::autoscroll_canvas ()
{
int x, y;
Gdk::ModifierType mask;
- frameoffset_t dx = 0;
+ sampleoffset_t dx = 0;
bool no_stop = false;
Gtk::Window* toplevel = dynamic_cast<Gtk::Window*>(contents().get_toplevel());
if (autoscroll_horizontal_allowed) {
- framepos_t new_frame = leftmost_frame;
+ samplepos_t new_sample = _leftmost_sample;
/* horizontal */
dx = pixel_to_sample (dx);
- if (leftmost_frame < max_framepos - dx) {
- new_frame = leftmost_frame + dx;
+ dx *= UIConfiguration::instance().get_draggable_playhead_speed();
+
+ if (_leftmost_sample < max_samplepos - dx) {
+ new_sample = _leftmost_sample + dx;
} else {
- new_frame = max_framepos;
+ new_sample = max_samplepos;
}
no_stop = true;
dx = pixel_to_sample (dx);
- if (leftmost_frame >= dx) {
- new_frame = leftmost_frame - dx;
+ dx *= UIConfiguration::instance().get_draggable_playhead_speed();
+
+ if (_leftmost_sample >= dx) {
+ new_sample = _leftmost_sample - dx;
} else {
- new_frame = 0;
+ new_sample = 0;
}
no_stop = true;
}
- if (new_frame != leftmost_frame) {
- vc.time_origin = new_frame;
+ if (new_sample != _leftmost_sample) {
+ vc.time_origin = new_sample;
vc.add (VisualChange::TimeOrigin);
}
}
{
horizontal_adjustment.set_value (p);
- leftmost_frame = (framepos_t) floor (p * samples_per_pixel);
-
- update_fixed_rulers ();
- redisplay_tempo (true);
-
- if (pending_visual_change.idle_handler_id < 0) {
- _summary->set_overlays_dirty ();
- }
-
- update_video_timeline();
+ _leftmost_sample = (samplepos_t) floor (p * samples_per_pixel);
}
void
Editor::color_handler()
{
- ArdourCanvas::Color base = UIConfiguration::instance().color ("ruler base");
- ArdourCanvas::Color text = UIConfiguration::instance().color ("ruler text");
+ Gtkmm2ext::Color base = UIConfiguration::instance().color ("ruler base");
+ Gtkmm2ext::Color text = UIConfiguration::instance().color ("ruler text");
timecode_ruler->set_fill_color (base);
timecode_ruler->set_outline_color (text);
minsec_ruler->set_fill_color (base);
_track_canvas->queue_draw ();
/*
- redisplay_tempo (true);
+ redisplay_grid (true);
if (_session)
_session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers
double
Editor::horizontal_position () const
{
- return sample_to_pixel (leftmost_frame);
+ return sample_to_pixel (_leftmost_sample);
}
bool
}
}
-Gdk::Cursor*
-Editor::which_grabber_cursor () const
-{
- Gdk::Cursor* c = _cursors->grabber;
-
- switch (_edit_point) {
- case EditAtMouse:
- c = _cursors->grabber_edit_point;
- break;
- default:
- boost::shared_ptr<Movable> m = _movable.lock();
- if (m && m->locked()) {
- c = _cursors->speaker;
- }
- break;
- }
-
- return c;
-}
-
Gdk::Cursor*
Editor::which_trim_cursor (bool left) const
{
switch (_join_object_range_state) {
case JOIN_OBJECT_RANGE_NONE:
case JOIN_OBJECT_RANGE_OBJECT:
- cursor = which_grabber_cursor ();
+ cursor = _cursors->grabber;
break;
case JOIN_OBJECT_RANGE_RANGE:
cursor = _cursors->selector;
cursor = which_track_cursor ();
break;
case PlayheadCursorItem:
- switch (_edit_point) {
- case EditAtMouse:
- cursor = _cursors->grabber_edit_point;
- break;
- default:
- cursor = _cursors->grabber;
- break;
- }
+ cursor = _cursors->grabber;
break;
case SelectionItem:
cursor = _cursors->selector;
cursor = _cursors->cross_hair;
break;
case LeftFrameHandle:
- if ( effective_mouse_mode() == MouseObject ) // (smart mode): if the user is in the btm half, show the trim cursor
+ if (effective_mouse_mode() == MouseObject) // (smart mode): if the user is in the btm half, show the trim cursor
cursor = which_trim_cursor (true);
else
- cursor = _cursors->selector; // (smart mode): in the top half, just show the selection (range) cursor
+ cursor = _cursors->selector; // (smart mode): in the top half, just show the selection (range) cursor
break;
case RightFrameHandle:
- if ( effective_mouse_mode() == MouseObject ) //see above
+ if (effective_mouse_mode() == MouseObject) // see above
cursor = which_trim_cursor (false);
else
cursor = _cursors->selector;
case VideoBarItem:
case TransportMarkerBarItem:
case DropZoneItem:
- cursor = which_grabber_cursor();
+ cursor = _cursors->grabber;
break;
default: