#include "ardour/midi_region.h"
#include "ardour/midi_track.h"
#include "ardour/operations.h"
+#include "ardour/profile.h"
#include "ardour/region_factory.h"
#include "ardour/session.h"
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
const boost::shared_ptr<const Region> original = rv->region();
- boost::shared_ptr<Region> region_copy = RegionFactory::create (original, true
- , current_music_divisor (original->position(), event->button.state));
+ boost::shared_ptr<Region> region_copy;
+
+ if (rv == _primary) {
+ region_copy = RegionFactory::create (original, true
+ , current_music_divisor (original->position(), event->button.state));
+ } else {
+ region_copy = RegionFactory::create (original, true, 0);
+ }
+
/* need to set this so that the drop zone code can work. This doesn't
actually put the region into the playlist, but just sets a weak pointer
to it.
if (was_double_click() && !_views.empty()) {
DraggingView dv = _views.front();
- dv.view->show_region_editor ();
-
+ _editor->edit_region (dv.view);
}
return;
);
}
-
- _editor->maybe_locate_with_edit_preroll (_editor->get_selection().regions.start());
}
RouteTimeAxisView*
/* Add a new track of the correct type, and return the RouteTimeAxisView that is created to display the
new track.
*/
-
+ TimeAxisView* tav = 0;
try {
if (boost::dynamic_pointer_cast<AudioRegion> (region)) {
list<boost::shared_ptr<AudioTrack> > audio_tracks;
output_chan = _editor->session()->master_out()->n_inputs().n_audio();
}
audio_tracks = _editor->session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order);
- TimeAxisView* tav =_editor->axis_view_from_stripable (audio_tracks.front());
- if (tav) {
- tav->set_height (original->current_height());
- }
- return dynamic_cast<RouteTimeAxisView*>(tav);
+ tav =_editor->axis_view_from_stripable (audio_tracks.front());
} else {
ChanCount one_midi_port (DataType::MIDI, 1);
list<boost::shared_ptr<MidiTrack> > midi_tracks;
- midi_tracks = _editor->session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr<ARDOUR::PluginInfo>(),
+ midi_tracks = _editor->session()->new_midi_track (one_midi_port, one_midi_port,
+ Config->get_strict_io () || Profile->get_mixbus (),
+ boost::shared_ptr<ARDOUR::PluginInfo>(),
(ARDOUR::Plugin::PresetRecord*) 0,
(ARDOUR::RouteGroup*) 0, 1, region->name(), PresentationInfo::max_order);
- TimeAxisView* tav = _editor->axis_view_from_stripable (midi_tracks.front());
- if (tav) {
- tav->set_height (original->current_height());
- }
- return dynamic_cast<RouteTimeAxisView*> (tav);
+ tav = _editor->axis_view_from_stripable (midi_tracks.front());
+ }
+
+ if (tav) {
+ tav->set_height (original->current_height());
}
} catch (...) {
error << _("Could not create new track after region placed in the drop zone") << endmsg;
- return 0;
}
+
+ return dynamic_cast<RouteTimeAxisView*> (tav);
}
void
PlaylistSet modified_playlists;
RouteTimeAxisView* new_time_axis_view = 0;
+ int32_t divisor = current_music_divisor (_primary->region()->position() - drag_delta, ev_state);
+ TempoMap& tmap (_editor->session()->tempo_map());
+ double qn_delta = _primary->region()->quarter_note() - tmap.exact_qn_at_frame (_primary->region()->position() - drag_delta, divisor);
+
if (_brushing) {
/* all changes were made during motion event handlers */
if ((pm = playlist_mapping.find (i->view->region()->playlist())) == playlist_mapping.end()) {
/* first region from this original playlist: create a new track */
new_time_axis_view = create_destination_time_axis (i->view->region(), i->initial_time_axis_view);
+ if(!new_time_axis_view) {
+ Drag::abort();
+ return;
+ }
playlist_mapping.insert (make_pair (i->view->region()->playlist(), new_time_axis_view));
dest_rtv = new_time_axis_view;
} else {
}
if (dest_rtv != 0) {
- RegionView* new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
- modified_playlists, current_music_divisor (where, ev_state));
+ RegionView* new_view;
+ if (i->view == _primary) {
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
+ modified_playlists, current_music_divisor (where, ev_state));
+ } else {
+ if (i->view->region()->position_lock_style() == AudioTime) {
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
+ modified_playlists, 0);
+ } else {
+ where = tmap.frame_at_quarter_note (i->view->region()->quarter_note() - qn_delta);
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
+ modified_playlists, 0);
+ }
+ }
if (new_view != 0) {
new_views.push_back (new_view);
typedef map<boost::shared_ptr<Playlist>, RouteTimeAxisView*> PlaylistMapping;
PlaylistMapping playlist_mapping;
+ int32_t divisor = current_music_divisor (_primary->region()->position() - drag_delta, ev_state);
+ TempoMap& tmap (_editor->session()->tempo_map());
+ double qn_delta = _primary->region()->quarter_note() - tmap.exact_qn_at_frame (_primary->region()->position() - drag_delta, divisor);
+
std::set<boost::shared_ptr<const Region> > uniq;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
if ((pm = playlist_mapping.find (i->view->region()->playlist())) == playlist_mapping.end()) {
/* first region from this original playlist: create a new track */
new_time_axis_view = create_destination_time_axis (i->view->region(), i->initial_time_axis_view);
+ if(!new_time_axis_view) { // New track creation failed
+ Drag::abort();
+ return;
+ }
playlist_mapping.insert (make_pair (i->view->region()->playlist(), new_time_axis_view));
dest_rtv = new_time_axis_view;
} else {
if (changed_tracks) {
/* insert into new playlist */
+ RegionView* new_view;
+ if (rv == _primary) {
+ new_view = insert_region_into_playlist (
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
+ modified_playlists, current_music_divisor (where, ev_state)
+ );
+ } else {
+ if (rv->region()->position_lock_style() == AudioTime) {
- RegionView* new_view = insert_region_into_playlist (
- RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
- modified_playlists, current_music_divisor (where, ev_state)
- );
+ new_view = insert_region_into_playlist (
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
+ modified_playlists, 0
+ );
+ } else {
+ where = tmap.frame_at_quarter_note (rv->region()->quarter_note() - qn_delta);
+ new_view = insert_region_into_playlist (
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
+ modified_playlists, 0
+ );
+ }
+ }
if (new_view == 0) {
++i;
if (r.second) {
playlist->freeze ();
}
+ if (rv == _primary) {
+ rv->region()->set_position (where, current_music_divisor (where, ev_state));
+ } else {
+ if (rv->region()->position_lock_style() == AudioTime) {
+ rv->region()->set_position (where, 0);
+ } else {
+ rv->region()->set_position (tmap.frame_at_quarter_note (rv->region()->quarter_note() - qn_delta), 0);
- rv->region()->set_position (where, current_music_divisor (where, ev_state));
+ }
+ }
_editor->session()->add_command (new StatefulDiffCommand (rv->region()));
}
if (was_double_click() && !_views.empty()) {
DraggingView dv = _views.front();
- dv.view->show_region_editor ();
-
+ _editor->edit_region (dv.view);
}
return;
}
}
- if (!_views.empty()) {
- if (_operation == StartTrim) {
- _editor->maybe_locate_with_edit_preroll(
- _views.begin()->view->region()->position());
- }
- if (_operation == EndTrim) {
- _editor->maybe_locate_with_edit_preroll(
- _views.begin()->view->region()->position() +
- _views.begin()->view->region()->length());
- }
- }
-
if (!_editor->selection->selected (_primary)) {
_primary->thaw_after_trim ();
} else {
--bbt.bars;
}
const double beat = map.beat_at_bbt (bbt);
+ const framepos_t frame = map.frame_at_beat (beat);
_real_section = map.add_meter (Meter (_marker->meter().divisions_per_bar(), _marker->meter().note_divisor())
- , beat, bbt, _real_section->position_lock_style());
+ , beat, bbt, frame, _real_section->position_lock_style());
if (!_real_section) {
aborted (true);
return;
pf = adjusted_current_frame (event, false);
}
- _editor->session()->tempo_map().gui_move_meter (_real_section, pf);
+ _editor->session()->tempo_map().gui_set_meter_position (_real_section, pf);
/* fake marker meeds to stay under the mouse, unlike the real one. */
_marker->set_position (adjusted_current_frame (event, false));
_marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker"));
_real_section = &_marker->tempo();
- _movable = _real_section->movable();
+ _movable = !_real_section->initial();
_grab_bpm = _real_section->note_types_per_minute();
assert (_marker);
}
/* snap to beat is 1, snap to bar is -1 (sorry) */
const int sub_num = _editor->get_grid_music_divisions (event->button.state);
- map.gui_move_tempo (_real_section, pf, sub_num);
+ map.gui_set_tempo_position (_real_section, pf, sub_num);
show_verbose_cursor_time (_real_section->frame());
}
if (first_move) {
/* get current state */
before_state = &map.get_state();
- _editor->begin_reversible_command (_("dilate tempo"));
+ _editor->begin_reversible_command (_("stretch tempo"));
}
framepos_t pf;
if (ArdourKeyboard::indicates_constraint (event->button.state)) {
/* adjust previous tempo to match pointer frame */
- _editor->session()->tempo_map().gui_dilate_tempo (_tempo, map.frame_at_quarter_note (_grab_qn), pf);
+ _editor->session()->tempo_map().gui_stretch_tempo (_tempo, map.frame_at_quarter_note (_grab_qn), pf);
}
ostringstream sstr;
sstr << "^" << fixed << setprecision(3) << map.tempo_at_frame (pf).note_types_per_minute() << "\n";
return;
}
+ const int32_t divisions = _editor->get_grid_music_divisions (event->button.state);
+
/* now move them all */
for (x = _copied_locations.begin(); x != _copied_locations.end(); ++x) {
if (copy_location->is_mark()) {
/* now move it */
-
- copy_location->set_start (copy_location->start() + f_delta);
+ copy_location->set_start (copy_location->start() + f_delta, false, true, divisions);
} else {
if (is_start) { // start-of-range marker
if (move_both || (*x).move_both) {
- copy_location->set_start (new_start);
- copy_location->set_end (new_end);
+ copy_location->set_start (new_start, false, true, divisions);
+ copy_location->set_end (new_end, false, true, divisions);
} else if (new_start < copy_location->end()) {
- copy_location->set_start (new_start);
+ copy_location->set_start (new_start, false, true, divisions);
} else if (newframe > 0) {
//_editor->snap_to (next, RoundUpAlways, true);
- copy_location->set_end (next);
- copy_location->set_start (newframe);
+ copy_location->set_end (next, false, true, divisions);
+ copy_location->set_start (newframe, false, true, divisions);
}
} else { // end marker
if (move_both || (*x).move_both) {
- copy_location->set_end (new_end);
- copy_location->set_start (new_start);
+ copy_location->set_end (new_end, divisions);
+ copy_location->set_start (new_start, false, true, divisions);
} else if (new_end > copy_location->start()) {
- copy_location->set_end (new_end);
+ copy_location->set_end (new_end, false, true, divisions);
} else if (newframe > 0) {
//_editor->snap_to (next, RoundDownAlways, true);
- copy_location->set_start (next);
- copy_location->set_end (newframe);
+ copy_location->set_start (next, false, true, divisions);
+ copy_location->set_end (newframe, false, true, divisions);
}
}
}
MarkerSelection::iterator i;
CopiedLocationInfo::iterator x;
+ const int32_t divisions = _editor->get_grid_music_divisions (event->button.state);
bool is_start;
for (i = _editor->selection->markers.begin(), x = _copied_locations.begin();
in_command = true;
}
if (location->is_mark()) {
- location->set_start (((*x).location)->start());
+ location->set_start (((*x).location)->start(), false, true, divisions);
} else {
- location->set (((*x).location)->start(), ((*x).location)->end());
+ location->set (((*x).location)->start(), ((*x).location)->end(), true, divisions);
}
if (location->is_session_range()) {
: Drag (e, i)
, _operation (o)
, _add (false)
+ , _track_selection_at_start (e)
, _time_selection_at_start (!_editor->get_selection().time.empty())
{
DEBUG_TRACE (DEBUG::Drags, "New SelectionDrag\n");
return;
}
+ if (first_move) {
+ _track_selection_at_start = _editor->selection->tracks;
+ }
+
switch (_operation) {
case CreateSelection:
{
}
}
- //now find any tracks that are GROUPED with the tracks we selected
- TrackViewList grouped_add = new_selection;
- for (TrackViewList::const_iterator i = new_selection.begin(); i != new_selection.end(); ++i) {
- RouteTimeAxisView *n = dynamic_cast<RouteTimeAxisView *>(*i);
- if ( n && n->route()->route_group() && n->route()->route_group()->is_active() && n->route()->route_group()->enabled_property (ARDOUR::Properties::group_select.property_id) ) {
- for (TrackViewList::const_iterator j = all_tracks.begin(); j != all_tracks.end(); ++j) {
- RouteTimeAxisView *check = dynamic_cast<RouteTimeAxisView *>(*j);
- if ( check && (n != check) && (check->route()->route_group() == n->route()->route_group()) )
- grouped_add.push_back (*j);
+ //now compare our list with the current selection, and add as necessary
+ //( NOTE: most mouse moves don't change the selection so we can't just SET it for every mouse move; it gets clunky )
+ TrackViewList tracks_to_add;
+ TrackViewList tracks_to_remove;
+
+ if (!first_move) {
+ for (TrackViewList::const_iterator i = _editor->selection->tracks.begin(); i != _editor->selection->tracks.end(); ++i) {
+ if (!new_selection.contains (*i) && !_track_selection_at_start.contains (*i)) {
+ tracks_to_remove.push_back (*i);
}
}
}
- //now compare our list with the current selection, and add or remove as necessary
- //( NOTE: most mouse moves don't change the selection so we can't just SET it for every mouse move; it gets clunky )
- TrackViewList tracks_to_add;
- TrackViewList tracks_to_remove;
- for (TrackViewList::const_iterator i = grouped_add.begin(); i != grouped_add.end(); ++i)
- if ( !_editor->selection->tracks.contains ( *i ) )
- tracks_to_add.push_back ( *i );
- for (TrackViewList::const_iterator i = _editor->selection->tracks.begin(); i != _editor->selection->tracks.end(); ++i)
- if ( !grouped_add.contains ( *i ) )
- tracks_to_remove.push_back ( *i );
- _editor->selection->add(tracks_to_add);
- _editor->selection->remove(tracks_to_remove);
+ for (TrackViewList::const_iterator i = new_selection.begin(); i != new_selection.end(); ++i) {
+ if (!_editor->selection->tracks.contains (*i)) {
+ tracks_to_add.push_back (*i);
+ }
+ }
+
+ _editor->selection->add (tracks_to_add);
+ if (!tracks_to_remove.empty()) {
+ _editor->selection->remove (tracks_to_remove);
+ }
}
}
break;
s->request_play_range (&_editor->selection->time, true);
} else if (!s->config.get_external_sync()) {
if (UIConfiguration::instance().get_follow_edits() && !s->transport_rolling()) {
- if (_operation == SelectionEndTrim)
- _editor->maybe_locate_with_edit_preroll( _editor->get_selection().time.end_frame());
- else
- s->request_locate (_editor->get_selection().time.start());
+ s->request_locate (_editor->get_selection().time.start());
}
}
/* just a click, no pointer movement.
*/
+ if (was_double_click()) {
+ if (UIConfiguration::instance().get_use_double_click_to_zoom_to_selection()) {
+ _editor->temporal_zoom_selection (Both);
+ return;
+ }
+ }
+
if (_operation == SelectionExtend) {
if (_time_selection_at_start) {
framepos_t pos = adjusted_current_frame (event, false);
}
newloc = new Location (
*_editor->session(), _editor->temp_location->start(), _editor->temp_location->end(), rangename, (Location::Flags) flags
- );
+ , _editor->get_grid_music_divisions (event->button.state));
_editor->session()->locations()->add (newloc, true);
XMLNode &after = _editor->session()->locations()->get_state();
, _cumulative_dx (0)
, _cumulative_dy (0)
, _was_selected (false)
+ , _copy (false)
{
DEBUG_TRACE (DEBUG::Drags, "New NoteDrag\n");
NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
Drag::start_grab (event);
+
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::CopyModifier)) {
+ _copy = true;
+ } else {
+ _copy = false;
+ }
+
setup_snap_delta (_region->source_beats_to_absolute_frames (_primary->note()->time ()));
if (!(_was_selected = _primary->selected())) {
}
void
-NoteDrag::motion (GdkEvent * event, bool)
+NoteDrag::motion (GdkEvent * event, bool first_move)
{
+ if (_copy && first_move) {
+ /* make copies of all the selected notes */
+ _primary = _region->copy_selection ();
+ }
+
/* Total change in x and y since the start of the drag */
frameoffset_t const dx = total_dx (event->button.state);
int8_t const dy = total_dy ();
int8_t note_delta = total_dy();
if (tdx || tdy) {
- _region->move_selection (tdx, tdy, note_delta);
+ if (_copy) {
+ _region->move_copies (tdx, tdy, note_delta);
+ } else {
+ _region->move_selection (tdx, tdy, note_delta);
+ }
/* the new note value may be the same as the old one, but we
* don't know what that means because the selection may have
}
}
} else {
- _region->note_dropped (_primary, total_dx (ev->button.state), total_dy());
+ _region->note_dropped (_primary, total_dx (ev->button.state), total_dy(), _copy);
}
}