13
0

modified fix from carl for region copy-moves-original-to-start bug; change verbose canvas cursor color to be more distinct and readable; fix naming issues with imported files containing ':'; make sure [N] channels count shows up for whole files in region list; fix #1575, a subtle and nasty bug; improve positioning of verbose canvas cursor for ruler drags (but has a wierd side effect

git-svn-id: svn://localhost/ardour2/trunk@1675 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2007-04-06 23:42:07 +00:00
parent facf616868
commit 2dd0b9321c
12 changed files with 147 additions and 85 deletions

View File

@ -42,7 +42,7 @@ cLocationRange 0.29 0.48 0.35 1.0
cLocationCDMarker 0.12 0.91 0.77 1.0
cLocationLoop 0.21 0.59 0.31 1.0
cLocationPunch 0.49 0.23 0.23 1.0
cVerboseCanvasCursor 0 0 0 0.74
cVerboseCanvasCursor 0.96 0.95 0.08 0.74
cRangeDragBarRect 0.59 0.59 0.59 0.78
cRangeDragBarRectFill 0.78 0.82 0.70 0.43
cRangeDragRect 0.59 0.59 0.59 0.78

View File

@ -323,8 +323,8 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
Selection::Operation op = Keyboard::selection_type (event->button.state);
bool press = (event->type == GDK_BUTTON_PRESS);
begin_reversible_command (_("select on click"));
// begin_reversible_command (_("select on click"));
switch (item_type) {
case RegionItem:
if (mouse_mode != MouseRange) {
@ -379,9 +379,9 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
break;
}
if (commit) {
commit_reversible_command ();
}
// if (commit) {
// commit_reversible_command ();
// }
}
bool
@ -3287,12 +3287,10 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
if (regionview_y_movement) {
/* moved to a different audio track. */
vector<RegionView*> new_selection;
list<RegionView*> new_selection;
new_selection = selection->regions.by_layer();
selection->clear_regions ();
for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end(); ++i) {
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
RegionView* rv = (*i);
@ -3334,15 +3332,37 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
c.disconnect ();
if (latest_regionview) {
selection->add (latest_regionview);
new_selection.push_back (latest_regionview);
}
if (drag_info.copy) {
// get rid of the copy
delete rv;
}
/* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
was selected in all of them, then removing it from the playlist will have removed all
trace of it from the selection (i.e. there were N regions selected, we removed 1,
but since its the same playlist for N tracks, all N tracks updated themselves, removed the
corresponding regionview, and the selection is now empty).
this could have invalidated any and all iterators into the region selection.
the heuristic we use here is: if the region selection is empty, break out of the loop
here. if the region selection is not empty, then restart the loop because we know that
we must have removed at least the region(view) we've just been working on as well as any
that we processed on previous iterations.
*/
if (selection->regions.empty()) {
break;
} else {
i = selection->regions.by_layer().begin();
}
}
selection->set (new_selection);
} else {
/* motion within a single track */

View File

@ -2831,8 +2831,9 @@ Editor::cut_copy_regions (CutCopyOp op)
case Copy:
if (!ar) break;
npl->add_region ((*x)->region(), (*x)->region()->position() - first_position);
/* copy region before adding, so we're not putting same object into two different playlists */
npl->add_region (RegionFactory::create ((*x)->region()), (*x)->region()->position() - first_position);
break;
case Clear:

View File

@ -21,6 +21,7 @@
#include <cmath>
#include <algorithm>
#include <string>
#include <sstream>
#include <pbd/basename.h>
@ -138,12 +139,13 @@ Editor::add_audio_region_to_region_display (boost::shared_ptr<AudioRegion> regio
if (region->source()->name()[0] == '/') { // external file
if (region->whole_file()) {
str = ".../";
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(region->source());
str = ".../";
if (afs) {
str += region_name_from_path (afs->path(), region->n_channels() > 1);
str = region_name_from_path (afs->path(), region->n_channels() > 1);
} else {
str += region->source()->name();
}
@ -158,6 +160,14 @@ Editor::add_audio_region_to_region_display (boost::shared_ptr<AudioRegion> regio
}
if (region->n_channels() > 1) {
std::stringstream foo;
foo << region->n_channels ();
str += " [";
str += foo.str();
str += ']';
}
if (missing_source) {
str += _(" (MISSING)");
}

View File

@ -260,12 +260,12 @@ Editor::ruler_mouse_motion (GdkEventMotion* ev)
/* need to use the correct x,y, the event lies */
time_canvas_event_box.get_window()->get_pointer (x, y, state);
track_canvas.c2w (x, y, wcx, wcy);
track_canvas.w2c (wcx, wcy, cx, cy);
nframes_t where = leftmost_frame + pixel_to_frame (x);
time_canvas.c2w (x, y, wcx, wcy);
time_canvas.w2c (wcx, wcy, cx, cy);
wcx = x;
nframes_t where = event_frame ((GdkEvent*) ev, &wcx, (double *) 0);
cx = wcx;
/// ripped from maybe_autoscroll, and adapted to work here
nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
@ -307,8 +307,7 @@ Editor::ruler_mouse_motion (GdkEventMotion* ev)
break;
}
if (cursor)
{
if (cursor) {
cursor->set_position (where);
if (cursor == edit_cursor) {

View File

@ -31,12 +31,16 @@ using namespace sigc;
RegionSelection::RegionSelection ()
{
RegionView::RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
_current_start = 0;
_current_end = 0;
}
RegionSelection::RegionSelection (const RegionSelection& other)
{
RegionView::RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
add (*i);
}
@ -44,8 +48,6 @@ RegionSelection::RegionSelection (const RegionSelection& other)
_current_end = other._current_end;
}
RegionSelection&
RegionSelection::operator= (const RegionSelection& other)
{
@ -86,8 +88,6 @@ RegionSelection::add (RegionView* rv)
return false;
}
rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
if (rv->region()->first_frame() < _current_start || empty()) {
_current_start = rv->region()->first_frame();
}

View File

@ -24,6 +24,7 @@
#include <gtkmm.h>
#include <gtkmm2ext/gtk_ui.h>
#include <pbd/stacktrace.h>
#include <ardour/playlist.h>
#include <ardour/audioregion.h>

View File

@ -81,6 +81,7 @@ class AudioFileSource : public AudioSource {
virtual void mark_capture_start (nframes_t) {}
virtual void mark_capture_end () {}
virtual void clear_capture_marks() {}
virtual bool one_of_several_channels () const { return false; }
virtual int update_header (nframes_t when, struct tm&, time_t) = 0;
virtual int flush_header () = 0;
@ -161,7 +162,7 @@ class AudioFileSource : public AudioSource {
virtual void set_timeline_position (int64_t pos);
virtual void set_header_timeline_position () = 0;
bool find (Glib::ustring& path, bool must_exist, bool& is_new);
bool find (Glib::ustring& path, bool must_exist, bool& is_new, uint16_t& chan);
bool removable() const;
bool writable() const { return _flags & Writable; }
};

View File

@ -56,6 +56,8 @@ class SndFileSource : public AudioFileSource {
bool set_destructive (bool yn);
bool one_of_several_channels () const;
static void setup_standard_crossfades (nframes_t sample_rate);
static const AudioFileSource::Flag default_writable_flags;

View File

@ -93,15 +93,17 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFo
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
/* _channel is set in set_state() */
/* _channel is set in set_state() or init() */
{
/* constructor used for existing internal-to-session files. file must exist */
if (set_state (node)) {
throw failed_constructor ();
}
string foo = _name;
if (init (_name, must_exist)) {
if (init (foo, must_exist)) {
throw failed_constructor ();
}
}
@ -136,7 +138,7 @@ AudioFileSource::init (ustring pathstr, bool must_exist)
_peaks_built = false;
file_is_new = false;
if (!find (pathstr, must_exist, is_new)) {
if (!find (pathstr, must_exist, is_new, _channel)) {
throw non_existent_source ();
}
@ -361,42 +363,13 @@ AudioFileSource::move_to_trash (const ustring& trash_dir_name)
}
bool
AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew)
AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t& chan)
{
ustring::size_type pos;
bool ret = false;
isnew = false;
/* i (paul) made a nasty design error by using ':' as a special character in
Ardour 0.99 .. this hack tries to make things sort of work.
*/
if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS)) {
/* its a real file, no problem */
} else {
if (must_exist) {
/* older session using file:channel syntax */
warning << string_compose (_("This older session references an embedded\n\
non-mono audio file:\n\n%1\n\n \
The session file may be edited or the file must be removed before it can be used."),
short_path (pathstr, 48))
<< endmsg;
return false;
} else {
/* new derived file (e.g. for timefx) being created in a newer session */
}
}
}
if (pathstr[0] != '/') {
/* non-absolute pathname: find pathstr in search path */
@ -421,12 +394,60 @@ The session file may be edited or the file must be removed before it can be used
if (fullpath[fullpath.length()-1] != '/') {
fullpath += '/';
}
fullpath += pathstr;
/* i (paul) made a nasty design error by using ':' as a special character in
Ardour 0.99 .. this hack tries to make things sort of work.
*/
if (access (fullpath.c_str(), R_OK) == 0) {
keeppath = fullpath;
++cnt;
}
if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
/* its a real file, no problem */
keeppath = fullpath;
++cnt;
} else {
if (must_exist) {
/* might be an older session using file:channel syntax. see if the version
without the :suffix exists
*/
ustring shorter = pathstr.substr (0, pos);
fullpath = *i;
if (fullpath[fullpath.length()-1] != '/') {
fullpath += '/';
}
fullpath += shorter;
if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
chan = atoi (pathstr.substr (pos+1));
pathstr = shorter;
keeppath = fullpath;
++cnt;
}
} else {
/* new derived file (e.g. for timefx) being created in a newer session */
}
}
} else {
if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
keeppath = fullpath;
++cnt;
}
}
}
if (cnt > 1) {
@ -443,7 +464,7 @@ The session file may be edited or the file must be removed before it can be used
isnew = true;
}
}
_name = pathstr;
_path = keeppath;
ret = true;
@ -451,18 +472,31 @@ The session file may be edited or the file must be removed before it can be used
} else {
/* external files and/or very very old style sessions include full paths */
/* ugh, handle ':' situation */
if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
ustring shorter = pathstr.substr (0, pos);
if (Glib::file_test (shorter, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
chan = atoi (pathstr.substr (pos+1));
pathstr = shorter;
}
}
_path = pathstr;
if (is_embedded()) {
_name = pathstr;
} else {
_name = pathstr.substr (pathstr.find_last_of ('/') + 1);
}
if (access (_path.c_str(), R_OK) != 0) {
if (!Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
/* file does not exist or we cannot read it */
if (must_exist) {
error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
goto out;
@ -483,6 +517,7 @@ The session file may be edited or the file must be removed before it can be used
/* already exists */
ret = true;
}
}

View File

@ -653,10 +653,7 @@ Multi2dPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nfram
}
pan = left * gain_coeff;
for (; n < nframes; ++n) {
dst[n] += src[n] * pan;
}
Session::mix_buffers_with_gain(dst+n,src+n,nframes-n,pan);
} else {
@ -666,20 +663,10 @@ Multi2dPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nfram
if ((pan *= gain_coeff) != 1.0f) {
if (pan != 0.0f) {
for (nframes_t n = 0; n < nframes; ++n) {
dst[n] += src[n] * pan;
}
Session::mix_buffers_with_gain(dst,src,nframes,pan);
}
} else {
for (nframes_t n = 0; n < nframes; ++n) {
dst[n] += src[n];
}
Session::mix_buffers_no_gain(dst,src,nframes);
}
#endif
#ifdef CAN_INTERP

View File

@ -894,3 +894,9 @@ SndFileSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& e
ret |= (uint32_t) binfo->time_reference_low;
return ret;
}
bool
SndFileSource::one_of_several_channels () const
{
return _info.channels > 1;
}