#include "marker.h"
#include "streamview.h"
#include "region_gain_line.h"
+#include "rc_option_editor.h"
#include "automation_time_axis.h"
#include "control_point.h"
#include "selection.h"
using Gtkmm2ext::Keyboard;
bool
-Editor::mouse_frame (framepos_t& where, bool& in_track_canvas) const
+Editor::mouse_sample (samplepos_t& where, bool& in_track_canvas) const
{
/* gdk_window_get_pointer() has X11's XQueryPointer semantics in that it only
pays attentions to subwindows. this means that menu windows are ignored, and
return true;
}
-framepos_t
+samplepos_t
Editor::window_event_sample (GdkEvent const * event, double* pcx, double* pcy) const
{
ArdourCanvas::Duple d;
return pixel_to_sample (d.x);
}
-framepos_t
+samplepos_t
Editor::canvas_event_sample (GdkEvent const * event, double* pcx, double* pcy) const
{
double x;
/* note that pixel_to_sample_from_event() never returns less than zero, so even if the pixel
position is negative (as can be the case with motion events in particular),
- the frame location is always positive.
+ the sample location is always positive.
*/
return pixel_to_sample_from_event (x);
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
assert (tact);
- set_mouse_mode(m, true); //call this so the button styles can get updated
+ set_mouse_mode (m, true); // call this so the button styles can get updated
}
+bool
+Editor::snap_mode_button_clicked (GdkEventButton* ev)
+{
+ if (ev->button != 3) {
+ cycle_snap_mode();
+ return true;
+ }
+
+ RCOptionEditor* rc_option_editor = ARDOUR_UI::instance()->get_rc_option_editor();
+ if (rc_option_editor) {
+ ARDOUR_UI::instance()->show_tabbable (rc_option_editor);
+ rc_option_editor->set_current_page (_("Editor/Snap"));
+ }
+
+ return true;
+}
+
+
+
static Glib::RefPtr<Action>
get_mouse_mode_action(MouseMode m)
{
}
if (ARDOUR::Profile->get_mixbus()) {
- if ( m == MouseCut) m = MouseObject;
+ if (m == MouseCut) m = MouseObject;
+ if (m == MouseAudition) m = MouseRange;
}
Glib::RefPtr<Action> act = get_mouse_mode_action(m);
tact->set_active (false);
tact->set_active (true);
- //NOTE: this will result in a call to mouse_mode_toggled which does the heavy lifting
+ /* NOTE: this will result in a call to mouse_mode_toggled which does the heavy lifting */
}
void
Editor::mouse_mode_toggled (MouseMode m)
{
if (ARDOUR::Profile->get_mixbus()) {
- if ( m == MouseCut) m = MouseObject;
+ if (m == MouseCut) m = MouseObject;
+ if (m == MouseAudition) m = MouseRange;
}
Glib::RefPtr<Action> act = get_mouse_mode_action(m);
/* Switch snap type/mode if we're moving to/from an internal tool. Note
this must toggle the actions and not call set_snap_*() directly,
otherwise things get out of sync and the combo box stops working. */
- if (!was_internal && internal_editing()) {
- snap_type_action(internal_snap_type)->set_active(true);
+ if (!UIConfiguration::instance().get_grid_follows_internal()) {
+ grid_type_action(pre_internal_grid_type)->set_active(true);
+ snap_mode_action(pre_internal_snap_mode)->set_active(true);
+ } else if (!was_internal && internal_editing()) {
+ grid_type_action(internal_grid_type)->set_active(true);
snap_mode_action(internal_snap_mode)->set_active(true);
} else if (was_internal && !internal_editing()) {
- snap_type_action(pre_internal_snap_type)->set_active(true);
+ grid_type_action(pre_internal_grid_type)->set_active(true);
snap_mode_action(pre_internal_snap_mode)->set_active(true);
}
std::list<Selectable*> selectables;
uint32_t before, after;
- framecnt_t const where = (framecnt_t) floor (event->button.x * samples_per_pixel) - clicked_regionview->region ()->position ();
+ samplecnt_t const where = (samplecnt_t) floor (event->button.x * samples_per_pixel) - clicked_regionview->region ()->position ();
if (!argl || !argl->control_points_adjacent (where, before, after)) {
break;
al->grab_item().canvas_to_item (mx, my);
uint32_t before, after;
- framecnt_t const where = (framecnt_t) floor (mx * samples_per_pixel);
+ samplecnt_t const where = (samplecnt_t) floor (mx * samples_per_pixel);
if (!al || !al->control_points_adjacent (where, before, after)) {
break;
break;
case StreamItem:
- //in the past, we created a new midi region here, but perhaps that is best left to the Draw mode
+ /* in the past, we created a new midi region here, but perhaps that is best left to the Draw mode */
break;
case AutomationTrackItem:
case StartCrossFadeItem:
case EndCrossFadeItem:
- /* we might allow user to grab inside the fade to trim a region with preserve_fade_anchor. for not this is not fully implemented */
-// if (!clicked_regionview->region()->locked()) {
-// _drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), true), event);
-// return true;
-// }
+ /* we might allow user to grab inside the fade to trim a region with preserve_fade_anchor.
+ * For not this is not fully implemented */
+#if 0
+ if (!clicked_regionview->region()->locked()) {
+ _drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer(), true), event);
+ return true;
+ }
+#endif
break;
case FeatureLineItem:
_drags->set (new RegionCreateDrag (this, item, parent), event);
} else {
/* See if there's a region before the click that we can extend, and extend it if so */
- framepos_t const t = canvas_event_sample (event);
+ samplepos_t const t = canvas_event_sample (event);
boost::shared_ptr<Region> prev = pl->find_next_region (t, End, -1);
if (!prev) {
_drags->set (new RegionCreateDrag (this, item, parent), event);
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y, false);
if (tvp.first) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
- if ( atv) {
+ if (atv) {
/* smart "join" mode: drag automation */
_drags->set (new AutomationRangeDrag (this, atv, selection->time), event, _cursors->up_down);
}
if ((item_type != FadeInHandleItem) &&
(item_type != FadeOutHandleItem) &&
- !_drags->active () &&
- _session &&
- !_session->transport_rolling() &&
- (effective_mouse_mode() == MouseRange) &&
- UIConfiguration::instance().get_follow_edits() &&
+ !_drags->active () &&
+ _session &&
+ !_session->transport_rolling() &&
+ (effective_mouse_mode() == MouseRange) &&
+ UIConfiguration::instance().get_follow_edits() &&
!_session->config.get_external_sync()) {
- MusicFrame where (canvas_event_sample (event), 0);
+ MusicSample where (canvas_event_sample (event), 0);
snap_to (where);
- _session->request_locate (where.frame, false);
+ _session->request_locate (where.sample, false);
}
switch (event->button.button) {
bool
Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
- MusicFrame where (canvas_event_sample (event), 0);
+ MusicSample where (canvas_event_sample (event), 0);
AutomationTimeAxisView* atv = 0;
_press_cursor_ctx.reset();
case SamplesRulerItem:
case MinsecRulerItem:
case BBTRulerItem:
- popup_ruler_menu (where.frame, item_type);
+ popup_ruler_menu (where.sample, item_type);
break;
case MarkerItem:
case MarkerBarItem:
if (!_dragging_playhead) {
- snap_to_with_modifier (where, event, RoundNearest, true);
- mouse_add_new_marker (where.frame);
+ snap_to_with_modifier (where, event, RoundNearest, SnapToGrid_Scaled);
+ mouse_add_new_marker (where.sample);
}
return true;
case CdMarkerBarItem:
if (!_dragging_playhead) {
- // if we get here then a dragged range wasn't done
- snap_to_with_modifier (where, event, RoundNearest, true);
- mouse_add_new_marker (where.frame, true);
+ /* if we get here then a dragged range wasn't done */
+ snap_to_with_modifier (where, event, RoundNearest, SnapToGrid_Scaled);
+ mouse_add_new_marker (where.sample, true);
}
return true;
case TempoBarItem:
case TempoCurveItem:
if (!_dragging_playhead && Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
snap_to_with_modifier (where, event);
- mouse_add_new_tempo_event (where.frame);
+ mouse_add_new_tempo_event (where.sample);
}
return true;
bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
atv = dynamic_cast<AutomationTimeAxisView*>(clicked_axisview);
if (atv) {
- atv->add_automation_event (event, where.frame, event->button.y, with_guard_points);
+ atv->add_automation_event (event, where.sample, event->button.y, with_guard_points);
}
return true;
break;
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier|Keyboard::SecondaryModifier))) {
lower_region ();
} else {
- // Button2 click is unused
+ /* Button2 click is unused */
}
return true;
}
void
-Editor::scrub (framepos_t frame, double current_x)
+Editor::scrub (samplepos_t sample, double current_x)
{
double delta;
if (scrubbing_direction == 0) {
/* first move */
- _session->request_locate (frame, false);
+ _session->request_locate (sample, false);
_session->request_transport_speed (0.1);
scrubbing_direction = 1;
update_join_object_range_location (event->motion.y);
if (_drags->active ()) {
+ //drags change the snapped_cursor location, because we are snapping the thing being dragged, not the actual mouse cursor
return _drags->motion_handler (event, from_autoscroll);
+ } else {
+ //the snapped_cursor shows where an operation (like Split) is going to occur
+ bool ignored;
+ MusicSample where (0, 0);
+ if (mouse_sample (where.sample, ignored)) {
+ snap_to_with_modifier (where, event);
+ set_snapped_cursor_position (where.sample);
+ }
}
return false;
if (Keyboard::modifier_state_contains (event->state, Keyboard::PrimaryModifier)) {
TimeAxisView* tv = &rv.get_time_axis_view();
- RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
- framepos_t where = get_preferred_edit_position();
+ samplepos_t where = get_preferred_edit_position();
if (where >= 0) {
}
void
-Editor::point_trim (GdkEvent* event, framepos_t new_bound)
+Editor::point_trim (GdkEvent* event, samplepos_t new_bound)
{
RegionView* rv = clicked_regionview;
void
-Editor::mouse_brush_insert_region (RegionView* rv, framepos_t pos)
+Editor::mouse_brush_insert_region (RegionView* rv, samplepos_t pos)
{
- /* no brushing without a useful snap setting */
-
- switch (_snap_mode) {
- case SnapMagnetic:
- return; /* can't work because it allows region to be placed anywhere */
- default:
- break; /* OK */
- }
-
- switch (_snap_type) {
- case SnapToMark:
+ /* no brushing without a useful quantize setting */
+ if (_grid_type == GridTypeNone)
return;
- default:
- break;
- }
-
/* don't brush a copy over the original */
if (pos == rv->region()->position()) {
playlist->add_region (new_region, pos);
_session->add_command (new StatefulDiffCommand (playlist));
- // playlist is frozen, so we have to update manually XXX this is disgusting
+ /* playlist is frozen, so we have to update manually XXX this is disgusting */
//playlist->RegionAdded (new_region); /* EMIT SIGNAL */
}
_drags->abort ();
} else {
selection->clear ();
+
+ /* if session is playing a range, cancel that */
+ if (_session->get_play_range()) {
+ _session->request_cancel_play_range();
+ }
+
+ if (_session->solo_selection_active()) {
+ StripableList sl;
+ _session->solo_selection (sl, false);
+ }
}
ARDOUR_UI::instance()->reset_focus (&contents());
if (entered_regionview) {
- //ToDo: there is currently a bug here(?)
- //when we are inside a region fade handle, it acts as though we are in range mode because it is in the top half of the region
- //can it be fixed here?
+ /* TODO: there is currently a bug here(?)
+ * when we are inside a region fade handle, it acts as though we are in range mode because it is in the top half of the region
+ * can it be fixed here?
+ */
ArdourCanvas::Duple const item_space = entered_regionview->get_canvas_group()->canvas_to_item (ArdourCanvas::Duple (0, y));
double const c = item_space.y / entered_regionview->height();