X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Fsource.cc;h=b9ea6ee78a912f5ac75e020509fd94faf3d76c59;hb=22b07e0233a29d9633ffa825a79503befaf2e16e;hp=aaae432570fbdb7f02bba2c43fe223103e35d114;hpb=900309993c485527145be4265247bd521073ee61;p=ardour.git diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index aaae432570..b9ea6ee78a 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,8 +19,6 @@ #include #include -#include -#include #include #include #include @@ -29,52 +27,67 @@ #include #include -#include +#include #include #include -#include -#include -#include +#include "pbd/xml++.h" +#include "pbd/pthread_utils.h" +#include "pbd/enumwriter.h" -#include -#include -#include -#include +#include "ardour/debug.h" +#include "ardour/profile.h" +#include "ardour/session.h" +#include "ardour/source.h" +#include "ardour/transient_detector.h" #include "i18n.h" using namespace std; using namespace ARDOUR; +using namespace PBD; -Source::Source (Session& s, const string& name, DataType type, Flag flags) +Source::Source (Session& s, DataType type, const string& name, Flag flags) : SessionObject(s, name) , _type(type) , _flags(flags) + , _timeline_position(0) + , _use_count (0) + , _level (0) { _analysed = false; _timestamp = 0; - _length = 0; - _in_use = 0; + fix_writable_flags (); } -Source::Source (Session& s, const XMLNode& node) +Source::Source (Session& s, const XMLNode& node) : SessionObject(s, "unnamed source") , _type(DataType::AUDIO) , _flags (Flag (Writable|CanRename)) + , _timeline_position(0) + , _use_count (0) + , _level (0) { _timestamp = 0; - _length = 0; _analysed = false; - _in_use = 0; - if (set_state (node) || _type == DataType::NIL) { + if (set_state (node, Stateful::loading_state_version) || _type == DataType::NIL) { throw failed_constructor(); } + + fix_writable_flags (); } Source::~Source () { - notify_callbacks (); + DEBUG_TRACE (DEBUG::Destruction, string_compose ("Source %1 destructor %2\n", _name, this)); +} + +void +Source::fix_writable_flags () +{ + if (!_session.writable()) { + _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename)); + } } XMLNode& @@ -83,10 +96,10 @@ Source::get_state () XMLNode *node = new XMLNode ("Source"); char buf[64]; - node->add_property ("name", _name); + node->add_property ("name", name()); node->add_property ("type", _type.to_string()); node->add_property (X_("flags"), enum_2_string (_flags)); - _id.print (buf, sizeof (buf)); + id().print (buf, sizeof (buf)); node->add_property ("id", buf); if (_timestamp != 0) { @@ -98,7 +111,7 @@ Source::get_state () } int -Source::set_state (const XMLNode& node) +Source::set_state (const XMLNode& node, int version) { const XMLProperty* prop; @@ -107,10 +120,8 @@ Source::set_state (const XMLNode& node) } else { return -1; } - - if ((prop = node.property ("id")) != 0) { - _id = prop->value (); - } else { + + if (!set_id (node)) { return -1; } @@ -121,7 +132,7 @@ Source::set_state (const XMLNode& node) if ((prop = node.property ("timestamp")) != 0) { sscanf (prop->value().c_str(), "%ld", &_timestamp); } - + if ((prop = node.property (X_("flags"))) != 0) { _flags = Flag (string_2_enum (prop->value(), _flags)); } else { @@ -129,65 +140,33 @@ Source::set_state (const XMLNode& node) } - return 0; -} - -void -Source::update_length (nframes_t pos, nframes_t cnt) -{ - if (pos + cnt > _length) { - _length = pos+cnt; + /* old style, from the period when we had DestructiveFileSource */ + if ((prop = node.property (X_("destructive"))) != 0) { + _flags = Flag (_flags | Destructive); } -} - -void -Source::add_playlist (boost::shared_ptr pl) -{ - std::pair res; - std::pair, uint32_t> newpair (pl, 1); - Glib::Mutex::Lock lm (_playlist_lock); - res = _playlists.insert (newpair); - - if (!res.second) { - /* it already existed, bump count */ - res.first->second++; - } - - pl->GoingAway.connect (bind (mem_fun (*this, &Source::remove_playlist), boost::weak_ptr (pl))); -} - -void -Source::remove_playlist (boost::weak_ptr wpl) -{ - boost::shared_ptr pl (wpl.lock()); - - if (!pl) { - return; + if (Profile->get_trx() && (_flags & Destructive)) { + error << string_compose (_("%1: this session uses destructive tracks, which are not supported"), PROGRAM_NAME) << endmsg; + return -1; } - PlaylistMap::iterator x; - Glib::Mutex::Lock lm (_playlist_lock); - - if ((x = _playlists.find (pl)) != _playlists.end()) { - if (x->second > 1) { - x->second--; - } else { - _playlists.erase (x); + if (version < 3000) { + /* a source with an XML node must necessarily already exist, + and therefore cannot be removable/writable etc. etc.; 2.X + sometimes marks sources as removable which shouldn't be. + */ + if (!(_flags & Destructive)) { + _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename)); } } -} -uint32_t -Source::used () const -{ - return _playlists.size(); + return 0; } bool Source::has_been_analysed() const { - Glib::Mutex::Lock lm (_analysis_lock); + Glib::Threads::Mutex::Lock lm (_analysis_lock); return _analysed; } @@ -195,10 +174,10 @@ void Source::set_been_analysed (bool yn) { { - Glib::Mutex::Lock lm (_analysis_lock); + Glib::Threads::Mutex::Lock lm (_analysis_lock); _analysed = yn; } - + if (yn) { load_transients (get_transients_path()); AnalysisChanged(); // EMIT SIGNAL @@ -213,7 +192,7 @@ Source::load_transients (const string& path) if (!file) { return -1; } - + transients.clear (); stringstream strstr; @@ -223,7 +202,7 @@ Source::load_transients (const string& path) file >> val; if (!file.fail()) { - nframes64_t frame = (nframes64_t) floor (val * _session.frame_rate()); + framepos_t frame = (framepos_t) floor (val * _session.frame_rate()); transients.push_back (frame); } } @@ -231,29 +210,29 @@ Source::load_transients (const string& path) return 0; } -string +string Source::get_transients_path () const { vector parts; string s; /* old sessions may not have the analysis directory */ - + _session.ensure_subdirs (); s = _session.analysis_dir (); parts.push_back (s); - s = _id.to_s(); + s = id().to_s(); s += '.'; s += TransientDetector::operational_identifier(); parts.push_back (s); - + return Glib::build_filename (parts); } bool -Source::check_for_analysis_data_on_disk () +Source::check_for_analysis_data_on_disk () { /* looks to see if the analysis files for this source are on disk. if so, mark us already analysed. @@ -272,3 +251,65 @@ Source::check_for_analysis_data_on_disk () return ok; } +void +Source::mark_for_remove () +{ + // This operation is not allowed for sources for destructive tracks or out-of-session files. + + /* XXX need a way to detect _within_session() condition here - move it from FileSource? + */ + + if ((_flags & Destructive)) { + return; + } + + _flags = Flag (_flags | Removable | RemoveAtDestroy); +} + +void +Source::set_timeline_position (framepos_t pos) +{ + _timeline_position = pos; +} + +void +Source::set_allow_remove_if_empty (bool yn) +{ + if (!writable()) { + return; + } + + if (yn) { + _flags = Flag (_flags | RemovableIfEmpty); + } else { + _flags = Flag (_flags & ~RemovableIfEmpty); + } +} + +void +Source::inc_use_count () +{ + g_atomic_int_inc (&_use_count); +} + +void +Source::dec_use_count () +{ +#ifndef NDEBUG + gint oldval = g_atomic_int_add (&_use_count, -1); + if (oldval <= 0) { + cerr << "Bad use dec for " << name() << endl; + abort (); + } + assert (oldval > 0); +#else + g_atomic_int_add (&_use_count, -1); +#endif +} + +bool +Source::writable () const +{ + return (_flags & Writable) && _session.writable(); +} +