modified fix from carl for region copy-moves-original-to-start bug; change verbose...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 6 Apr 2007 23:42:07 +0000 (23:42 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 6 Apr 2007 23:42:07 +0000 (23:42 +0000)
git-svn-id: svn://localhost/ardour2/trunk@1675 d708f5d6-7413-0410-9779-e7cbd77b26cf

12 files changed:
gtk2_ardour/ardour.colors
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_region_list.cc
gtk2_ardour/editor_rulers.cc
gtk2_ardour/region_selection.cc
gtk2_ardour/region_view.cc
libs/ardour/ardour/audiofilesource.h
libs/ardour/ardour/sndfilesource.h
libs/ardour/audiofilesource.cc
libs/ardour/panner.cc
libs/ardour/sndfilesource.cc

index b68d270e6e63eb46cc2b9c8ef3bdcfe9cdcd3dd6..fa89646e09856122cac8f13186d98dbbeb08f17f 100644 (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
index b5c8042672cecfb434f8a4f829685ffb4d3113cf..39680980d6e8f19fa6ba80ee668405c2b7e15bf3 100644 (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 */
index f8e6f41a9e41ea0311b6d4c4b655eac35c4445de..f80ec708ebee70178fc003a5c0493ab44989ce7c 100644 (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:
index 56196623eddd5897549956eca5be7953b8b1bb9c..df23ac503cbc2dff44cb3056324461dc2b8ba68d 100644 (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)");
                }
index 6338993ae2276652d70466155c275de0925946f0..992d67b9be6a6f5407e6cf3df71f7c75cb3c9d5e 100644 (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) {
index 34810691f5c33e3f1cc678b9dc056daa0f6f55bc..7ac7763773a6848aa90d871d4e0df8d09de27ab0 100644 (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();
        }
index 3e6921aab9efe87da53bd891cad9586dbb5f21f3..7a8f9b5d6ae03904d88907a3eda72b3045bb79c8 100644 (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>
index 6bc9ec42075f1487936a98e068005f4df41e5f4a..dce06c1ca03b2e9817966ab9ae151108518b7127 100644 (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; }
 };
index 2fc3872887644b3dfad3c7763f37af8bacdd4a8f..916e9da49ec15f6b5d4ed7c8cecd705180b4dc90 100644 (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;
 
index 929cfc808370f666b102b680144a2abc58720125..3a02c4c4b0ccf6416a766283e14833692c75218b 100644 (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) {
 
-                       /* file does not exist or we cannot read it */
+               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;
+
                }
        }
        
index deb131e6fcd005c2c8a8252e3b81fbbc45b81831..563d4e90d41da2ebca6584bfde602a4f85e4252f 100644 (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
index 8aecbc3cdc4cc41bae78ca357f594f5c16b5b2ec..24647030ab702da6d22822da37031d5e418b0fdb 100644 (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;
+}