#include "transform_dialog.h"
#include "ui_config.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace std;
using namespace ARDOUR;
}
void
-Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int32_t& sub_num)
+Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int32_t sub_num)
{
bool frozen = false;
} else {
loc->set_end (max_framepos);
}
+ if (loc->is_session_range()) {
+ _session->set_end_is_free (false);
+ }
}
if (!in_command) {
begin_reversible_command (_("nudge location forward"));
} else {
loc->set_end (loc->length());
}
+ if (loc->is_session_range()) {
+ _session->set_end_is_free (false);
+ }
}
if (!in_command) {
begin_reversible_command (_("nudge location forward"));
commit_reversible_command ();
}
+
+ _session->set_end_is_free (false);
}
void
}
}
+
struct AutomationRecord {
AutomationRecord () : state (0) , line(NULL) {}
AutomationRecord (XMLNode* s, const AutomationLine* l) : state (s) , line (l) {}
const AutomationLine* line; ///< line this came from
boost::shared_ptr<Evoral::ControlList> copy; ///< copied events for the cut buffer
};
-
+struct PointsSelectionPositionSorter {
+ bool operator() (ControlPoint* a, ControlPoint* b) {
+ return (*(a->model()))->when < (*(b->model()))->when;
+ }
+};
/** Cut, copy or clear selected automation points.
* @param op Operation (Cut, Copy or Clear)
*/
typedef std::map<boost::shared_ptr<AutomationList>, AutomationRecord> Lists;
Lists lists;
+ /* user could select points in any order */
+ selection->points.sort(PointsSelectionPositionSorter ());
+
/* Go through all selected points, making an AutomationRecord for each distinct AutomationList */
- for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
- const AutomationLine& line = (*i)->line();
+ for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
+ const AutomationLine& line = (*sel_point)->line();
const boost::shared_ptr<AutomationList> al = line.the_list();
if (lists.find (al) == lists.end ()) {
/* We haven't seen this list yet, so make a record for it. This includes
/* Add all selected points to the relevant copy ControlLists */
framepos_t start = std::numeric_limits<framepos_t>::max();
- for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
- boost::shared_ptr<AutomationList> al = (*i)->line().the_list();
- AutomationList::const_iterator j = (*i)->model();
+ for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
+ boost::shared_ptr<AutomationList> al = (*sel_point)->line().the_list();
+ AutomationList::const_iterator ctrl_evt = (*sel_point)->model ();
- lists[al].copy->fast_simple_add ((*j)->when, (*j)->value);
+ lists[al].copy->fast_simple_add ((*ctrl_evt)->when, (*ctrl_evt)->value);
if (midi) {
/* Update earliest MIDI start time in beats */
- earliest = std::min(earliest, Evoral::Beats((*j)->when));
+ earliest = std::min(earliest, Evoral::Beats((*ctrl_evt)->when));
} else {
/* Update earliest session start time in frames */
- start = std::min(start, (*i)->line().session_position(j));
+ start = std::min(start, (*sel_point)->line().session_position(ctrl_evt));
}
}
start time, so relative ordering between points is preserved
when copying from several lists and the paste starts at the
earliest copied piece of data. */
- for (AutomationList::iterator j = i->second.copy->begin(); j != i->second.copy->end(); ++j) {
- (*j)->when -= line_offset;
+ boost::shared_ptr<Evoral::ControlList> &al_cpy = i->second.copy;
+ for (AutomationList::iterator ctrl_evt = al_cpy->begin(); ctrl_evt != al_cpy->end(); ++ctrl_evt) {
+ (*ctrl_evt)->when -= line_offset;
}
/* And add it to the cut buffer */
- cut_buffer->add (i->second.copy);
+ cut_buffer->add (al_cpy);
}
}
}
/* Remove each selected point from its AutomationList */
- for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
- boost::shared_ptr<AutomationList> al = (*i)->line().the_list();
- al->erase ((*i)->model ());
+ for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
+ AutomationLine& line = (*sel_point)->line ();
+ boost::shared_ptr<AutomationList> al = line.the_list();
+
+ bool erase = true;
+
+ if (dynamic_cast<AudioRegionGainLine*> (&line)) {
+ /* removing of first and last gain point in region gain lines is prohibited*/
+ if (line.is_last_point (*(*sel_point)) || line.is_first_point (*(*sel_point))) {
+ erase = false;
+ }
+ }
+
+ if(erase) {
+ al->erase ((*sel_point)->model ());
+ }
}
/* Thaw the lists and add undo records for them */
}
void
-Editor::paste_internal (framepos_t position, float times, const int32_t& sub_num)
+Editor::paste_internal (framepos_t position, float times, const int32_t sub_num)
{
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("apparent paste position is %1\n", position));
Location* loc;
if ((loc = _session->locations()->session_range_location()) == 0) {
- _session->set_session_extents ( start, end ); // this will create a new session range; no need for UNDO
+ _session->set_session_extents (start, end); // this will create a new session range; no need for UNDO
} else {
XMLNode &before = loc->get_state();
- _session->set_session_extents ( start, end );
+ _session->set_session_extents (start, end);
XMLNode &after = loc->get_state();
commit_reversible_command ();
}
+
+ _session->set_end_is_free (false);
}
void
} else if (t.frame() == start) {
_session->tempo_map().change_existing_tempo_at (start, beats_per_minute, t.note_type());
} else {
- _session->tempo_map().add_tempo (Tempo (beats_per_minute, t.note_type()), 0.0, start, TempoSection::Constant, AudioTime);
+ const Tempo tempo (beats_per_minute, t.note_type());
+ _session->tempo_map().add_tempo (tempo, 0.0, start, TempoSection::Constant, AudioTime);
}
XMLNode& after (_session->tempo_map().get_state());
{
Timers::TimerSuspender t;
label->set_text (string_compose ("Copying %1, %2 of %3", name, n, total));
- Gtkmm2ext::UI::instance()->flush_pending ();
+ Gtkmm2ext::UI::instance()->flush_pending (1);
}
void
*/
Timers::TimerSuspender t;
- Gtkmm2ext::UI::instance()->flush_pending ();
+ Gtkmm2ext::UI::instance()->flush_pending (3);
cerr << " Do it\n";