fix ordering of cut/copied regions when pasting; ctrl-click now does the right thing the first time its used on a region; fix missing click and other dubious behaviour in new sessions caused by not connecting to Configuration::ParameterChanged in the new session constructor
git-svn-id: svn://localhost/ardour2/trunk@1331 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
d3071f84e5
commit
762d2ae936
|
@ -266,7 +266,7 @@ ActionManager::toggle_config_state (const char* group, const char* action, bool
|
|||
|
||||
if (tact) {
|
||||
bool x = (Config->*get)();
|
||||
|
||||
|
||||
if (x != tact->get_active()) {
|
||||
(Config->*set) (!x);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <pbd/convert.h>
|
||||
#include <pbd/stacktrace.h>
|
||||
|
||||
#include <gtkmm2ext/utils.h>
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <pbd/convert.h>
|
||||
#include <pbd/error.h>
|
||||
#include <pbd/stacktrace.h>
|
||||
#include <pbd/memento_command.h>
|
||||
|
||||
#include <gtkmm/image.h>
|
||||
|
@ -3030,7 +3031,6 @@ Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((pl = ds->playlist()) != 0) {
|
||||
pl->get_equivalent_regions (basis->region(), results);
|
||||
}
|
||||
|
@ -3052,6 +3052,10 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (press) {
|
||||
button_release_can_deselect = false;
|
||||
}
|
||||
|
||||
if (op == Selection::Toggle || op == Selection::Set) {
|
||||
|
||||
mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click),
|
||||
|
@ -4292,3 +4296,17 @@ Editor::idle_visual_changer ()
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct EditorOrderTimeAxisSorter {
|
||||
bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
|
||||
return a->order < b->order;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
Editor::sort_track_selection ()
|
||||
{
|
||||
EditorOrderTimeAxisSorter cmp;
|
||||
selection->tracks.sort (cmp);
|
||||
}
|
||||
|
||||
|
|
|
@ -419,6 +419,8 @@ class Editor : public PublicEditor
|
|||
CrossfadeView* clicked_crossfadeview;
|
||||
ControlPoint* clicked_control_point;
|
||||
|
||||
void sort_track_selection ();
|
||||
|
||||
void get_relevant_audio_tracks (std::set<AudioTimeAxisView*>& relevant_tracks);
|
||||
void mapover_audio_tracks (sigc::slot<void,AudioTimeAxisView&,uint32_t> sl);
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ Editor::kbd_do_split (GdkEvent* ev)
|
|||
nframes_t where = event_frame (ev);
|
||||
|
||||
if (entered_regionview) {
|
||||
if (selection->regions.find (entered_regionview) != selection->regions.end()) {
|
||||
if (selection->regions.contains (entered_regionview)) {
|
||||
split_regions_at (where, selection->regions);
|
||||
} else {
|
||||
RegionSelection s;
|
||||
|
|
|
@ -77,6 +77,9 @@ Editor::show_editor_mixer (bool yn)
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
AudioTimeAxisView* atv;
|
||||
|
||||
|
|
|
@ -1351,27 +1351,20 @@ Editor::select_all_within (nframes_t start, nframes_t end, double top, double bo
|
|||
(*iter)->get_selectables (start, end, top, bot, touched);
|
||||
}
|
||||
|
||||
cerr << "select all within found " << touched.size() << endl;
|
||||
|
||||
begin_reversible_command (_("select all within"));
|
||||
switch (op) {
|
||||
case Selection::Add:
|
||||
case Selection::Toggle:
|
||||
cerr << "toggle\n";
|
||||
selection->add (touched);
|
||||
break;
|
||||
case Selection::Set:
|
||||
cerr << "set\n";
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
cerr << "extend\n";
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
|
||||
cerr << "selection now has " << selection->points.size() << endl;
|
||||
|
||||
commit_reversible_command ();
|
||||
return !touched.empty();
|
||||
}
|
||||
|
@ -2166,6 +2159,8 @@ Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& n
|
|||
nframes_t start = selection->time[clicked_selection].start;
|
||||
nframes_t end = selection->time[clicked_selection].end;
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
|
||||
boost::shared_ptr<AudioRegion> current;
|
||||
|
@ -2227,6 +2222,8 @@ Editor::separate_region_from_selection ()
|
|||
|
||||
boost::shared_ptr<Playlist> playlist;
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
|
||||
AudioTimeAxisView* atv;
|
||||
|
@ -2333,6 +2330,8 @@ Editor::crop_region_to_selection ()
|
|||
|
||||
} else {
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
|
||||
AudioTimeAxisView* atv;
|
||||
|
@ -2949,17 +2948,33 @@ struct lt_playlist {
|
|||
}
|
||||
};
|
||||
|
||||
struct PlaylistMapping {
|
||||
TimeAxisView* tv;
|
||||
boost::shared_ptr<AudioPlaylist> pl;
|
||||
|
||||
PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
|
||||
};
|
||||
|
||||
void
|
||||
Editor::cut_copy_regions (CutCopyOp op)
|
||||
{
|
||||
typedef std::map<boost::shared_ptr<AudioPlaylist>,boost::shared_ptr<AudioPlaylist> > PlaylistMapping;
|
||||
PlaylistMapping pmap;
|
||||
nframes_t first_position = max_frames;
|
||||
/* we can't use a std::map here because the ordering is important, and we can't trivially sort
|
||||
a map when we want ordered access to both elements. i think.
|
||||
*/
|
||||
|
||||
vector<PlaylistMapping> pmap;
|
||||
|
||||
nframes_t first_position = max_frames;
|
||||
|
||||
set<PlaylistState, lt_playlist> freezelist;
|
||||
pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
|
||||
|
||||
/* get ordering correct before we cut/copy */
|
||||
|
||||
selection->regions.sort_by_position_and_track ();
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
|
||||
first_position = min ((*x)->region()->position(), first_position);
|
||||
|
||||
if (op == Cut || op == Clear) {
|
||||
|
@ -2972,66 +2987,94 @@ Editor::cut_copy_regions (CutCopyOp op)
|
|||
before.before = &pl->get_state();
|
||||
|
||||
insert_result = freezelist.insert (before);
|
||||
|
||||
|
||||
if (insert_result.second) {
|
||||
pl->freeze ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeAxisView* tv = &(*x)->get_trackview();
|
||||
vector<PlaylistMapping>::iterator z;
|
||||
|
||||
for (z = pmap.begin(); z != pmap.end(); ++z) {
|
||||
if ((*z).tv == tv) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (z == pmap.end()) {
|
||||
pmap.push_back (PlaylistMapping (tv));
|
||||
}
|
||||
}
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
|
||||
|
||||
boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
|
||||
|
||||
if (!pl) {
|
||||
/* impossible, but this handles it for the future */
|
||||
continue;
|
||||
}
|
||||
|
||||
TimeAxisView& tv = (*x)->get_trackview();
|
||||
boost::shared_ptr<AudioPlaylist> npl;
|
||||
RegionSelection::iterator tmp;
|
||||
|
||||
tmp = x;
|
||||
++tmp;
|
||||
|
||||
if (pl) {
|
||||
|
||||
PlaylistMapping::iterator pi = pmap.find (pl);
|
||||
vector<PlaylistMapping>::iterator z;
|
||||
|
||||
for (z = pmap.begin(); z != pmap.end(); ++z) {
|
||||
if ((*z).tv == &tv) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert (z != pmap.end());
|
||||
|
||||
if (!(*z).pl) {
|
||||
npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
|
||||
npl->freeze();
|
||||
(*z).pl = npl;
|
||||
} else {
|
||||
npl = (*z).pl;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
|
||||
|
||||
switch (op) {
|
||||
case Cut:
|
||||
if (!ar) break;
|
||||
|
||||
if (pi == pmap.end()) {
|
||||
npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
|
||||
npl->freeze();
|
||||
pmap[pl] = npl;
|
||||
} else {
|
||||
npl = pi->second;
|
||||
}
|
||||
|
||||
// FIXME
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
|
||||
switch (op) {
|
||||
case Cut:
|
||||
if (!ar) break;
|
||||
|
||||
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
|
||||
pl->remove_region (((*x)->region()));
|
||||
break;
|
||||
|
||||
case Copy:
|
||||
if (!ar) break;
|
||||
|
||||
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
|
||||
break;
|
||||
|
||||
case Clear:
|
||||
pl->remove_region (((*x)->region()));
|
||||
break;
|
||||
}
|
||||
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
|
||||
pl->remove_region (((*x)->region()));
|
||||
break;
|
||||
|
||||
case Copy:
|
||||
if (!ar) break;
|
||||
|
||||
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
|
||||
break;
|
||||
|
||||
case Clear:
|
||||
pl->remove_region (((*x)->region()));
|
||||
break;
|
||||
}
|
||||
|
||||
x = tmp;
|
||||
}
|
||||
|
||||
|
||||
list<boost::shared_ptr<Playlist> > foo;
|
||||
|
||||
for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
|
||||
foo.push_back (i->second);
|
||||
|
||||
/* the pmap is in the same order as the tracks in which selected regions occured */
|
||||
|
||||
for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
|
||||
(*i).pl->thaw();
|
||||
foo.push_back ((*i).pl);
|
||||
}
|
||||
|
||||
|
||||
if (!foo.empty()) {
|
||||
cut_buffer->set (foo);
|
||||
}
|
||||
|
@ -3095,15 +3138,19 @@ Editor::paste_internal (nframes_t position, float times)
|
|||
TrackSelection::iterator i;
|
||||
size_t nth;
|
||||
|
||||
/* get everything in the correct order */
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
|
||||
|
||||
|
||||
/* undo/redo is handled by individual tracks */
|
||||
|
||||
if ((*i)->paste (position, times, *cut_buffer, nth)) {
|
||||
commit = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (commit) {
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
@ -3129,6 +3176,8 @@ Editor::paste_named_selection (float times)
|
|||
chunk = ns->playlists.begin();
|
||||
|
||||
begin_reversible_command (_("paste chunk"));
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
|
||||
|
||||
|
@ -3241,8 +3290,6 @@ Editor::reset_point_selection ()
|
|||
{
|
||||
/* reset all selected points to the relevant default value */
|
||||
|
||||
cerr << "point selection has " << selection->points.size() << " entries\n";
|
||||
|
||||
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
|
||||
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
|
||||
|
|
|
@ -22,22 +22,13 @@
|
|||
|
||||
#include "region_view.h"
|
||||
#include "region_selection.h"
|
||||
#include "time_axis_view.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
using namespace sigc;
|
||||
|
||||
|
||||
bool
|
||||
RegionComparator::operator() (const RegionView* a, const RegionView* b) const
|
||||
{
|
||||
if (a == b) {
|
||||
return false;
|
||||
} else {
|
||||
return a < b;
|
||||
}
|
||||
}
|
||||
|
||||
RegionSelection::RegionSelection ()
|
||||
{
|
||||
_current_start = 0;
|
||||
|
@ -46,9 +37,8 @@ RegionSelection::RegionSelection ()
|
|||
|
||||
RegionSelection::RegionSelection (const RegionSelection& other)
|
||||
{
|
||||
|
||||
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
|
||||
add (*i, false);
|
||||
add (*i);
|
||||
}
|
||||
_current_start = other._current_start;
|
||||
_current_end = other._current_end;
|
||||
|
@ -64,7 +54,7 @@ RegionSelection::operator= (const RegionSelection& other)
|
|||
clear_all();
|
||||
|
||||
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
|
||||
add (*i, false);
|
||||
add (*i);
|
||||
}
|
||||
|
||||
_current_start = other._current_start;
|
||||
|
@ -85,11 +75,11 @@ RegionSelection::clear_all()
|
|||
|
||||
bool RegionSelection::contains (RegionView* rv)
|
||||
{
|
||||
return this->find (rv) != end();
|
||||
return find (begin(), end(), rv) != end();
|
||||
}
|
||||
|
||||
void
|
||||
RegionSelection::add (RegionView* rv, bool dosort)
|
||||
RegionSelection::add (RegionView* rv)
|
||||
{
|
||||
if (contains (rv)) {
|
||||
/* we already have it */
|
||||
|
@ -106,11 +96,11 @@ RegionSelection::add (RegionView* rv, bool dosort)
|
|||
_current_end = rv->region()->last_frame();
|
||||
}
|
||||
|
||||
insert (rv);
|
||||
push_back (rv);
|
||||
|
||||
// add to layer sorted list
|
||||
|
||||
add_to_layer (rv);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -124,7 +114,7 @@ RegionSelection::remove (RegionView* rv)
|
|||
{
|
||||
RegionSelection::iterator i;
|
||||
|
||||
if ((i = this->find (rv)) != end()) {
|
||||
if ((i = find (begin(), end(), rv)) != end()) {
|
||||
|
||||
erase (i);
|
||||
|
||||
|
@ -198,7 +188,7 @@ RegionSelection::add_to_layer (RegionView * rv)
|
|||
}
|
||||
|
||||
struct RegionSortByTime {
|
||||
bool operator() (const RegionView* a, const RegionView* b) {
|
||||
bool operator() (const RegionView* a, const RegionView* b) const {
|
||||
return a->region()->position() < b->region()->position();
|
||||
}
|
||||
};
|
||||
|
@ -217,3 +207,37 @@ RegionSelection::by_position (list<RegionView*>& foo) const
|
|||
foo.sort (sorter);
|
||||
return;
|
||||
}
|
||||
|
||||
struct RegionSortByTrack {
|
||||
bool operator() (const RegionView* a, const RegionView* b) const {
|
||||
|
||||
/* really, track and position */
|
||||
|
||||
if (a->get_trackview().order == b->get_trackview().order) {
|
||||
return a->region()->position() < b->region()->position();
|
||||
} else {
|
||||
return a->get_trackview().order < b->get_trackview().order;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
RegionSelection::by_track (list<RegionView*>& foo) const
|
||||
{
|
||||
list<RegionView*>::const_iterator i;
|
||||
RegionSortByTrack sorter;
|
||||
|
||||
for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
|
||||
foo.push_back (*i);
|
||||
}
|
||||
|
||||
foo.sort (sorter);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
RegionSelection::sort_by_position_and_track ()
|
||||
{
|
||||
RegionSortByTrack sorter;
|
||||
sort (sorter);
|
||||
}
|
||||
|
|
|
@ -29,11 +29,7 @@ using std::set;
|
|||
|
||||
class RegionView;
|
||||
|
||||
struct RegionComparator {
|
||||
bool operator() (const RegionView* a, const RegionView* b) const;
|
||||
};
|
||||
|
||||
class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::trackable
|
||||
class RegionSelection : public std::list<RegionView*>, public sigc::trackable
|
||||
{
|
||||
public:
|
||||
RegionSelection();
|
||||
|
@ -41,9 +37,10 @@ class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::
|
|||
|
||||
RegionSelection& operator= (const RegionSelection&);
|
||||
|
||||
void add (RegionView*, bool dosort = true);
|
||||
void add (RegionView*);
|
||||
bool remove (RegionView*);
|
||||
bool contains (RegionView*);
|
||||
void sort_by_position_and_track ();
|
||||
|
||||
void clear_all();
|
||||
|
||||
|
@ -51,14 +48,15 @@ class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::
|
|||
return _current_start;
|
||||
}
|
||||
|
||||
/* collides with list<>::end */
|
||||
/* "end" collides with list<>::end */
|
||||
|
||||
nframes_t end_frame () const {
|
||||
return _current_end;
|
||||
}
|
||||
|
||||
const list<RegionView *> & by_layer() const { return _bylayer; }
|
||||
void by_position (list<RegionView*>&) const;
|
||||
const std::list<RegionView *>& by_layer() const { return _bylayer; }
|
||||
void by_position (std::list<RegionView*>&) const;
|
||||
void by_track (std::list<RegionView*>&) const;
|
||||
|
||||
private:
|
||||
void remove_it (RegionView*);
|
||||
|
|
|
@ -232,6 +232,11 @@ class TimeAxisViewItem : public Selectable
|
|||
ArdourCanvas::Text* get_name_text();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the time axis that this item is upon
|
||||
*/
|
||||
TimeAxisView& get_trackview() const { return trackview; }
|
||||
|
||||
/**
|
||||
* Sets the samples per unit of this item.
|
||||
* this item is used to determine the relative visual size and position of this item
|
||||
|
|
|
@ -27,9 +27,13 @@ class ConfigVariableBase {
|
|||
virtual void add_to_node (XMLNode& node) = 0;
|
||||
virtual bool set_from_node (const XMLNode& node, Owner owner) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
Owner _owner;
|
||||
|
||||
void notify ();
|
||||
void miss ();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
|
@ -41,10 +45,12 @@ class ConfigVariable : public ConfigVariableBase
|
|||
|
||||
virtual bool set (T val, Owner owner) {
|
||||
if (val == value) {
|
||||
miss ();
|
||||
return false;
|
||||
}
|
||||
value = val;
|
||||
_owner = (ConfigVariableBase::Owner)(_owner |owner);
|
||||
notify ();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -317,3 +317,16 @@ Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
|
|||
#undef CONFIG_VARIABLE
|
||||
#undef CONFIG_VARIABLE_SPECIAL
|
||||
}
|
||||
|
||||
void
|
||||
ConfigVariableBase::notify ()
|
||||
{
|
||||
// placeholder for any debugging desired when a config variable is modified
|
||||
}
|
||||
|
||||
void
|
||||
ConfigVariableBase::miss ()
|
||||
{
|
||||
// placeholder for any debugging desired when a config variable
|
||||
// is set but to the same value as it already has
|
||||
}
|
||||
|
|
|
@ -368,7 +368,6 @@ Session::Session (AudioEngine &eng,
|
|||
if (master_out_channels) {
|
||||
shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
|
||||
r->set_remote_control_id (control_id);
|
||||
cerr << "master bus has remote control ID " << r->remote_control_id() << endl;
|
||||
|
||||
rl.push_back (r);
|
||||
} else {
|
||||
|
@ -396,6 +395,8 @@ Session::Session (AudioEngine &eng,
|
|||
|
||||
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
|
||||
|
||||
Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
|
||||
|
||||
if (was_dirty) {
|
||||
DirtyChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue