fixes for desirable playback when using seamless looping.
[ardour.git] / libs / ardour / location.cc
index 09e5001eea78aee37da1d6d2926494584fae5fed..2e9125126b4c69ea2e617abebdeb489a87a95e53 100644 (file)
@@ -25,6 +25,7 @@
 #include <ctime>
 #include <list>
 
+#include "pbd/convert.h"
 #include "pbd/stl_delete.h"
 #include "pbd/xml++.h"
 #include "pbd/enumwriter.h"
@@ -37,8 +38,6 @@
 
 #include "i18n.h"
 
-#define SUFFIX_MAX 32
-
 using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
@@ -221,7 +220,12 @@ Location::set_start (framepos_t s, bool force, bool allow_bbt_recompute)
                assert (_end >= 0);
 
                return 0;
-       }
+       } else if (!force) {
+                /* range locations must exceed a minimum duration */
+                if (_end - s < Config->get_range_location_minimum()) {
+                        return -1;
+                }
+        }
 
        if (s != _start) {
 
@@ -247,7 +251,7 @@ Location::set_start (framepos_t s, bool force, bool allow_bbt_recompute)
 
 /** Set end position.
  *  @param s New end.
- *  @param force true to force setting, even if the given new start is after the current end.
+ *  @param force true to force setting, even if the given new end is before the current start.
  *  @param allow_bbt_recompute True to recompute BBT end time from the new given end time.
  */
 int
@@ -284,6 +288,11 @@ Location::set_end (framepos_t e, bool force, bool allow_bbt_recompute)
                assert (_end >= 0);
 
                return 0;
+        } else if (!force) {
+                /* range locations must exceed a minimum duration */
+                if (e - _start < Config->get_range_location_minimum()) {
+                        return -1;
+                }
        }
 
        if (e != _end) {
@@ -341,6 +350,11 @@ Location::set (framepos_t s, framepos_t e, bool allow_bbt_recompute)
                assert (_end >= 0);
 
        } else {
+
+                /* range locations must exceed a minimum duration */
+                if (e - s < Config->get_range_location_minimum()) {
+                        return -1;
+                }
                 
                 if (s != _start) {
 
@@ -783,33 +797,55 @@ int
 Locations::next_available_name(string& result,string base)
 {
        LocationList::iterator i;
-       Location* location;
-       string temp;
        string::size_type l;
        int suffix;
        char buf[32];
-       bool available[SUFFIX_MAX+1];
+        std::map<uint32_t,bool> taken;
+        uint32_t n;
 
        result = base;
-       for (int k=1; k<SUFFIX_MAX; k++) {
-               available[k] = true;
-       }
-       l = base.length();
-       for (i = locations.begin(); i != locations.end(); ++i) {
-               location =* i;
-               temp = location->name();
-               if (l && !temp.find(base,0)) {
-                       suffix = atoi(temp.substr(l,3).c_str());
-                       if (suffix) available[suffix] = false;
-               }
-       }
-       for (int k=1; k<=SUFFIX_MAX; k++) {
-               if (available[k]) {
-                       snprintf (buf, 31, "%d", k);
-                       result += buf;
-                       return 1;
-               }
-       }
+        l = base.length();
+
+        if (!base.empty()) {
+                
+                /* find all existing names that match "base", and store
+                   the numeric part of them (if any) in the map "taken"
+                */
+
+                for (i = locations.begin(); i != locations.end(); ++i) {
+
+                        const string& temp ((*i)->name());
+                        
+                        if (!temp.find (base,0)) {
+
+                                if ((suffix = atoi (temp.substr(l,3))) != 0) {
+                                        taken.insert (make_pair (suffix,true));
+                                }
+                        }
+                }
+        }
+
+        /* Now search for an un-used suffix to add to "base". This
+           will find "holes" in the numbering sequence when a location
+           was deleted.
+
+           This must start at 1, both for human-numbering reasons
+           and also because the call to atoi() above would return 
+           zero if there is no recognizable numeric suffix, causing
+           "base 0" not to be inserted into the "taken" map.
+        */
+
+        n = 1; 
+
+        while (n < UINT32_MAX) {
+                if (taken.find (n) == taken.end()) {
+                        snprintf (buf, sizeof(buf), "%d", n);
+                        result += buf;
+                        return 1;
+                }
+                ++n;
+        }
+                
        return 0;
 }