*** NEW CODING POLICY ***
[ardour.git] / libs / ardour / location.cc
index 58ef812d2e51a009ca745dde98032dbf3b3cad4a..ca0a56972ecc8484ea77461016eb49fc5fe03bdf 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <algorithm>
 #include <ctime>
 #include <sigc++/bind.h>
 
-#include <pbd/stl_delete.h>
-#include <pbd/xml++.h>
+#include "pbd/stl_delete.h"
+#include "pbd/xml++.h"
+#include "pbd/enumwriter.h"
 
-#include <ardour/location.h>
-#include <ardour/audiofilesource.h>
+#include "ardour/location.h"
+#include "ardour/session.h"
+#include "ardour/audiofilesource.h"
 
 #include "i18n.h"
 
+#define SUFFIX_MAX 32
+
 using namespace std;
 using namespace ARDOUR;
 using namespace sigc;
@@ -49,6 +52,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)
@@ -70,22 +77,40 @@ 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 (jack_nframes_t s)
+Location::set_start (nframes_t s)
 {
+       if (_locked) {
+               return -1;
+       }
+
        if (is_mark()) {
                if (_start != s) {
+
                        _start = s;
                        _end = s;
+
                        start_changed(this); /* EMIT SIGNAL */
+                       end_changed(this); /* EMIT SIGNAL */
+
                        if ( is_start() ) {
+
+                               Session::StartTimeChanged (); /* EMIT SIGNAL */
                                AudioFileSource::set_header_position_offset ( s );
                        }
+
+                       if ( is_end() ) {
+                               Session::EndTimeChanged (); /* EMIT SIGNAL */
+                       }
                }
                return 0;
        }
@@ -103,13 +128,27 @@ Location::set_start (jack_nframes_t s)
 }
 
 int
-Location::set_end (jack_nframes_t e)
+Location::set_end (nframes_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;
        }
@@ -126,8 +165,12 @@ Location::set_end (jack_nframes_t e)
 }
 
 int
-Location::set (jack_nframes_t start, jack_nframes_t end)
+Location::set (nframes_t start, nframes_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)) {
@@ -146,6 +189,23 @@ Location::set (jack_nframes_t start, jack_nframes_t end)
        return 0;
 }
 
+int
+Location::move_to (nframes_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)
 {
@@ -157,6 +217,14 @@ Location::set_hidden (bool yn, void *src)
 void
 Location::set_cd (bool yn, void *src)
 {
+       // XXX this really needs to be session start
+       // but its not available here - leave to GUI
+
+       if (_start == 0) {
+               error << _("You cannot put a CD marker at this position") << endmsg;
+               return;
+       }
+
        if (set_flag_internal (yn, IsCDMarker)) {
                 FlagsChanged (this, src); /* EMIT SIGNAL */
        }
@@ -178,6 +246,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) 
 {
@@ -207,12 +283,12 @@ Location::set_flag_internal (bool yn, Flags flag)
 {
        if (yn) {
                if (!(_flags & flag)) {
-                       _flags |= flag;
+                       _flags = Flags (_flags | flag);
                        return true;
                }
        } else {
                if (_flags & flag) {
-                       _flags &= ~flag;
+                       _flags = Flags (_flags & ~flag);
                        return true;
                }
        }
@@ -256,15 +332,15 @@ Location::get_state (void)
                node->add_child_nocopy(cd_info_node(m->first, m->second));
        }
 
-       id().print (buf);
+       id().print (buf, sizeof (buf));
        node->add_property("id", buf);
        node->add_property ("name", name());
        snprintf (buf, sizeof (buf), "%u", start());
        node->add_property ("start", buf);
        snprintf (buf, sizeof (buf), "%u", end());
        node->add_property ("end", buf);
-       snprintf (buf, sizeof (buf), "%" PRIu32, (uint32_t) _flags);
-       node->add_property ("flags", buf);
+       node->add_property ("flags", enum_2_string (_flags));
+       node->add_property ("locked", (_locked ? "yes" : "no"));
 
        return *node;
 }
@@ -317,14 +393,18 @@ Location::set_state (const XMLNode& node)
                
        _end = atoi (prop->value().c_str());
                
-       _flags = 0;
-               
        if ((prop = node.property ("flags")) == 0) {
                  error << _("XML node for Location has no flags information") << endmsg; 
                  return -1;
        }
                
-       _flags = Flags (atoi (prop->value().c_str()));
+       _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) {
                  
@@ -362,27 +442,16 @@ Locations::Locations ()
 
 {
        current_location = 0;
-       save_state (_("initial"));
 }
 
 Locations::~Locations () 
 {
-       std::set<Location*> all_locations;
-       
-       for (StateMap::iterator siter = states.begin(); siter != states.end(); ++siter) {
-
-               State* lstate = dynamic_cast<State*> (*siter);
-
-               for (LocationList::iterator liter = lstate->locations.begin(); liter != lstate->locations.end(); ++liter) {
-                       all_locations.insert (*liter);
-               }
-
-               for (LocationList::iterator siter = lstate->states.begin(); siter != lstate->states.end(); ++siter) {
-                       all_locations.insert (*siter);
-               }
+       for (LocationList::iterator i = locations.begin(); i != locations.end(); ) {
+               LocationList::iterator tmp = i;
+               ++tmp;
+               delete *i;
+               i = tmp;
        }
-
-       set_delete (&all_locations);
 }
 
 int
@@ -404,6 +473,40 @@ Locations::set_current (Location *loc, bool want_lock)
        return ret;
 }
 
+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];
+
+       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;
+               }
+       }
+       return 0;
+}
+
 int
 Locations::set_current_unlocked (Location *loc)
 {
@@ -421,22 +524,22 @@ Locations::clear ()
 {
        {
                Glib::Mutex::Lock lm (lock);
-               LocationList::iterator tmp;
+
                for (LocationList::iterator i = locations.begin(); i != locations.end(); ) {
-                       tmp = i;
+
+                       LocationList::iterator tmp = i;
                        ++tmp;
+
                        if (!(*i)->is_end() && !(*i)->is_start()) {
                                locations.erase (i);
                        }
+
                        i = tmp;
                }
 
-               locations.clear ();
                current_location = 0;
        }
 
-       save_state (_("clear"));
-       
        changed (); /* EMIT SIGNAL */
        current_changed (0); /* EMIT SIGNAL */
 }      
@@ -460,8 +563,6 @@ Locations::clear_markers ()
                }
        }
 
-       save_state (_("clear markers"));
-       
        changed (); /* EMIT SIGNAL */
 }      
 
@@ -488,8 +589,6 @@ Locations::clear_ranges ()
                current_location = 0;
        }
 
-       save_state (_("clear ranges"));
-
        changed (); /* EMIT SIGNAL */
        current_changed (0); /* EMIT SIGNAL */
 }      
@@ -506,8 +605,6 @@ Locations::add (Location *loc, bool make_current)
                }
        }
        
-       save_state (_("add"));
-
        added (loc); /* EMIT SIGNAL */
 
        if (make_current) {
@@ -544,9 +641,8 @@ Locations::remove (Location *loc)
        }
        
        if (was_removed) {
-               save_state (_("remove"));
-
-                removed (loc); /* EMIT SIGNAL */
+               
+               removed (loc); /* EMIT SIGNAL */
 
                if (was_current) {
                         current_changed (0); /* EMIT SIGNAL */
@@ -559,7 +655,6 @@ Locations::remove (Location *loc)
 void
 Locations::location_changed (Location* loc)
 {
-       save_state (X_("location changed"));
        changed (); /* EMIT SIGNAL */
 }
 
@@ -589,7 +684,10 @@ Locations::set_state (const XMLNode& node)
        }
        
        nlist = node.children();
-       
+
+       locations.clear ();
+       current_location = 0;
+
        {
                Glib::Mutex::Lock lm (lock);
 
@@ -634,7 +732,7 @@ struct LocationStartLaterComparison
 };
 
 Location *
-Locations::first_location_before (jack_nframes_t frame)
+Locations::first_location_before (nframes_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -649,6 +747,9 @@ Locations::first_location_before (jack_nframes_t frame)
        /* locs is now sorted latest..earliest */
        
        for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+               if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+                       continue;
+               }
                if (!(*i)->is_hidden() && (*i)->start() < frame) {
                        return (*i);
                }
@@ -658,7 +759,7 @@ Locations::first_location_before (jack_nframes_t frame)
 }
 
 Location *
-Locations::first_location_after (jack_nframes_t frame)
+Locations::first_location_after (nframes_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -673,6 +774,9 @@ Locations::first_location_after (jack_nframes_t frame)
        /* locs is now sorted earliest..latest */
        
        for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+               if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+                       continue;
+               }
                if (!(*i)->is_hidden() && (*i)->start() > frame) {
                        return (*i);
                }
@@ -681,8 +785,8 @@ Locations::first_location_after (jack_nframes_t frame)
        return 0;
 }
 
-jack_nframes_t
-Locations::first_mark_before (jack_nframes_t frame)
+nframes_t
+Locations::first_mark_before (nframes_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -697,6 +801,9 @@ Locations::first_mark_before (jack_nframes_t frame)
        /* locs is now sorted latest..earliest */
        
        for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+               if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+                       continue;
+               }
                if (!(*i)->is_hidden()) {
                        if ((*i)->is_mark()) {
                                /* MARK: start == end */
@@ -718,8 +825,8 @@ Locations::first_mark_before (jack_nframes_t frame)
        return 0;
 }
 
-jack_nframes_t
-Locations::first_mark_after (jack_nframes_t frame)
+nframes_t
+Locations::first_mark_after (nframes_t frame, bool include_special_ranges)
 {
        LocationList locs;
 
@@ -734,6 +841,9 @@ Locations::first_mark_after (jack_nframes_t frame)
        /* locs is now sorted earliest..latest */
        
        for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+               if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+                       continue;
+               }
                if (!(*i)->is_hidden()) {
                        if ((*i)->is_mark()) {
                                /* MARK, start == end so just compare start */
@@ -799,45 +909,6 @@ Locations::auto_punch_location () const
        return 0;
 }      
 
-StateManager::State*
-Locations::state_factory (std::string why) const
-{
-       State* state = new State (why);
-
-       state->locations = locations;
-       
-       for (LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
-               state->states.push_back (new Location (**i));
-       }
-
-       return state;
-}
-
-Change
-Locations::restore_state (StateManager::State& state) 
-{
-       {
-               Glib::Mutex::Lock lm (lock);
-               State* lstate = dynamic_cast<State*> (&state);
-
-               locations = lstate->locations;
-               LocationList& states = lstate->states;
-               LocationList::iterator l, s;
-
-               for (l = locations.begin(), s = states.begin(); s != states.end(); ++s, ++l) {
-                       (*l) = (*s);
-               }
-       }
-
-       return Change (0);
-}
-
-UndoAction
-Locations::get_memento () const
-{
-  return sigc::bind (mem_fun (*(const_cast<Locations*> (this)), &StateManager::use_state), _current_state_id);
-}
-
 uint32_t
 Locations::num_range_markers () const
 {
@@ -861,3 +932,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);
+               }
+       }
+}