interpolation.cc/.h: Spline-Bugfixes: Crash bug at tempos close to 0, wrong calculati...
[ardour.git] / libs / ardour / location.cc
index 093c6cf8fcd98d3aa0d0f1e2fc6ef9c37f5bb2fd..b66d0f3942606ad52982f717e34644bdb0de7878 100644 (file)
 #include <ctime>
 #include <sigc++/bind.h>
 
-#include <pbd/stl_delete.h>
-#include <pbd/xml++.h>
-#include <pbd/enumwriter.h>
+#include "pbd/stl_delete.h"
+#include "pbd/xml++.h"
+#include "pbd/enumwriter.h"
 
-#include <ardour/location.h>
-#include <ardour/session.h>
-#include <ardour/audiofilesource.h>
+#include "ardour/location.h"
+#include "ardour/session.h"
+#include "ardour/audiofilesource.h"
 
 #include "i18n.h"
 
@@ -43,7 +43,8 @@ using namespace sigc;
 using namespace PBD;
 
 Location::Location (const Location& other)
-       : _name (other._name),
+       : StatefulDestructible(),
+         _name (other._name),
          _start (other._start),
          _end (other._end),
          _flags (other._flags)
@@ -52,6 +53,10 @@ Location::Location (const Location& other)
 
        _flags = Flags (_flags & ~IsStart);
        _flags = Flags (_flags & ~IsEnd);
+
+       /* copy is not locked even if original was */
+
+       _locked = false;
 }
 
 Location::Location (const XMLNode& node)
@@ -73,14 +78,22 @@ Location::operator= (const Location& other)
        _end = other._end;
        _flags = other._flags;
 
+       /* copy is not locked even if original was */
+
+       _locked = false;
+
        /* "changed" not emitted on purpose */
        
        return this;
 }
 
 int
-Location::set_start (nframes_t s)
+Location::set_start (nframes64_t s)
 {
+       if (_locked) {
+               return -1;
+       }
+
        if (is_mark()) {
                if (_start != s) {
 
@@ -88,6 +101,7 @@ Location::set_start (nframes_t s)
                        _end = s;
 
                        start_changed(this); /* EMIT SIGNAL */
+                       end_changed(this); /* EMIT SIGNAL */
 
                        if ( is_start() ) {
 
@@ -115,13 +129,27 @@ Location::set_start (nframes_t s)
 }
 
 int
-Location::set_end (nframes_t e)
+Location::set_end (nframes64_t e)
 {
+       if (_locked) {
+               return -1;
+       }
+
        if (is_mark()) {
                if (_start != e) {
                        _start = e;
                        _end = e;
+                       start_changed(this); /* EMIT SIGNAL */
                        end_changed(this); /* EMIT SIGNAL */
+
+                       if ( is_start() ) {
+                               Session::StartTimeChanged (); /* EMIT SIGNAL */
+                       }
+
+                       if ( is_end() ) {
+                               Session::EndTimeChanged (); /* EMIT SIGNAL */
+                       }
+
                }
                return 0;
        }
@@ -138,8 +166,12 @@ Location::set_end (nframes_t e)
 }
 
 int
-Location::set (nframes_t start, nframes_t end)
+Location::set (nframes64_t start, nframes64_t end)
 {
+       if (_locked) {
+               return -1;
+       }
+
        if (is_mark() && start != end) {
                return -1;
        } else if (((is_auto_punch() || is_auto_loop()) && start >= end) || (start > end)) {
@@ -158,6 +190,23 @@ Location::set (nframes_t start, nframes_t end)
        return 0;
 }
 
+int
+Location::move_to (nframes64_t pos) 
+{
+       if (_locked) {
+               return -1;
+       }
+
+       if (_start != pos) {
+               _start = pos;
+               _end = _start + length();
+               
+               changed (this); /* EMIT SIGNAL */
+       }
+       
+       return 0;
+}
+
 void
 Location::set_hidden (bool yn, void *src)
 {
@@ -198,6 +247,14 @@ Location::set_is_start (bool yn, void *src)
        }
 }
 
+void
+Location::set_is_range_marker (bool yn, void *src)
+{
+       if (set_flag_internal (yn, IsRangeMarker)) {
+                FlagsChanged (this, src); /* EMIT SIGNAL */
+       }
+}
+
 void
 Location::set_auto_punch (bool yn, void *src) 
 {
@@ -279,11 +336,12 @@ Location::get_state (void)
        id().print (buf, sizeof (buf));
        node->add_property("id", buf);
        node->add_property ("name", name());
-       snprintf (buf, sizeof (buf), "%u", start());
+       snprintf (buf, sizeof (buf), "%" PRId64, start());
        node->add_property ("start", buf);
-       snprintf (buf, sizeof (buf), "%u", end());
+       snprintf (buf, sizeof (buf), "%" PRId64, end());
        node->add_property ("end", buf);
        node->add_property ("flags", enum_2_string (_flags));
+       node->add_property ("locked", (_locked ? "yes" : "no"));
 
        return *node;
 }
@@ -327,14 +385,14 @@ Location::set_state (const XMLNode& node)
                   may make the value of _start illegal.
                */
                
-       _start = atoi (prop->value().c_str());
-               
+       sscanf (prop->value().c_str(), "%" PRId64, &_start);
+       
        if ((prop = node.property ("end")) == 0) {
                  error << _("XML node for Location has no end information") << endmsg; 
                  return -1;
        }
                
-       _end = atoi (prop->value().c_str());
+       sscanf (prop->value().c_str(), "%" PRId64, &_end);
                
        if ((prop = node.property ("flags")) == 0) {
                  error << _("XML node for Location has no flags information") << endmsg; 
@@ -343,6 +401,12 @@ Location::set_state (const XMLNode& node)
                
        _flags = Flags (string_2_enum (prop->value(), _flags));
 
+       if ((prop = node.property ("locked")) != 0) {
+               _locked = (prop->value() == "yes");
+       } else {
+               _locked = false;
+       }
+
        for (cd_iter = cd_list.begin(); cd_iter != cd_list.end(); ++cd_iter) {
                  
                  cd_node = *cd_iter;
@@ -590,7 +654,7 @@ Locations::remove (Location *loc)
 }
 
 void
-Locations::location_changed (Location* loc)
+Locations::location_changed (Location* /*loc*/)
 {
        changed (); /* EMIT SIGNAL */
 }
@@ -669,7 +733,7 @@ struct LocationStartLaterComparison
 };
 
 Location *
-Locations::first_location_before (nframes_t frame, bool include_special_ranges)
+Locations::first_location_before (nframes64_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -696,7 +760,7 @@ Locations::first_location_before (nframes_t frame, bool include_special_ranges)
 }
 
 Location *
-Locations::first_location_after (nframes_t frame, bool include_special_ranges)
+Locations::first_location_after (nframes64_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -722,8 +786,8 @@ Locations::first_location_after (nframes_t frame, bool include_special_ranges)
        return 0;
 }
 
-nframes_t
-Locations::first_mark_before (nframes_t frame, bool include_special_ranges)
+nframes64_t
+Locations::first_mark_before (nframes64_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -762,8 +826,8 @@ Locations::first_mark_before (nframes_t frame, bool include_special_ranges)
        return 0;
 }
 
-nframes_t
-Locations::first_mark_after (nframes_t frame, bool include_special_ranges)
+nframes64_t
+Locations::first_mark_after (nframes64_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -869,3 +933,16 @@ Locations::get_location_by_id(PBD::ID id)
 
     return 0;
 }
+
+void
+Locations::find_all_between (nframes64_t start, nframes64_t end, LocationList& ll, Location::Flags flags)
+{
+       Glib::Mutex::Lock lm (lock);
+
+       for (LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
+               if ((flags == 0 || (*i)->matches (flags)) && 
+                   ((*i)->start() >= start && (*i)->end() < end)) {
+                       ll.push_back (*i);
+               }
+       }
+}