mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 16:46:35 +01:00
newly created files for use in recording appear in a .stubs folder, and are moved out of it when recording stops
git-svn-id: svn://localhost/ardour2/branches/3.0@7426 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
e9ab577177
commit
c8e3f32533
31 changed files with 345 additions and 194 deletions
|
|
@ -33,11 +33,12 @@
|
||||||
#include "pbd/memento_command.h"
|
#include "pbd/memento_command.h"
|
||||||
#include "pbd/stateful_diff_command.h"
|
#include "pbd/stateful_diff_command.h"
|
||||||
|
|
||||||
#include <gtkmm2ext/gtk_ui.h>
|
#include "gtkmm2ext/gtk_ui.h"
|
||||||
#include <gtkmm2ext/selector.h>
|
#include "gtkmm2ext/selector.h"
|
||||||
#include <gtkmm2ext/bindable_button.h>
|
#include "gtkmm2ext/bindable_button.h"
|
||||||
#include <gtkmm2ext/utils.h>
|
#include "gtkmm2ext/utils.h"
|
||||||
|
|
||||||
|
#include "ardour/file_source.h"
|
||||||
#include "ardour/midi_playlist.h"
|
#include "ardour/midi_playlist.h"
|
||||||
#include "ardour/midi_diskstream.h"
|
#include "ardour/midi_diskstream.h"
|
||||||
#include "ardour/midi_patch_manager.h"
|
#include "ardour/midi_patch_manager.h"
|
||||||
|
|
@ -961,7 +962,6 @@ MidiTimeAxisView::add_region (nframes64_t pos)
|
||||||
|
|
||||||
boost::shared_ptr<Source> src = _session->create_midi_source_for_session (view()->trackview().track().get(),
|
boost::shared_ptr<Source> src = _session->create_midi_source_for_session (view()->trackview().track().get(),
|
||||||
view()->trackview().track()->name());
|
view()->trackview().track()->name());
|
||||||
|
|
||||||
PropertyList plist;
|
PropertyList plist;
|
||||||
|
|
||||||
plist.add (ARDOUR::Properties::start, 0);
|
plist.add (ARDOUR::Properties::start, 0);
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ class CoreAudioSource : public AudioFileSource {
|
||||||
CoreAudioSource (ARDOUR::Session&, const string& path, int chn, Flag);
|
CoreAudioSource (ARDOUR::Session&, const string& path, int chn, Flag);
|
||||||
~CoreAudioSource ();
|
~CoreAudioSource ();
|
||||||
|
|
||||||
|
void set_path (const std::string& p);
|
||||||
|
|
||||||
float sample_rate() const;
|
float sample_rate() const;
|
||||||
int update_header (sframes_t when, struct tm&, time_t);
|
int update_header (sframes_t when, struct tm&, time_t);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ extern const char* const templates_dir_name;
|
||||||
extern const char* const route_templates_dir_name;
|
extern const char* const route_templates_dir_name;
|
||||||
extern const char* const surfaces_dir_name;
|
extern const char* const surfaces_dir_name;
|
||||||
extern const char* const user_config_dir_name;
|
extern const char* const user_config_dir_name;
|
||||||
|
extern const char* const stub_dir_name;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@ class FileSource : virtual public Source {
|
||||||
public:
|
public:
|
||||||
const Glib::ustring& path() const { return _path; }
|
const Glib::ustring& path() const { return _path; }
|
||||||
|
|
||||||
|
int unstubify ();
|
||||||
|
void stubify ();
|
||||||
|
|
||||||
virtual bool safe_file_extension (const Glib::ustring& path) const = 0;
|
virtual bool safe_file_extension (const Glib::ustring& path) const = 0;
|
||||||
|
|
||||||
int move_to_trash (const Glib::ustring& trash_dir_name);
|
int move_to_trash (const Glib::ustring& trash_dir_name);
|
||||||
|
|
@ -57,6 +60,8 @@ public:
|
||||||
bool must_exist, bool& is_new, uint16_t& chan,
|
bool must_exist, bool& is_new, uint16_t& chan,
|
||||||
Glib::ustring& found_path);
|
Glib::ustring& found_path);
|
||||||
|
|
||||||
|
void inc_use_count ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileSource (Session& session, DataType type,
|
FileSource (Session& session, DataType type,
|
||||||
const Glib::ustring& path,
|
const Glib::ustring& path,
|
||||||
|
|
@ -66,6 +71,7 @@ protected:
|
||||||
|
|
||||||
virtual int init (const Glib::ustring& idstr, bool must_exist);
|
virtual int init (const Glib::ustring& idstr, bool must_exist);
|
||||||
|
|
||||||
|
virtual void set_path (const std::string&);
|
||||||
virtual int move_dependents_to_trash() { return 0; }
|
virtual int move_dependents_to_trash() { return 0; }
|
||||||
void set_within_session_from_path (const std::string&);
|
void set_within_session_from_path (const std::string&);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
std::string peak_path_from_audio_path (std::string) const;
|
std::string peak_path_from_audio_path (std::string) const;
|
||||||
std::string new_audio_source_name (const std::string&, uint32_t nchans, uint32_t chan, bool destructive);
|
std::string new_audio_source_name (const std::string&, uint32_t nchans, uint32_t chan, bool destructive);
|
||||||
std::string new_midi_source_name (const std::string&);
|
std::string new_midi_source_name (const std::string&);
|
||||||
std::string new_source_path_from_name (DataType type, const std::string&);
|
std::string new_source_path_from_name (DataType type, const std::string&, bool as_stub = false);
|
||||||
RouteList new_route_from_template (uint32_t how_many, const std::string& template_path);
|
RouteList new_route_from_template (uint32_t how_many, const std::string& template_path);
|
||||||
|
|
||||||
void process (nframes_t nframes);
|
void process (nframes_t nframes);
|
||||||
|
|
@ -533,9 +533,10 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
*/
|
*/
|
||||||
static PBD::Signal0<int> AskAboutPendingState;
|
static PBD::Signal0<int> AskAboutPendingState;
|
||||||
|
|
||||||
boost::shared_ptr<AudioFileSource> create_audio_source_for_session (size_t, std::string const &, uint32_t, bool);
|
boost::shared_ptr<AudioFileSource> create_audio_source_for_session (size_t, std::string const &, uint32_t,
|
||||||
|
bool destructive, bool as_stub = false);
|
||||||
|
|
||||||
boost::shared_ptr<MidiSource> create_midi_source_for_session (Track*, std::string const &);
|
boost::shared_ptr<MidiSource> create_midi_source_for_session (Track*, std::string const &, bool as_stub = false);
|
||||||
|
|
||||||
boost::shared_ptr<Source> source_by_id (const PBD::ID&);
|
boost::shared_ptr<Source> source_by_id (const PBD::ID&);
|
||||||
boost::shared_ptr<Source> source_by_path_and_channel (const Glib::ustring&, uint16_t);
|
boost::shared_ptr<Source> source_by_path_and_channel (const Glib::ustring&, uint16_t);
|
||||||
|
|
@ -1415,6 +1416,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
void add_session_range_location (nframes_t, nframes_t);
|
void add_session_range_location (nframes_t, nframes_t);
|
||||||
|
|
||||||
void setup_midi_machine_control ();
|
void setup_midi_machine_control ();
|
||||||
|
void cleanup_stubfiles ();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,17 @@ public:
|
||||||
*/
|
*/
|
||||||
const PBD::sys::path sound_path () const;
|
const PBD::sys::path sound_path () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the absolute path to the directory in which
|
||||||
|
* the session stores STUB audio files.
|
||||||
|
*
|
||||||
|
* If the session is an older session with an existing
|
||||||
|
* "sounds" directory then it will return a path to that
|
||||||
|
* directory otherwise it will return the new location
|
||||||
|
* of root_path()/interchange/session_name/audiofiles/.stubs
|
||||||
|
*/
|
||||||
|
const PBD::sys::path sound_stub_path () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the absolute path to the directory in which
|
* @return the absolute path to the directory in which
|
||||||
* the session stores MIDI files, ie
|
* the session stores MIDI files, ie
|
||||||
|
|
@ -58,6 +69,13 @@ public:
|
||||||
*/
|
*/
|
||||||
const PBD::sys::path midi_path () const;
|
const PBD::sys::path midi_path () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the absolute path to the directory in which
|
||||||
|
* the session stores STUB MIDI files, ie
|
||||||
|
* root_path()/interchange/session_name/midifiles/.stubs
|
||||||
|
*/
|
||||||
|
const PBD::sys::path midi_stub_path () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the absolute path to the directory in which
|
* @return the absolute path to the directory in which
|
||||||
* the session stores MIDNAM patch files, ie
|
* the session stores MIDNAM patch files, ie
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,10 @@ public:
|
||||||
|
|
||||||
static bool safe_midi_file_extension (const Glib::ustring& path);
|
static bool safe_midi_file_extension (const Glib::ustring& path);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
void set_path (const std::string& newpath);
|
||||||
|
|
||||||
|
private:
|
||||||
nframes_t read_unlocked (Evoral::EventSink<nframes_t>& dst,
|
nframes_t read_unlocked (Evoral::EventSink<nframes_t>& dst,
|
||||||
sframes_t position,
|
sframes_t position,
|
||||||
sframes_t start,
|
sframes_t start,
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ class SndFileSource : public AudioFileSource {
|
||||||
static int get_soundfile_info (const Glib::ustring& path, SoundFileInfo& _info, std::string& error_msg);
|
static int get_soundfile_info (const Glib::ustring& path, SoundFileInfo& _info, std::string& error_msg);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void set_path (const std::string& p);
|
||||||
void set_header_timeline_position ();
|
void set_header_timeline_position ();
|
||||||
|
|
||||||
framecnt_t read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) const;
|
framecnt_t read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) const;
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,8 @@ class Source : public SessionObject
|
||||||
Glib::Mutex& mutex() { return _lock; }
|
Glib::Mutex& mutex() { return _lock; }
|
||||||
Flag flags() const { return _flags; }
|
Flag flags() const { return _flags; }
|
||||||
|
|
||||||
void inc_use_count () { g_atomic_int_inc (&_use_count); }
|
virtual void inc_use_count ();
|
||||||
void dec_use_count ();
|
virtual void dec_use_count ();
|
||||||
int use_count() const { return g_atomic_int_get (&_use_count); }
|
int use_count() const { return g_atomic_int_get (&_use_count); }
|
||||||
bool used() const { return use_count() > 0; }
|
bool used() const { return use_count() > 0; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <jack/types.h>
|
#include <jack/types.h>
|
||||||
|
|
@ -440,7 +441,7 @@ namespace ARDOUR {
|
||||||
|
|
||||||
struct CleanupReport {
|
struct CleanupReport {
|
||||||
std::vector<std::string> paths;
|
std::vector<std::string> paths;
|
||||||
int64_t space;
|
size_t space;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PositionLockStyle {
|
enum PositionLockStyle {
|
||||||
|
|
|
||||||
|
|
@ -1388,6 +1388,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
|
||||||
|
|
||||||
(*chan)->write_source->mark_for_remove ();
|
(*chan)->write_source->mark_for_remove ();
|
||||||
(*chan)->write_source->drop_references ();
|
(*chan)->write_source->drop_references ();
|
||||||
|
_session.remove_source ((*chan)->write_source);
|
||||||
(*chan)->write_source.reset ();
|
(*chan)->write_source.reset ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1409,9 +1410,13 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
srcs.push_back (s);
|
srcs.push_back (s);
|
||||||
|
if (s->unstubify ()) {
|
||||||
|
error << string_compose (_("Could not move capture file from %1"), s->path()) << endmsg;
|
||||||
|
}
|
||||||
s->update_header (capture_info.front()->start, when, twhen);
|
s->update_header (capture_info.front()->start, when, twhen);
|
||||||
s->set_captured_for (_name.val());
|
s->set_captured_for (_name.val());
|
||||||
s->mark_immutable ();
|
s->mark_immutable ();
|
||||||
|
|
||||||
if (Config->get_auto_analyse_audio()) {
|
if (Config->get_auto_analyse_audio()) {
|
||||||
Analyser::queue_source_for_analysis (s, true);
|
Analyser::queue_source_for_analysis (s, true);
|
||||||
}
|
}
|
||||||
|
|
@ -1880,7 +1885,13 @@ AudioDiskstream::use_new_write_source (uint32_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(), name(), n, destructive())) == 0) {
|
/* file starts off as a stub file, it will be converted
|
||||||
|
when we're done with a capture pass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(),
|
||||||
|
name(), n, destructive(),
|
||||||
|
true)) == 0) {
|
||||||
throw failed_constructor();
|
throw failed_constructor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1895,10 +1906,6 @@ AudioDiskstream::use_new_write_source (uint32_t n)
|
||||||
|
|
||||||
chan->write_source->set_allow_remove_if_empty (!destructive());
|
chan->write_source->set_allow_remove_if_empty (!destructive());
|
||||||
|
|
||||||
/* until we write, this file is considered removable */
|
|
||||||
|
|
||||||
chan->write_source->mark_for_remove ();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -368,3 +368,9 @@ CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string&
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CoreAudioSource::set_path (const string& p)
|
||||||
|
{
|
||||||
|
FileSource::set_path (p);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,6 @@ const char* const templates_dir_name = X_("templates");
|
||||||
const char* const route_templates_dir_name = X_("route_templates");
|
const char* const route_templates_dir_name = X_("route_templates");
|
||||||
const char* const surfaces_dir_name = X_("surfaces");
|
const char* const surfaces_dir_name = X_("surfaces");
|
||||||
const char* const user_config_dir_name = X_("ardour3");
|
const char* const user_config_dir_name = X_("ardour3");
|
||||||
|
const char* const stub_dir_name = X_(".stubs");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
#include <glibmm/thread.h>
|
#include <glibmm/thread.h>
|
||||||
|
|
||||||
#include "ardour/file_source.h"
|
#include "ardour/file_source.h"
|
||||||
|
#include "ardour/directory_names.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/session_directory.h"
|
#include "ardour/session_directory.h"
|
||||||
#include "ardour/source_factory.h"
|
#include "ardour/source_factory.h"
|
||||||
|
|
@ -51,8 +52,6 @@ using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
using namespace Glib;
|
using namespace Glib;
|
||||||
|
|
||||||
static const std::string PATH_SEP = "/"; // I don't do windows
|
|
||||||
|
|
||||||
map<DataType, ustring> FileSource::search_paths;
|
map<DataType, ustring> FileSource::search_paths;
|
||||||
|
|
||||||
FileSource::FileSource (Session& session, DataType type, const ustring& path, Source::Flag flag)
|
FileSource::FileSource (Session& session, DataType type, const ustring& path, Source::Flag flag)
|
||||||
|
|
@ -80,9 +79,14 @@ FileSource::FileSource (Session& session, const XMLNode& node, bool /*must_exist
|
||||||
bool
|
bool
|
||||||
FileSource::removable () const
|
FileSource::removable () const
|
||||||
{
|
{
|
||||||
return (_flags & Removable)
|
bool r = (_path.find (stub_dir_name) != string::npos) ||
|
||||||
|
((_flags & Removable)
|
||||||
&& ((_flags & RemoveAtDestroy) ||
|
&& ((_flags & RemoveAtDestroy) ||
|
||||||
((_flags & RemovableIfEmpty) && empty() == 0));
|
((_flags & RemovableIfEmpty) && empty() == 0)));
|
||||||
|
|
||||||
|
cerr << "is " << _path << " removable ? " << r << endl;
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -140,15 +144,16 @@ FileSource::move_to_trash (const ustring& trash_dir_name)
|
||||||
trash_dir_name directory on whichever filesystem it was already on
|
trash_dir_name directory on whichever filesystem it was already on
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ustring newpath;
|
vector<string> v;
|
||||||
newpath = Glib::path_get_dirname (_path);
|
v.push_back (Glib::path_get_dirname (Glib::path_get_dirname (_path)));
|
||||||
newpath = Glib::path_get_dirname (newpath);
|
v.push_back (trash_dir_name);
|
||||||
|
v.push_back (Glib::path_get_basename (_path));
|
||||||
|
|
||||||
newpath += string(PATH_SEP) + trash_dir_name + PATH_SEP;
|
string newpath = Glib::build_filename (v);
|
||||||
newpath += Glib::path_get_basename (_path);
|
|
||||||
|
|
||||||
/* the new path already exists, try versioning */
|
/* the new path already exists, try versioning */
|
||||||
if (access (newpath.c_str(), F_OK) == 0) {
|
|
||||||
|
if (Glib::file_test (newpath.c_str(), Glib::FILE_TEST_EXISTS)) {
|
||||||
char buf[PATH_MAX+1];
|
char buf[PATH_MAX+1];
|
||||||
int version = 1;
|
int version = 1;
|
||||||
ustring newpath_v;
|
ustring newpath_v;
|
||||||
|
|
@ -391,7 +396,7 @@ FileSource::set_source_name (const ustring& newname, bool destructive)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
|
if (::rename (oldpath.c_str(), newpath.c_str()) != 0) {
|
||||||
error << string_compose (_("cannot rename audio file %1 to %2"), _name, newpath) << endmsg;
|
error << string_compose (_("cannot rename audio file %1 to %2"), _name, newpath) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -428,3 +433,42 @@ FileSource::set_within_session_from_path (const std::string& path)
|
||||||
{
|
{
|
||||||
_within_session = _session.path_is_within_session (path);
|
_within_session = _session.path_is_within_session (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
FileSource::unstubify ()
|
||||||
|
{
|
||||||
|
string::size_type pos = _path.find (stub_dir_name);
|
||||||
|
|
||||||
|
if (pos == string::npos || (_flags & Destructive)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string> v;
|
||||||
|
|
||||||
|
v.push_back (Glib::path_get_dirname (Glib::path_get_dirname (_path)));
|
||||||
|
v.push_back (Glib::path_get_basename(_path));
|
||||||
|
|
||||||
|
string newpath = Glib::build_filename (v);
|
||||||
|
|
||||||
|
if (::rename (_path.c_str(), newpath.c_str()) != 0) {
|
||||||
|
error << string_compose (_("rename from %1 to %2 failed: %3)"), _path, newpath, strerror (errno)) << endmsg;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_path (newpath);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FileSource::set_path (const std::string& newpath)
|
||||||
|
{
|
||||||
|
_path = newpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FileSource::inc_use_count ()
|
||||||
|
{
|
||||||
|
Source::inc_use_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -957,14 +957,18 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
|
||||||
|
|
||||||
_write_source->mark_streaming_write_completed ();
|
_write_source->mark_streaming_write_completed ();
|
||||||
|
|
||||||
|
/* make it not a stub anymore */
|
||||||
|
|
||||||
|
_write_source->unstubify ();
|
||||||
|
|
||||||
/* we will want to be able to keep (over)writing the source
|
/* we will want to be able to keep (over)writing the source
|
||||||
but we don't want it to be removable. this also differs
|
but we don't want it to be removable. this also differs
|
||||||
from the audio situation, where the source at this point
|
from the audio situation, where the source at this point
|
||||||
must be considered immutable
|
must be considered immutable. luckily, we can rely on
|
||||||
|
MidiSource::mark_streaming_write_completed() to have
|
||||||
|
already done the necessary work for that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_write_source->mark_nonremovable ();
|
|
||||||
|
|
||||||
string whole_file_region_name;
|
string whole_file_region_name;
|
||||||
whole_file_region_name = region_name_from_path (_write_source->name(), true);
|
whole_file_region_name = region_name_from_path (_write_source->name(), true);
|
||||||
|
|
||||||
|
|
@ -1321,7 +1325,14 @@ MidiDiskstream::use_new_write_source (uint32_t n)
|
||||||
_write_source.reset();
|
_write_source.reset();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_write_source = boost::dynamic_pointer_cast<SMFSource>(_session.create_midi_source_for_session (0, name ()));
|
/* file starts off as a stub file, it will be converted
|
||||||
|
when we're done with a capture pass, or when "stolen"
|
||||||
|
by the GUI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_write_source = boost::dynamic_pointer_cast<SMFSource>(
|
||||||
|
_session.create_midi_source_for_session (0, name (), true));
|
||||||
|
|
||||||
if (!_write_source) {
|
if (!_write_source) {
|
||||||
throw failed_constructor();
|
throw failed_constructor();
|
||||||
}
|
}
|
||||||
|
|
@ -1342,8 +1353,26 @@ list<boost::shared_ptr<Source> >
|
||||||
MidiDiskstream::steal_write_sources()
|
MidiDiskstream::steal_write_sources()
|
||||||
{
|
{
|
||||||
list<boost::shared_ptr<Source> > ret;
|
list<boost::shared_ptr<Source> > ret;
|
||||||
|
|
||||||
|
/* put some data on the disk, even if its just a header for an empty file.
|
||||||
|
XXX should we not have a more direct method for doing this? Maybe not
|
||||||
|
since we don't want to mess around with the model/disk relationship
|
||||||
|
that the Source has to pay attention to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
boost::dynamic_pointer_cast<MidiSource>(_write_source)->session_saved ();
|
||||||
|
|
||||||
|
/* make it visible/present */
|
||||||
|
_write_source->unstubify ();
|
||||||
|
/* never let it go away */
|
||||||
|
_write_source->mark_nonremovable ();
|
||||||
|
|
||||||
ret.push_back (_write_source);
|
ret.push_back (_write_source);
|
||||||
|
|
||||||
|
/* get a new one */
|
||||||
|
|
||||||
use_new_write_source (0);
|
use_new_write_source (0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -321,19 +321,11 @@ MidiSource::session_saved()
|
||||||
XXX do we need to do this every time?
|
XXX do we need to do this every time?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flush_midi();
|
|
||||||
|
|
||||||
if (_model && _model->edited()) {
|
if (_model && _model->edited()) {
|
||||||
#if 0 // old style: clone the source if necessary on every session save
|
|
||||||
// and switch to the new source
|
|
||||||
boost::shared_ptr<MidiSource> newsrc = clone ();
|
|
||||||
|
|
||||||
if (newsrc) {
|
|
||||||
_model->set_midi_source (newsrc);
|
|
||||||
Switched (newsrc); /* EMIT SIGNAL */
|
// if the model is edited, write its contents into
|
||||||
}
|
|
||||||
#else
|
|
||||||
// new style: if the model is edited, write its contents into
|
|
||||||
// the current source file (overwiting previous contents.
|
// the current source file (overwiting previous contents.
|
||||||
|
|
||||||
/* temporarily drop our reference to the model so that
|
/* temporarily drop our reference to the model so that
|
||||||
|
|
@ -343,13 +335,19 @@ MidiSource::session_saved()
|
||||||
|
|
||||||
boost::shared_ptr<MidiModel> mm = _model ;
|
boost::shared_ptr<MidiModel> mm = _model ;
|
||||||
_model.reset ();
|
_model.reset ();
|
||||||
mm->sync_to_source ();
|
|
||||||
_model = mm;
|
|
||||||
/* data is in the file now, its not removable */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << name() << " @ " << this << " length at save = " << _length_beats << endl;
|
/* flush model contents to disk
|
||||||
|
*/
|
||||||
|
|
||||||
|
mm->sync_to_source ();
|
||||||
|
|
||||||
|
/* reacquire model */
|
||||||
|
|
||||||
|
_model = mm;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
flush_midi();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,11 @@ PlaylistFactory::create (Session& s, const XMLNode& node, bool hidden, bool unus
|
||||||
|
|
||||||
boost::shared_ptr<Playlist> pl;
|
boost::shared_ptr<Playlist> pl;
|
||||||
|
|
||||||
if ( !type || type->value() == "audio" )
|
if (!type || type->value() == "audio") {
|
||||||
pl = boost::shared_ptr<Playlist> (new AudioPlaylist (s, node, hidden));
|
pl = boost::shared_ptr<Playlist> (new AudioPlaylist (s, node, hidden));
|
||||||
else if ( type->value() == "midi" )
|
} else if (type->value() == "midi") {
|
||||||
pl = boost::shared_ptr<Playlist> (new MidiPlaylist (s, node, hidden));
|
pl = boost::shared_ptr<Playlist> (new MidiPlaylist (s, node, hidden));
|
||||||
|
}
|
||||||
|
|
||||||
pl->set_region_ownership ();
|
pl->set_region_ownership ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1388,7 +1388,6 @@ void
|
||||||
Region::set_master_sources (const SourceList& srcs)
|
Region::set_master_sources (const SourceList& srcs)
|
||||||
{
|
{
|
||||||
for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
|
for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
|
||||||
cerr << name() << " " << id() << " DEC M SMS\n";
|
|
||||||
(*i)->dec_use_count ();
|
(*i)->dec_use_count ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,10 @@ Session::destroy ()
|
||||||
|
|
||||||
delete state_tree;
|
delete state_tree;
|
||||||
|
|
||||||
|
/* remove all stubfiles that might still be lurking */
|
||||||
|
|
||||||
|
cleanup_stubfiles ();
|
||||||
|
|
||||||
/* reset dynamic state version back to default */
|
/* reset dynamic state version back to default */
|
||||||
|
|
||||||
Stateful::loading_state_version = 0;
|
Stateful::loading_state_version = 0;
|
||||||
|
|
@ -2606,6 +2610,7 @@ Session::remove_source (boost::weak_ptr<Source> src)
|
||||||
Glib::Mutex::Lock lm (source_lock);
|
Glib::Mutex::Lock lm (source_lock);
|
||||||
|
|
||||||
if ((i = sources.find (source->id())) != sources.end()) {
|
if ((i = sources.find (source->id())) != sources.end()) {
|
||||||
|
cerr << "Removing source " << source->name() << endl;
|
||||||
sources.erase (i);
|
sources.erase (i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2640,7 +2645,6 @@ Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
|
||||||
Glib::Mutex::Lock lm (source_lock);
|
Glib::Mutex::Lock lm (source_lock);
|
||||||
|
|
||||||
for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
|
for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
|
||||||
cerr << "comparing " << path << " with " << i->second->name() << endl;
|
|
||||||
boost::shared_ptr<AudioFileSource> afs
|
boost::shared_ptr<AudioFileSource> afs
|
||||||
= boost::dynamic_pointer_cast<AudioFileSource>(i->second);
|
= boost::dynamic_pointer_cast<AudioFileSource>(i->second);
|
||||||
|
|
||||||
|
|
@ -2670,18 +2674,12 @@ Session::change_source_path_by_name (string path, string oldname, string newname
|
||||||
the task here is to replace NAME with the new name.
|
the task here is to replace NAME with the new name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* find last slash */
|
|
||||||
|
|
||||||
string dir;
|
string dir;
|
||||||
string prefix;
|
string prefix;
|
||||||
string::size_type slash;
|
|
||||||
string::size_type dash;
|
string::size_type dash;
|
||||||
|
|
||||||
if ((slash = path.find_last_of ('/')) == string::npos) {
|
dir = Glib::path_get_dirname (path);
|
||||||
return "";
|
path = Glib::path_get_basename (path);
|
||||||
}
|
|
||||||
|
|
||||||
dir = path.substr (0, slash+1);
|
|
||||||
|
|
||||||
/* '-' is not a legal character for the NAME part of the path */
|
/* '-' is not a legal character for the NAME part of the path */
|
||||||
|
|
||||||
|
|
@ -2689,7 +2687,7 @@ Session::change_source_path_by_name (string path, string oldname, string newname
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix = path.substr (slash+1, dash-(slash+1));
|
prefix = path.substr (0, dash);
|
||||||
|
|
||||||
path = dir;
|
path = dir;
|
||||||
path += prefix;
|
path += prefix;
|
||||||
|
|
@ -2708,17 +2706,11 @@ Session::change_source_path_by_name (string path, string oldname, string newname
|
||||||
|
|
||||||
string dir;
|
string dir;
|
||||||
string suffix;
|
string suffix;
|
||||||
string::size_type slash;
|
|
||||||
string::size_type dash;
|
string::size_type dash;
|
||||||
string::size_type postfix;
|
string::size_type postfix;
|
||||||
|
|
||||||
/* find last slash */
|
dir = Glib::path_get_dirname (path);
|
||||||
|
path = Glib::path_get_basename (path);
|
||||||
if ((slash = path.find_last_of ('/')) == string::npos) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = path.substr (0, slash+1);
|
|
||||||
|
|
||||||
/* '-' is not a legal character for the NAME part of the path */
|
/* '-' is not a legal character for the NAME part of the path */
|
||||||
|
|
||||||
|
|
@ -2750,7 +2742,7 @@ Session::change_source_path_by_name (string path, string oldname, string newname
|
||||||
|
|
||||||
snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
|
snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
|
||||||
|
|
||||||
if (access (buf, F_OK) != 0) {
|
if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
|
||||||
path = buf;
|
path = buf;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2771,7 +2763,7 @@ Session::change_source_path_by_name (string path, string oldname, string newname
|
||||||
* (e.g. as returned by new_*_source_name)
|
* (e.g. as returned by new_*_source_name)
|
||||||
*/
|
*/
|
||||||
string
|
string
|
||||||
Session::new_source_path_from_name (DataType type, const string& name)
|
Session::new_source_path_from_name (DataType type, const string& name, bool as_stub)
|
||||||
{
|
{
|
||||||
assert(name.find("/") == string::npos);
|
assert(name.find("/") == string::npos);
|
||||||
|
|
||||||
|
|
@ -2779,9 +2771,9 @@ Session::new_source_path_from_name (DataType type, const string& name)
|
||||||
|
|
||||||
sys::path p;
|
sys::path p;
|
||||||
if (type == DataType::AUDIO) {
|
if (type == DataType::AUDIO) {
|
||||||
p = sdir.sound_path();
|
p = (as_stub ? sdir.sound_stub_path() : sdir.sound_path());
|
||||||
} else if (type == DataType::MIDI) {
|
} else if (type == DataType::MIDI) {
|
||||||
p = sdir.midi_path();
|
p = (as_stub ? sdir.midi_stub_path() : sdir.midi_path());
|
||||||
} else {
|
} else {
|
||||||
error << "Unknown source type, unable to create file path" << endmsg;
|
error << "Unknown source type, unable to create file path" << endmsg;
|
||||||
return "";
|
return "";
|
||||||
|
|
@ -2889,10 +2881,10 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
|
||||||
|
|
||||||
/** Create a new within-session audio source */
|
/** Create a new within-session audio source */
|
||||||
boost::shared_ptr<AudioFileSource>
|
boost::shared_ptr<AudioFileSource>
|
||||||
Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive)
|
Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive, bool as_stub)
|
||||||
{
|
{
|
||||||
const string name = new_audio_source_name (n, n_chans, chan, destructive);
|
const string name = new_audio_source_name (n, n_chans, chan, destructive);
|
||||||
const string path = new_source_path_from_name(DataType::AUDIO, name);
|
const string path = new_source_path_from_name(DataType::AUDIO, name, as_stub);
|
||||||
|
|
||||||
return boost::dynamic_pointer_cast<AudioFileSource> (
|
return boost::dynamic_pointer_cast<AudioFileSource> (
|
||||||
SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
|
SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
|
||||||
|
|
@ -2949,7 +2941,7 @@ Session::new_midi_source_name (const string& base)
|
||||||
|
|
||||||
/** Create a new within-session MIDI source */
|
/** Create a new within-session MIDI source */
|
||||||
boost::shared_ptr<MidiSource>
|
boost::shared_ptr<MidiSource>
|
||||||
Session::create_midi_source_for_session (Track* track, string const & n)
|
Session::create_midi_source_for_session (Track* track, string const & n, bool as_stub)
|
||||||
{
|
{
|
||||||
/* try to use the existing write source for the track, to keep numbering sane
|
/* try to use the existing write source for the track, to keep numbering sane
|
||||||
*/
|
*/
|
||||||
|
|
@ -2968,7 +2960,7 @@ Session::create_midi_source_for_session (Track* track, string const & n)
|
||||||
}
|
}
|
||||||
|
|
||||||
const string name = new_midi_source_name (n);
|
const string name = new_midi_source_name (n);
|
||||||
const string path = new_source_path_from_name (DataType::MIDI, name);
|
const string path = new_source_path_from_name (DataType::MIDI, name, as_stub);
|
||||||
|
|
||||||
return boost::dynamic_pointer_cast<SMFSource> (
|
return boost::dynamic_pointer_cast<SMFSource> (
|
||||||
SourceFactory::createWritable (
|
SourceFactory::createWritable (
|
||||||
|
|
@ -3067,42 +3059,6 @@ Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::
|
||||||
return a->order_key(N_("signal")) < b->order_key(N_("signal"));
|
return a->order_key(N_("signal")) < b->order_key(N_("signal"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Session::remove_empty_sounds ()
|
|
||||||
{
|
|
||||||
vector<string> audio_filenames;
|
|
||||||
|
|
||||||
get_files_in_directory (_session_dir->sound_path(), audio_filenames);
|
|
||||||
|
|
||||||
Glib::Mutex::Lock lm (source_lock);
|
|
||||||
|
|
||||||
TapeFileMatcher tape_file_matcher;
|
|
||||||
|
|
||||||
remove_if (audio_filenames.begin(), audio_filenames.end(),
|
|
||||||
boost::bind (&TapeFileMatcher::matches, &tape_file_matcher, _1));
|
|
||||||
|
|
||||||
for (vector<string>::iterator i = audio_filenames.begin(); i != audio_filenames.end(); ++i) {
|
|
||||||
|
|
||||||
sys::path audio_file_path (_session_dir->sound_path());
|
|
||||||
|
|
||||||
audio_file_path /= *i;
|
|
||||||
|
|
||||||
if (AudioFileSource::is_empty (*this, audio_file_path.to_string())) {
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sys::remove (audio_file_path);
|
|
||||||
const string peakfile = peak_path (audio_file_path.to_string());
|
|
||||||
sys::remove (peakfile);
|
|
||||||
}
|
|
||||||
catch (const sys::filesystem_error& err)
|
|
||||||
{
|
|
||||||
error << err.what() << endmsg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Session::is_auditioning () const
|
Session::is_auditioning () const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -101,12 +101,27 @@ SessionDirectory::sound_path () const
|
||||||
return sources_root() / sound_dir_name;
|
return sources_root() / sound_dir_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const path
|
||||||
|
SessionDirectory::sound_stub_path () const
|
||||||
|
{
|
||||||
|
if(is_directory (old_sound_path ())) return old_sound_path();
|
||||||
|
|
||||||
|
// the new style sound directory
|
||||||
|
return sources_root() / sound_dir_name / stub_dir_name;
|
||||||
|
}
|
||||||
|
|
||||||
const path
|
const path
|
||||||
SessionDirectory::midi_path () const
|
SessionDirectory::midi_path () const
|
||||||
{
|
{
|
||||||
return sources_root() / midi_dir_name;
|
return sources_root() / midi_dir_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const path
|
||||||
|
SessionDirectory::midi_stub_path () const
|
||||||
|
{
|
||||||
|
return sources_root() / midi_dir_name / stub_dir_name;
|
||||||
|
}
|
||||||
|
|
||||||
const path
|
const path
|
||||||
SessionDirectory::midi_patch_path () const
|
SessionDirectory::midi_patch_path () const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_VFS_H
|
#ifdef HAVE_SYS_VFS_H
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
|
|
@ -66,6 +65,7 @@
|
||||||
#include "pbd/search_path.h"
|
#include "pbd/search_path.h"
|
||||||
#include "pbd/stacktrace.h"
|
#include "pbd/stacktrace.h"
|
||||||
#include "pbd/convert.h"
|
#include "pbd/convert.h"
|
||||||
|
#include "pbd/clear_dir.h"
|
||||||
|
|
||||||
#include "ardour/amp.h"
|
#include "ardour/amp.h"
|
||||||
#include "ardour/audio_diskstream.h"
|
#include "ardour/audio_diskstream.h"
|
||||||
|
|
@ -288,7 +288,7 @@ Session::second_stage_init ()
|
||||||
if (load_state (_current_snapshot_name)) {
|
if (load_state (_current_snapshot_name)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
remove_empty_sounds ();
|
cleanup_stubfiles ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_butler->start_thread()) {
|
if (_butler->start_thread()) {
|
||||||
|
|
@ -460,6 +460,13 @@ Session::ensure_subdirs ()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dir = session_directory().sound_stub_path().to_string();
|
||||||
|
|
||||||
|
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||||
|
error << string_compose(_("Session: cannot create session stub sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
dir = session_directory().midi_path().to_string();
|
dir = session_directory().midi_path().to_string();
|
||||||
|
|
||||||
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||||
|
|
@ -467,6 +474,13 @@ Session::ensure_subdirs ()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dir = session_directory().midi_stub_path().to_string();
|
||||||
|
|
||||||
|
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||||
|
error << string_compose(_("Session: cannot create session stub midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
dir = session_directory().dead_sound_path().to_string();
|
dir = session_directory().dead_sound_path().to_string();
|
||||||
|
|
||||||
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
|
||||||
|
|
@ -1595,14 +1609,10 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if ( !type || type->value() == "audio" ) {
|
if (!type || type->value() == "audio") {
|
||||||
|
|
||||||
return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
|
return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
|
||||||
|
|
||||||
} else if (type->value() == "midi") {
|
} else if (type->value() == "midi") {
|
||||||
|
|
||||||
return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
|
return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (failed_constructor& err) {
|
} catch (failed_constructor& err) {
|
||||||
|
|
@ -1738,24 +1748,16 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
|
||||||
boost::shared_ptr<Source> source;
|
boost::shared_ptr<Source> source;
|
||||||
boost::shared_ptr<MidiSource> ms;
|
boost::shared_ptr<MidiSource> ms;
|
||||||
SourceList sources;
|
SourceList sources;
|
||||||
uint32_t nchans = 1;
|
|
||||||
|
|
||||||
if (node.name() != X_("Region")) {
|
if (node.name() != X_("Region")) {
|
||||||
return boost::shared_ptr<MidiRegion>();
|
return boost::shared_ptr<MidiRegion>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prop = node.property (X_("channels"))) != 0) {
|
|
||||||
nchans = atoi (prop->value().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((prop = node.property ("name")) == 0) {
|
if ((prop = node.property ("name")) == 0) {
|
||||||
cerr << "no name for this region\n";
|
cerr << "no name for this region\n";
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiple midi channels? that's just crazy talk
|
|
||||||
assert(nchans == 1);
|
|
||||||
|
|
||||||
if ((prop = node.property (X_("source-0"))) == 0) {
|
if ((prop = node.property (X_("source-0"))) == 0) {
|
||||||
if ((prop = node.property ("source")) == 0) {
|
if ((prop = node.property ("source")) == 0) {
|
||||||
error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
|
error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
|
||||||
|
|
@ -2339,6 +2341,10 @@ Session::commit_reversible_command(Command *cmd)
|
||||||
static bool
|
static bool
|
||||||
accept_all_non_peak_files (const string& path, void */*arg*/)
|
accept_all_non_peak_files (const string& path, void */*arg*/)
|
||||||
{
|
{
|
||||||
|
if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
|
return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2710,9 +2716,6 @@ Session::cleanup_trash_sources (CleanupReport& rep)
|
||||||
|
|
||||||
vector<space_and_path>::iterator i;
|
vector<space_and_path>::iterator i;
|
||||||
string dead_sound_dir;
|
string dead_sound_dir;
|
||||||
struct dirent* dentry;
|
|
||||||
struct stat statbuf;
|
|
||||||
DIR* dead;
|
|
||||||
|
|
||||||
rep.paths.clear ();
|
rep.paths.clear ();
|
||||||
rep.space = 0;
|
rep.space = 0;
|
||||||
|
|
@ -2722,50 +2725,51 @@ Session::cleanup_trash_sources (CleanupReport& rep)
|
||||||
dead_sound_dir = (*i).path;
|
dead_sound_dir = (*i).path;
|
||||||
dead_sound_dir += dead_sound_dir_name;
|
dead_sound_dir += dead_sound_dir_name;
|
||||||
|
|
||||||
if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
|
clear_directory (dead_sound_dir, &rep.space, &rep.paths);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((dentry = readdir (dead)) != 0) {
|
|
||||||
|
|
||||||
/* avoid '.' and '..' */
|
|
||||||
|
|
||||||
if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
|
|
||||||
(dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
string fullpath;
|
|
||||||
|
|
||||||
fullpath = dead_sound_dir;
|
|
||||||
fullpath += '/';
|
|
||||||
fullpath += dentry->d_name;
|
|
||||||
|
|
||||||
if (stat (fullpath.c_str(), &statbuf)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISREG (statbuf.st_mode)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlink (fullpath.c_str())) {
|
|
||||||
error << string_compose (_("cannot remove dead sound file %1 (%2)"),
|
|
||||||
fullpath, strerror (errno))
|
|
||||||
<< endmsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
rep.paths.push_back (dentry->d_name);
|
|
||||||
rep.space += statbuf.st_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir (dead);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Session::cleanup_stubfiles ()
|
||||||
|
{
|
||||||
|
vector<space_and_path>::iterator i;
|
||||||
|
|
||||||
|
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
|
||||||
|
|
||||||
|
string dir;
|
||||||
|
string lname = legalize_for_path (_name);
|
||||||
|
|
||||||
|
vector<string> v;
|
||||||
|
|
||||||
|
/* XXX this is a hack caused by semantic conflicts
|
||||||
|
between space_and_path and the SessionDirectory concept.
|
||||||
|
*/
|
||||||
|
|
||||||
|
v.push_back ((*i).path);
|
||||||
|
v.push_back ("interchange");
|
||||||
|
v.push_back (lname);
|
||||||
|
v.push_back ("audiofiles");
|
||||||
|
v.push_back (stub_dir_name);
|
||||||
|
|
||||||
|
dir = Glib::build_filename (v);
|
||||||
|
|
||||||
|
clear_directory (dir);
|
||||||
|
|
||||||
|
v.clear ();
|
||||||
|
v.push_back ((*i).path);
|
||||||
|
v.push_back ("interchange");
|
||||||
|
v.push_back (lname);
|
||||||
|
v.push_back ("midifiles");
|
||||||
|
v.push_back (stub_dir_name);
|
||||||
|
|
||||||
|
dir = Glib::build_filename (v);
|
||||||
|
|
||||||
|
clear_directory (dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::set_dirty ()
|
Session::set_dirty ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -432,6 +432,13 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
|
DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
|
||||||
|
|
||||||
|
if (abort && did_record) {
|
||||||
|
/* no reason to save the session file when we remove sources
|
||||||
|
*/
|
||||||
|
_state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
|
||||||
|
}
|
||||||
|
|
||||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
||||||
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
|
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
|
||||||
if (tr) {
|
if (tr) {
|
||||||
|
|
@ -439,6 +446,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (abort && did_record) {
|
||||||
|
_state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
|
||||||
|
}
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,6 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
|
||||||
SMFSource::~SMFSource ()
|
SMFSource::~SMFSource ()
|
||||||
{
|
{
|
||||||
if (removable()) {
|
if (removable()) {
|
||||||
cerr << name() << " is removable, empty ? " << empty() << " UC " << use_count() << endl;
|
|
||||||
unlink (_path.c_str());
|
unlink (_path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +169,7 @@ SMFSource::read_unlocked (Evoral::EventSink<nframes_t>& destination, sframes_t s
|
||||||
assert(time >= start_ticks);
|
assert(time >= start_ticks);
|
||||||
const sframes_t ev_frame_time = converter.to(time / (double)ppqn()) + stamp_offset;
|
const sframes_t ev_frame_time = converter.to(time / (double)ppqn()) + stamp_offset;
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
cerr << " frames = " << ev_frame_time
|
cerr << " frames = " << ev_frame_time
|
||||||
<< " w/offset = " << ev_frame_time - negative_stamp_offset
|
<< " w/offset = " << ev_frame_time - negative_stamp_offset
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
@ -494,3 +493,9 @@ SMFSource::flush_midi ()
|
||||||
mark_nonremovable ();
|
mark_nonremovable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SMFSource::set_path (const string& p)
|
||||||
|
{
|
||||||
|
FileSource::set_path (p);
|
||||||
|
SMF::set_path (_path);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -889,3 +889,13 @@ SndFileSource::file_closed ()
|
||||||
|
|
||||||
touch_peakfile ();
|
touch_peakfile ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SndFileSource::set_path (const string& p)
|
||||||
|
{
|
||||||
|
FileSource::set_path (p);
|
||||||
|
|
||||||
|
if (_descriptor) {
|
||||||
|
_descriptor->set_path (_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,12 @@ Source::set_allow_remove_if_empty (bool yn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Source::inc_use_count ()
|
||||||
|
{
|
||||||
|
g_atomic_int_inc (&_use_count);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Source::dec_use_count ()
|
Source::dec_use_count ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,10 @@ public:
|
||||||
|
|
||||||
double round_to_file_precision (double val) const;
|
double round_to_file_precision (double val) const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
void set_path (const std::string& p);
|
||||||
|
|
||||||
|
private:
|
||||||
std::string _file_path;
|
std::string _file_path;
|
||||||
smf_t* _smf;
|
smf_t* _smf;
|
||||||
smf_track_t* _smf_track;
|
smf_track_t* _smf_track;
|
||||||
|
|
|
||||||
|
|
@ -90,14 +90,13 @@ SMF::open(const std::string& path, int track) THROW_FILE_ERROR
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_smf = smf_load (f);
|
if ((_smf = smf_load (f)) == 0) {
|
||||||
if (_smf == NULL) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_smf_track = smf_get_track_by_number(_smf, track);
|
if ((_smf_track = smf_get_track_by_number(_smf, track)) == 0) {
|
||||||
if (!_smf_track)
|
|
||||||
return -2;
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
//cerr << "Track " << track << " # events: " << _smf_track->number_of_events << endl;
|
//cerr << "Track " << track << " # events: " << _smf_track->number_of_events << endl;
|
||||||
if (_smf_track->number_of_events == 0) {
|
if (_smf_track->number_of_events == 0) {
|
||||||
|
|
@ -157,15 +156,22 @@ void
|
||||||
SMF::close() THROW_FILE_ERROR
|
SMF::close() THROW_FILE_ERROR
|
||||||
{
|
{
|
||||||
if (_smf) {
|
if (_smf) {
|
||||||
|
#if 0
|
||||||
|
/* XXX why would we automatically save-on-close?
|
||||||
|
*/
|
||||||
|
|
||||||
PBD::StdioFileDescriptor d (_file_path, "w+");
|
PBD::StdioFileDescriptor d (_file_path, "w+");
|
||||||
FILE* f = d.allocate ();
|
FILE* f = d.allocate ();
|
||||||
if (f == 0) {
|
if (f == 0) {
|
||||||
throw FileError ();
|
throw FileError ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "CLOSE: Save SMF to " << _file_path << endl;
|
||||||
|
|
||||||
if (smf_save(_smf, f) != 0) {
|
if (smf_save(_smf, f) != 0) {
|
||||||
throw FileError();
|
throw FileError();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
smf_delete(_smf);
|
smf_delete(_smf);
|
||||||
_smf = 0;
|
_smf = 0;
|
||||||
_smf_track = 0;
|
_smf_track = 0;
|
||||||
|
|
@ -294,5 +300,10 @@ SMF::round_to_file_precision (double val) const
|
||||||
return round (val * div) / div;
|
return round (val * div) / div;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SMF::set_path (const std::string& p)
|
||||||
|
{
|
||||||
|
_file_path = p;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Evoral
|
} // namespace Evoral
|
||||||
|
|
|
||||||
|
|
@ -100,19 +100,19 @@ FileManager::allocate (FileDescriptor* d)
|
||||||
DEBUG::FileManager,
|
DEBUG::FileManager,
|
||||||
string_compose (
|
string_compose (
|
||||||
"closed file for %1 to release file handle; now have %2 of %3 open\n",
|
"closed file for %1 to release file handle; now have %2 of %3 open\n",
|
||||||
(*oldest)->_name, _open, _max_open
|
(*oldest)->_path, _open, _max_open
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->open ()) {
|
if (d->open ()) {
|
||||||
DEBUG_TRACE (DEBUG::FileManager, string_compose ("open of %1 failed.\n", d->_name));
|
DEBUG_TRACE (DEBUG::FileManager, string_compose ("open of %1 failed.\n", d->_path));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_open++;
|
_open++;
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::FileManager, string_compose ("opened file for %1; now have %2 of %3 open.\n", d->_name, _open, _max_open));
|
DEBUG_TRACE (DEBUG::FileManager, string_compose ("opened file for %1; now have %2 of %3 open.\n", d->_path, _open, _max_open));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
|
@ -148,7 +148,7 @@ FileManager::remove (FileDescriptor* d)
|
||||||
close (d);
|
close (d);
|
||||||
DEBUG_TRACE (
|
DEBUG_TRACE (
|
||||||
DEBUG::FileManager,
|
DEBUG::FileManager,
|
||||||
string_compose ("closed file for %1; file is being removed; now have %2 of %3 open\n", d->_name, _open, _max_open)
|
string_compose ("closed file for %1; file is being removed; now have %2 of %3 open\n", d->_path, _open, _max_open)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +168,7 @@ FileManager::close (FileDescriptor* d)
|
||||||
FileDescriptor::FileDescriptor (string const & n, bool w)
|
FileDescriptor::FileDescriptor (string const & n, bool w)
|
||||||
: _refcount (0)
|
: _refcount (0)
|
||||||
, _last_used (0)
|
, _last_used (0)
|
||||||
, _name (n)
|
, _path (n)
|
||||||
, _writeable (w)
|
, _writeable (w)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -224,7 +224,7 @@ FdFileDescriptor::open ()
|
||||||
{
|
{
|
||||||
/* we must have a lock on the FileManager's mutex */
|
/* we must have a lock on the FileManager's mutex */
|
||||||
|
|
||||||
_fd = ::open (_name.c_str(), _writeable ? (O_RDWR | O_CREAT) : O_RDONLY, _mode);
|
_fd = ::open (_path.c_str(), _writeable ? (O_RDWR | O_CREAT) : O_RDONLY, _mode);
|
||||||
return (_fd == -1);
|
return (_fd == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,6 +253,13 @@ FdFileDescriptor::allocate ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FileDescriptor::set_path (const string& p)
|
||||||
|
{
|
||||||
|
assert (!is_open());
|
||||||
|
_path = p;
|
||||||
|
}
|
||||||
|
|
||||||
/** @param n Filename.
|
/** @param n Filename.
|
||||||
* @param w true to open writeable, otherwise false.
|
* @param w true to open writeable, otherwise false.
|
||||||
*/
|
*/
|
||||||
|
|
@ -283,7 +290,7 @@ StdioFileDescriptor::open ()
|
||||||
{
|
{
|
||||||
/* we must have a lock on the FileManager's mutex */
|
/* we must have a lock on the FileManager's mutex */
|
||||||
|
|
||||||
_file = fopen (_name.c_str(), _mode.c_str());
|
_file = fopen (_path.c_str(), _mode.c_str());
|
||||||
return (_file == 0);
|
return (_file == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,10 @@ public:
|
||||||
FileDescriptor (std::string const &, bool);
|
FileDescriptor (std::string const &, bool);
|
||||||
virtual ~FileDescriptor () {}
|
virtual ~FileDescriptor () {}
|
||||||
|
|
||||||
|
const std::string& path() const { return _path; }
|
||||||
|
|
||||||
void release ();
|
void release ();
|
||||||
|
virtual void set_path (const std::string&);
|
||||||
|
|
||||||
/** Emitted when the file is closed */
|
/** Emitted when the file is closed */
|
||||||
PBD::Signal0<void> Closed;
|
PBD::Signal0<void> Closed;
|
||||||
|
|
@ -71,7 +74,7 @@ protected:
|
||||||
|
|
||||||
int _refcount; ///< number of active users of this file
|
int _refcount; ///< number of active users of this file
|
||||||
double _last_used; ///< monotonic time that this file was last allocated
|
double _last_used; ///< monotonic time that this file was last allocated
|
||||||
std::string _name; ///< filename
|
std::string _path; ///< file path
|
||||||
bool _writeable; ///< true if it should be opened writeable, otherwise false
|
bool _writeable; ///< true if it should be opened writeable, otherwise false
|
||||||
|
|
||||||
FileManager* manager ();
|
FileManager* manager ();
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ SndFileDescriptor::open ()
|
||||||
{
|
{
|
||||||
/* we must have a lock on the FileManager's mutex */
|
/* we must have a lock on the FileManager's mutex */
|
||||||
|
|
||||||
_sndfile = sf_open (_name.c_str(), _writeable ? SFM_RDWR : SFM_READ, _info);
|
_sndfile = sf_open (_path.c_str(), _writeable ? SFM_RDWR : SFM_READ, _info);
|
||||||
return (_sndfile == 0);
|
return (_sndfile == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ def build(bld):
|
||||||
convert.cc
|
convert.cc
|
||||||
controllable.cc
|
controllable.cc
|
||||||
controllable_descriptor.cc
|
controllable_descriptor.cc
|
||||||
|
clear_dir.cc
|
||||||
crossthread.cc
|
crossthread.cc
|
||||||
cpus.cc
|
cpus.cc
|
||||||
debug.cc
|
debug.cc
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue