#!/bin/sh
source `dirname "$0"`/ardev_common.sh
-exec gtk2_ardour/ardour.bin --novst "$*"
+exec gtk2_ardour/ardour.bin --novst $*
void
ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
{
+ string session_name;
+ string session_path;
+
int response = Gtk::RESPONSE_NONE;
new_session_dialog->set_modal(true);
new_session_dialog->reset();
} else if (response == Gtk::RESPONSE_YES) {
- /* YES == OPEN, but there's no enum for that */
- std::string session_name = new_session_dialog->session_name();
- std::string session_path = new_session_dialog->session_folder();
- load_session (session_path, session_name);
+ /* YES == OPEN, but there's no enum for that */
+ session_name = new_session_dialog->session_name();
+
+ if (session_name.empty()) {
+ response = Gtk::RESPONSE_NONE;
+ cerr << "session name is empty\n";
+ continue;
+ }
+
+ if (session_name[0] == '/' ||
+ (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+ (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+ load_session (Glib::path_get_dirname (session_name), session_name);
+ } else {
+ session_path = new_session_dialog->session_folder();
+ load_session (session_path, session_name);
+ }
} else if (response == Gtk::RESPONSE_OK) {
+
if (new_session_dialog->get_current_page() == 1) {
/* XXX this is a bit of a hack..
if we're on page 1 (the load page)
Unfortunately i can't see how atm..
*/
-
- std::string session_name = new_session_dialog->session_name();
- std::string session_path = new_session_dialog->session_folder();
- load_session (session_path, session_name);
-
+
+ if (session_name.empty()) {
+ response = Gtk::RESPONSE_NONE;
+ cerr << "session name is empty 2\n";
+ continue;
+ }
+
+ if (session_name[0] == '/' ||
+ (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+ (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+ load_session (Glib::path_get_dirname (session_name), session_name);
+ } else {
+ session_path = new_session_dialog->session_folder();
+ load_session (session_path, session_name);
+ }
+
} else {
_session_is_new = true;
- std::string session_name = new_session_dialog->session_name();
- std::string session_path = new_session_dialog->session_folder();
+ session_name = new_session_dialog->session_name();
+ if (session_name.empty()) {
+ response = Gtk::RESPONSE_NONE;
+ cerr << "session name is empty 3\n";
+ continue;
+ }
+
+ if (session_name[0] == '/' ||
+ (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+ (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+
+ session_path = Glib::path_get_dirname (session_name);
+ session_name = Glib::path_get_basename (session_name);
+
+ } else {
+
+ std::string session_path = new_session_dialog->session_folder();
+
+ }
//XXX This is needed because session constructor wants a
//non-existant path. hopefully this will be fixed at some point.
-
- session_path = Glib::build_filename(session_path, session_name);
-
+
+ session_path = Glib::build_filename (session_path, session_name);
+
std::string template_name = new_session_dialog->session_template_name();
-
+
if (new_session_dialog->use_session_template()) {
-
- load_session (session_path, session_name, &template_name);
+
+ load_session (session_path, session_name, &template_name);
} else {
-
- uint32_t cchns;
+
+ uint32_t cchns;
uint32_t mchns;
Session::AutoConnectOption iconnect;
Session::AutoConnectOption oconnect;
-
+
if (new_session_dialog->create_control_bus()) {
- cchns = (uint32_t) new_session_dialog->control_channel_count();
+ cchns = (uint32_t) new_session_dialog->control_channel_count();
} else {
- cchns = 0;
+ cchns = 0;
}
-
+
if (new_session_dialog->create_master_bus()) {
- mchns = (uint32_t) new_session_dialog->master_channel_count();
+ mchns = (uint32_t) new_session_dialog->master_channel_count();
} else {
- mchns = 0;
+ mchns = 0;
}
-
+
if (new_session_dialog->connect_inputs()) {
- iconnect = Session::AutoConnectPhysical;
+ iconnect = Session::AutoConnectPhysical;
} else {
- iconnect = Session::AutoConnectOption (0);
+ iconnect = Session::AutoConnectOption (0);
}
-
+
/// @todo some minor tweaks.
-
+
if (new_session_dialog->connect_outs_to_master()) {
- oconnect = Session::AutoConnectMaster;
+ oconnect = Session::AutoConnectMaster;
} else if (new_session_dialog->connect_outs_to_physical()) {
- oconnect = Session::AutoConnectPhysical;
+ oconnect = Session::AutoConnectPhysical;
} else {
- oconnect = Session::AutoConnectOption (0);
+ oconnect = Session::AutoConnectOption (0);
}
-
+
uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
-
+
build_session (session_path,
- session_name,
- cchns,
- mchns,
- iconnect,
- oconnect,
- nphysin,
- nphysout,
- engine->frame_rate() * 60 * 5);
+ session_name,
+ cchns,
+ mchns,
+ iconnect,
+ oconnect,
+ nphysin,
+ nphysout,
+ engine->frame_rate() * 60 * 5);
}
- }
+ }
}
} while (response == Gtk::RESPONSE_NONE);
+
show();
new_session_dialog->get_window()->set_cursor();
-
new_session_dialog->hide();
}
void
ARDOUR_UI::close_session()
{
- unload_session();
- new_session ();
+ unload_session();
+ new_session ();
}
int
{
editor->connect_to_session (s);
mixer->connect_to_session (s);
+
+ /* its safe to do this now */
+
+ s->restore_history (s->snap_name());
}
void
use_rec_regions = tv.editor.show_waveforms_recording ();
last_rec_peak_frame = 0;
+
}
AudioStreamView::~AudioStreamView ()
XMLNode& get_state (void);
int set_state (const XMLNode&);
- PBD::ID id() { return _id; }
protected:
- PBD::ID _id;
+
string _name;
guint32 _height;
uint32_t _line_color;
}
/* register for undo history */
+
session->register_with_memento_command_factory(_id, this);
}
int x, y, xoff, yoff;
Gdk::Geometry g;
+ if ((prop = node.property ("id")) != 0) {
+ _id = prop->value ();
+ }
if ((geometry = find_named_node (node, "geometry")) == 0) {
XMLNode* node = new XMLNode ("Editor");
char buf[32];
+ _id.print (buf);
+ node->add_property ("id", buf);
+
if (is_realized()) {
Glib::RefPtr<Gdk::Window> win = get_window();
win->get_size(width, height);
XMLNode* geometry = new XMLNode ("geometry");
- char buf[32];
+
snprintf(buf, sizeof(buf), "%d", width);
geometry->add_property("x_size", string(buf));
snprintf(buf, sizeof(buf), "%d", height);
XMLNode& get_state ();
int set_state (const XMLNode& );
- PBD::ID id() { return _id; }
-
void set_mouse_mode (Editing::MouseMode, bool force=true);
void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () { return mouse_mode; }
ARDOUR::AudioEngine& engine;
bool constructed;
- PBD::ID _id;
-
PlaylistSelector* _playlist_selector;
void set_frames_per_unit (double);
idspec += string_compose(":%1", n);
try {
- source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
+ source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, idspec, (mode == ImportAsTrack ? AudioFileSource::Destructive : AudioFileSource::Flag (0))));
sources.push_back(source);
}
try {
- fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path, AudioFileSource::Flag (0)));
+ fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, path, AudioFileSource::Flag (0)));
}
catch (failed_constructor& err) {
path = s;
try {
- fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path, AudioFileSource::Flag (0)));
+ fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*session, path, AudioFileSource::Flag (0)));
}
catch (failed_constructor& err) {
void remove_point (ControlPoint&);
- PBD::ID id() { return _id; }
-
private:
ARDOUR::Session& session;
AudioRegionView& rv;
UndoAction get_memento();
-
- PBD::ID _id;
};
for (int n = 0; n < sf_info.channels; ++n) {
try {
- afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
+ afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (*_session, path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
srclist.push_back(afs);
} catch (failed_constructor& err) {
AudioDiskstream (Session &, const XMLNode&);
~AudioDiskstream();
- const PBD::ID& id() const { return _id; }
-
float playback_buffer_load() const;
float capture_buffer_load() const;
int move_to_trash (const string trash_dir_name);
- static bool is_empty (string path);
+ static bool is_empty (Session&, string path);
void mark_streaming_write_completed ();
void mark_take (string);
/* constructor to be called for existing external-to-session files */
- AudioFileSource (std::string path, Flag flags);
+ AudioFileSource (Session&, std::string path, Flag flags);
/* constructor to be called for new in-session files */
- AudioFileSource (std::string path, Flag flags,
+ AudioFileSource (Session&, std::string path, Flag flags,
SampleFormat samp_format, HeaderFormat hdr_format);
/* constructor to be called for existing in-session files */
- AudioFileSource (const XMLNode&);
+ AudioFileSource (Session&, const XMLNode&);
int init (string idstr, bool must_exist);
bool region_changed (Change, boost::shared_ptr<Region>);
void crossfade_changed (Change);
void add_crossfade (Crossfade&);
+
+ void source_offset_changed (boost::shared_ptr<AudioRegion> region);
};
} /* namespace ARDOUR */
void recompute_at_end ();
void envelope_changed (Change);
+ void source_offset_changed ();
void source_deleted (boost::shared_ptr<Source>);
class AudioSource : public Source
{
public:
- AudioSource (string name);
- AudioSource (const XMLNode&);
+ AudioSource (Session&, string name);
+ AudioSource (Session&, const XMLNode&);
virtual ~AudioSource ();
/* one could argue that this should belong to Source, but other data types
XMLNode &get_state(void);
int set_state (const XMLNode &s);
- PBD::ID id() { return _id; }
-
void set_max_xval (double);
double get_max_xval() const { return max_xval; }
static sigc::signal<void, AutomationList*> AutomationListCreated;
protected:
- PBD::ID _id;
+
struct State : public ARDOUR::StateManager::State {
AutomationEventList events;
class DestructiveFileSource : public SndFileSource {
public:
- DestructiveFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
+ DestructiveFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable));
- DestructiveFileSource (std::string path, Flag flags);
+ DestructiveFileSource (Session&, std::string path, Flag flags);
- DestructiveFileSource (const XMLNode&);
+ DestructiveFileSource (Session&, const XMLNode&);
~DestructiveFileSource ();
jack_nframes_t last_capture_start_frame() const;
bool destructive() const { return _flags & Destructive; }
virtual void set_destructive (bool yn);
- const PBD::ID& id() const { return _id; }
bool hidden() const { return _flags & Hidden; }
bool recordable() const { return _flags & Recordable; }
bool reversed() const { return _actual_speed < 0.0f; }
ARDOUR::Session& _session;
ARDOUR::IO* _io;
uint32_t _n_channels;
- PBD::ID _id;
Playlist* _playlist;
mutable gint _record_enabled;
void start_pan_touch (uint32_t which);
void end_pan_touch (uint32_t which);
- const PBD::ID& id() const { return _id; }
-
void defer_pan_reset ();
void allow_pan_reset ();
string _name;
Connection* _input_connection;
Connection* _output_connection;
- PBD::ID _id;
bool no_panner_reset;
XMLNode* deferred_state;
DataType _default_type;
XMLNode& get_state (void);
int set_state (const XMLNode&);
- PBD::ID id() { return _id; }
-
private:
- PBD::ID _id;
string _name;
jack_nframes_t _start;
jack_nframes_t _end;
XMLNode& get_state (void);
int set_state (const XMLNode&);
- PBD::ID id() { return _id; }
Location *get_location_by_id(PBD::ID);
Location* auto_loop_location () const;
Change restore_state (StateManager::State&);
StateManager::State* state_factory (std::string why) const;
-
- PBD::ID _id;
};
} // namespace ARDOUR
EditMode get_edit_mode() const { return _edit_mode; }
void set_edit_mode (EditMode);
- PBD::ID id() { return _id; }
/* Editing operations */
void add_region (boost::shared_ptr<Region>, jack_nframes_t position, float times = 1, bool with_save = true);
void unset_freeze_child (Playlist*);
void timestamp_layer_op (boost::shared_ptr<Region>);
-
- PBD::ID _id;
};
} /* namespace ARDOUR */
namespace ARDOUR {
class Playlist;
-class Source;
enum RegionEditState {
EditChangesNothing = 0,
virtual ~Region();
- const PBD::ID& id() const { return _id; }
-
/* Note: changing the name of a Region does not constitute an edit */
string name() const { return _name; }
mutable RegionEditState _first_edit;
int _frozen;
Glib::Mutex lock;
- PBD::ID _id;
ARDOUR::Playlist* _playlist;
mutable uint32_t _read_data_count; // modified in read()
Change pending_changed;
bool dirty() const { return _state_of_the_state & Dirty; }
sigc::signal<void> DirtyChanged;
- std::string sound_dir () const;
- std::string tape_dir () const;
+ std::string sound_dir (bool with_path = true) const;
std::string peak_dir () const;
std::string dead_sound_dir () const;
std::string automation_dir () const;
+ string peak_path_from_audio_path (string) const;
+
static string suffixed_search_path (std::string suffix, bool data);
static string control_protocol_path ();
static string template_path ();
static void get_template_list (list<string>&);
static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
- static string peak_path_from_audio_path (string);
string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
void process (jack_nframes_t nframes);
uint32_t _total_free_4k_blocks;
Glib::Mutex space_lock;
+ static const char* old_sound_dir_name;
static const char* sound_dir_name;
- static const char* tape_dir_name;
static const char* dead_sound_dir_name;
+ static const char* interchange_dir_name;
static const char* peak_dir_name;
string discover_best_sound_dir (bool destructive = false);
public:
/* constructor to be called for existing external-to-session files */
- SndFileSource (std::string path, Flag flags);
+ SndFileSource (Session&, std::string path, Flag flags);
/* constructor to be called for new in-session files */
- SndFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
+ SndFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
AudioFileSource::Removable|
AudioFileSource::RemovableIfEmpty|
/* constructor to be called for existing in-session files */
- SndFileSource (const XMLNode&);
+ SndFileSource (Session&, const XMLNode&);
~SndFileSource ();
namespace ARDOUR {
+class Session;
+
class Source : public PBD::StatefulDestructible, public sigc::trackable
{
public:
- Source (std::string name);
- Source (const XMLNode&);
+ Source (Session&, std::string name);
+ Source (Session&, const XMLNode&);
virtual ~Source ();
std::string name() const { return _name; }
int set_name (std::string str, bool destructive);
- const PBD::ID& id() const { return _id; }
-
time_t timestamp() const { return _timestamp; }
void stamp (time_t when) { _timestamp = when; }
protected:
+ Session& _session;
string _name;
time_t _timestamp;
private:
- PBD::ID _id;
};
}
namespace ARDOUR {
+class Session;
+
class SourceFactory {
public:
static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
- static boost::shared_ptr<Source> create (const XMLNode& node);
+ static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
// MIDI sources will have to be hacked in here somehow
- static boost::shared_ptr<Source> createReadable (std::string idstr, AudioFileSource::Flag flags, bool announce = true);
- static boost::shared_ptr<Source> createWritable (std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
+ static boost::shared_ptr<Source> createReadable (Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
+ static boost::shared_ptr<Source> createWritable (Session&, std::string name, bool destructive, jack_nframes_t rate, bool announce = true);
};
}
XMLNode& get_state (void);
int set_state (const XMLNode&);
- PBD::ID id() { return _id; }
void dump (std::ostream&) const;
void clear ();
void save_state (std::string why);
- PBD::ID _id;
-
};
}; /* namespace ARDOUR */
if (chan.write_source) {
- if (AudioFileSource::is_empty (chan.write_source->path())) {
+ if (AudioFileSource::is_empty (_session, chan.write_source->path())) {
chan.write_source->mark_for_remove ();
chan.write_source.reset ();
} else {
}
try {
- fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (prop->value(), false, _session.frame_rate()));
+ fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (_session, prop->value(), false, _session.frame_rate()));
}
catch (failed_constructor& err) {
char AudioFileSource::bwf_organization_code[4] = "LAS";
char AudioFileSource::bwf_serial_number[13] = "000000000000";
-AudioFileSource::AudioFileSource (string idstr, Flag flags)
- : AudioSource (idstr), _flags (flags)
+AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
+ : AudioSource (s, idstr), _flags (flags)
{
/* constructor used for existing external to session files. file must exist already */
}
-AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
- : AudioSource (path), _flags (flags)
+AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
+ : AudioSource (s, path), _flags (flags)
{
/* constructor used for new internal-to-session files. file cannot exist */
}
}
-AudioFileSource::AudioFileSource (const XMLNode& node)
- : AudioSource (node), _flags (Flag (Writable|CanRename))
+AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
+ : AudioSource (s, node), _flags (Flag (Writable|CanRename))
{
/* constructor used for existing internal-to-session files. file must exist */
bool
AudioFileSource::removable () const
{
- return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && is_empty (_path)));
+ return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && is_empty (_session, _path)));
}
int
string
AudioFileSource::peak_path (string audio_path)
{
- return Session::peak_path_from_audio_path (audio_path);
+ return _session.peak_path_from_audio_path (audio_path);
}
string
}
bool
-AudioFileSource::is_empty (string path)
+AudioFileSource::is_empty (Session& s, string path)
{
bool ret = false;
- boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (path, NoPeakFile, false));
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (s, path, NoPeakFile, false));
if (afs) {
ret = (afs->length() == 0);
}
try {
- nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> (SourceFactory::createWritable (path, false, session.frame_rate())));
+ nsrcs.push_back (boost::dynamic_pointer_cast<AudioSource> (SourceFactory::createWritable (session, path, false, session.frame_rate())));
}
catch (failed_constructor& err) {
#include <ardour/dB.h>
#include <ardour/playlist.h>
#include <ardour/audiofilter.h>
-#include <ardour/audiosource.h>
+#include <ardour/audiofilesource.h>
#include "i18n.h"
#include <locale.h>
master_sources.push_back (src);
src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src));
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+
_scale_amplitude = 1.0;
set_default_fades ();
master_sources.push_back (src);
src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src));
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+
_scale_amplitude = 1.0;
set_default_fades ();
sources.push_back (*i);
master_sources.push_back (*i);
(*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), (*i)));
+
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
}
_scale_amplitude = 1.0;
for (SourceList::const_iterator i= other->sources.begin(); i != other->sources.end(); ++i) {
sources.push_back (*i);
(*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i));
- unique_srcs.insert (*i);
+
+ pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
+
+ result = unique_srcs.insert (*i);
+
+ if (result.second) {
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+ }
}
for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) {
for (SourceList::const_iterator i = other->sources.begin(); i != other->sources.end(); ++i) {
sources.push_back (*i);
(*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i));
- unique_srcs.insert (*i);
+ pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
+
+ result = unique_srcs.insert (*i);
+
+ if (result.second) {
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+ }
}
for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) {
master_sources.push_back (src);
src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src));
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+
set_default_fades ();
if (set_state (node)) {
for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) {
sources.push_back (*i);
(*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i));
- unique_srcs.insert (*i);
+ pair<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
+
+ result = unique_srcs.insert (*i);
+
+ if (result.second) {
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*i);
+ if (afs) {
+ afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed));
+ }
+ }
}
for (SourceList::iterator i = srcs.begin(); i != srcs.end(); ++i) {
return fsr != sr;
}
+void
+AudioRegion::source_offset_changed ()
+{
+ set_position (source()->natural_position() + start(), this);
+}
+
extern "C" {
int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit)
bool AudioSource::_build_missing_peakfiles = false;
bool AudioSource::_build_peakfiles = false;
-AudioSource::AudioSource (string name)
- : Source (name)
+AudioSource::AudioSource (Session& s, string name)
+ : Source (s, name)
{
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;
_write_data_count = 0;
}
-AudioSource::AudioSource (const XMLNode& node)
- : Source (node)
+AudioSource::AudioSource (Session& s, const XMLNode& node)
+ : Source (s, node)
{
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;
gain_t* DestructiveFileSource::in_coefficient = 0;
jack_nframes_t DestructiveFileSource::xfade_frames = 64;
-DestructiveFileSource::DestructiveFileSource (string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
- : SndFileSource (path, samp_format, hdr_format, rate, flags)
+DestructiveFileSource::DestructiveFileSource (Session& s, string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
+ : SndFileSource (s, path, samp_format, hdr_format, rate, flags)
{
init ();
}
-DestructiveFileSource::DestructiveFileSource (string path, Flag flags)
- : SndFileSource (path, flags)
+DestructiveFileSource::DestructiveFileSource (Session& s, string path, Flag flags)
+ : SndFileSource (s, path, flags)
{
init ();
}
-DestructiveFileSource::DestructiveFileSource (const XMLNode& node)
- : SndFileSource (node)
+DestructiveFileSource::DestructiveFileSource (Session& s, const XMLNode& node)
+ : SndFileSource (s, node)
{
init ();
}
/* create it if necessary */
- mkdir (path.c_str (), 0755);
+ if (g_mkdir_with_parents (path.c_str (), 0755)) {
+ throw exception ();
+ }
return path;
}
} while ( !goodfile);
try {
- newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (buf, false, frame_rate()));
+ newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, buf, false, frame_rate()));
}
catch (failed_constructor& err) {
#include <algorithm>
#include <unistd.h>
#include <locale.h>
+#include <errno.h>
#include <sigc++/bind.h>
fullpath += path;
in.open (fullpath.c_str());
if (!in) {
- error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
- return -1;
+ error << string_compose(_("%1: cannot open automation event file \"%2\" (%2)"), _name, fullpath, strerror (errno)) << endmsg;
+ return -1;
}
}
{
if (is_mark()) {
if (_start != s) {
+
_start = s;
_end = s;
+
start_changed(this); /* EMIT SIGNAL */
+
if ( is_start() ) {
+
Session::StartTimeChanged (); /* EMIT SIGNAL */
AudioFileSource::set_header_position_offset ( s );
}
+
if ( is_end() ) {
Session::EndTimeChanged (); /* EMIT SIGNAL */
}
ofstream out (automation_path.c_str());
if (!out) {
- error << string_compose (_("cannot open pan automation file \"%1\" for saving (%s)"), automation_path, strerror (errno))
+ error << string_compose (_("cannot open pan automation file \"%1\" for saving (%2)"), automation_path, strerror (errno))
<< endmsg;
return -1;
}
free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults));
string path = string_compose("%1/.%2", envvar, domain);
- if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
+ if (g_mkdir_with_parents (path.c_str(), 0775)) {
warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
return false;
}
path += "/rdf";
- if (mkdir(path.c_str(), 0775) && errno != EEXIST) {
+ if (g_mkdir_with_parents (path.c_str(), 0775)) {
warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
return false;
}
const char* Session::_template_suffix = X_(".template");
const char* Session::_statefile_suffix = X_(".ardour");
const char* Session::_pending_suffix = X_(".pending");
-const char* Session::sound_dir_name = X_("sounds");
-const char* Session::tape_dir_name = X_("tapes");
+const char* Session::old_sound_dir_name = X_("sounds");
+const char* Session::sound_dir_name = X_("audiofiles");
const char* Session::peak_dir_name = X_("peaks");
const char* Session::dead_sound_dir_name = X_("dead_sounds");
+const char* Session::interchange_dir_name = X_("interchange");
Session::compute_peak_t Session::compute_peak = 0;
Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0;
}
string
-Session::peak_path_from_audio_path (string audio_path)
+Session::peak_path_from_audio_path (string audio_path) const
{
- /* XXX hardly bombproof! fix me */
-
string res;
- res = Glib::path_get_dirname (audio_path);
- res = Glib::path_get_dirname (res);
- res += '/';
- res += peak_dir_name;
- res += '/';
+ res = peak_dir ();
res += PBD::basename_nosuffix (audio_path);
res += ".peak";
spath = (*i).path;
- if (destructive) {
- spath += tape_dir_name;
- } else {
- spath += sound_dir_name;
- }
+ spath += sound_dir_name;
if (destructive) {
if (nchan < 2) {
string foo = buf;
- if (destructive) {
- spath = tape_dir ();
- } else {
- spath = discover_best_sound_dir ();
- }
+ spath = discover_best_sound_dir ();
string::size_type pos = foo.find_last_of ('/');
Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
{
string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
- return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (spath, destructive, frame_rate()));
+ return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, spath, destructive, frame_rate()));
}
/* Playlist management */
for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
- if (AudioFileSource::is_empty (*(*i))) {
+ if (AudioFileSource::is_empty (*this, *(*i))) {
unlink ((*i)->c_str());
Session::available_capture_duration ()
{
const double scale = 4096.0 / sizeof (Sample);
-
+
if (_total_free_4k_blocks * scale > (double) max_frames) {
return max_frames;
}
}
try {
- fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (buf, false, frame_rate()));
+ fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, buf, false, frame_rate()));
}
catch (failed_constructor& err) {
_end_location_is_free = false;
}
- restore_history(_current_snapshot_name);
return 0;
}
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
- fspath += sound_dir_name;
- fspath += ':';
-
- /* tape dir */
-
- fspath += sp.path;
- if (fspath[fspath.length()-1] != '/') {
- fspath += '/';
- }
- fspath += tape_dir_name;
+ fspath += sound_dir (false);
AudioFileSource::set_search_path (fspath);
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
- fspath += sound_dir_name;
- fspath += ':';
-
- /* add tape dir to file search path */
-
- fspath += sp.path;
- if (fspath[fspath.length()-1] != '/') {
- fspath += '/';
- }
- fspath += tape_dir_name;
+ fspath += sound_dir (false);
fspath += ':';
remaining = remaining.substr (colon+1);
if (fspath[fspath.length()-1] != '/') {
fspath += '/';
}
- fspath += sound_dir_name;
+ fspath += sound_dir (false);
fspath += ':';
- fspath += sp.path;
- if (fspath[fspath.length()-1] != '/') {
- fspath += '/';
- }
- fspath += tape_dir_name;
-
session_dirs.push_back (sp);
}
Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
{
string dir;
+
+ new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
- if (mkdir (_path.c_str(), 0755) < 0) {
- if (errno == EEXIST) {
- new_session = false;
- } else {
- error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
- return -1;
- }
- } else {
- new_session = true;
+ if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
+ return -1;
}
dir = peak_dir ();
- if (mkdir (dir.c_str(), 0755) < 0) {
- if (errno != EEXIST) {
- error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
}
dir = sound_dir ();
- if (mkdir (dir.c_str(), 0755) < 0) {
- if (errno != EEXIST) {
- error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
- return -1;
- }
- }
-
- dir = tape_dir ();
-
- if (mkdir (dir.c_str(), 0755) < 0) {
- if (errno != EEXIST) {
- error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
}
dir = dead_sound_dir ();
- if (mkdir (dir.c_str(), 0755) < 0) {
- if (errno != EEXIST) {
- error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
}
dir = automation_dir ();
- if (mkdir (dir.c_str(), 0755) < 0) {
- if (errno != EEXIST) {
- error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
}
}
+ cerr << "actually writing state\n";
+
if (!tree.write (xml_path)) {
error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
}
try {
- return SourceFactory::create (node);
+ return SourceFactory::create (*this, node);
}
catch (failed_constructor& err) {
if ((dp = opendir (dir.c_str()))) {
closedir (dp);
} else {
- if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
+ if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
/* Ensure that the parent directory exists */
- if (mkdir (path.c_str(), 0775)) {
- if (errno != EEXIST) {
- error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (path.c_str(), 0775)) {
+ error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
+ return -1;
}
/* Ensure that the sounds directory exists */
result += '/';
result += sound_dir_name;
- if (mkdir (result.c_str(), 0775)) {
- if (errno != EEXIST) {
- error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (result.c_str(), 0775)) {
+ error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
+ return -1;
}
dead = path;
dead += '/';
dead += dead_sound_dir_name;
- if (mkdir (dead.c_str(), 0775)) {
- if (errno != EEXIST) {
- error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (dead.c_str(), 0775)) {
+ error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
+ return -1;
}
peak = path;
peak += '/';
peak += peak_dir_name;
- if (mkdir (peak.c_str(), 0775)) {
- if (errno != EEXIST) {
- error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
- return -1;
- }
+ if (g_mkdir_with_parents (peak.c_str(), 0775)) {
+ error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
+ return -1;
}
/* callers expect this to be terminated ... */
vector<space_and_path>::iterator i;
string result;
- /* destructive files all go into the same place */
-
- if (destructive) {
- return tape_dir();
- }
-
/* handle common case without system calls */
if (session_dirs.size() == 1) {
}
string
-Session::sound_dir () const
+Session::sound_dir (bool with_path) const
{
- string res = _path;
+ /* support old session structure */
+
+ struct stat statbuf;
+ string old;
+
+ if (with_path) {
+ old = _path;
+ }
+
+ old += sound_dir_name;
+ old += '/';
+
+ if (stat (old.c_str(), &statbuf) == 0) {
+ return old;
+ }
+
+ string res;
+
+ if (with_path) {
+ res = _path;
+ }
+
+ res += interchange_dir_name;
+ res += '/';
+ res += legalize_for_path (_name);
+ res += '/';
res += sound_dir_name;
res += '/';
- return res;
-}
-string
-Session::tape_dir () const
-{
- string res = _path;
- res += tape_dir_name;
- res += '/';
return res;
}
XMLTree tree;
string xml_path;
string bak_path;
-
-
+
tree.set_root (&history.get_state());
if (snapshot_name.empty()) {
}
xml_path = _path + snapshot_name + ".history";
- cerr << "Saving history to " << xml_path << endmsg;
bak_path = xml_path + ".bak";
return -1;
}
+ cerr << "actually writing history\n";
+
if (!tree.write (xml_path))
{
error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
void
Session::sync_time_vars ()
{
- _current_frame_rate = _base_frame_rate * (1.0 + (video_pullup/100.0) );
+ _current_frame_rate = (jack_nframes_t) round (_base_frame_rate * (1.0 + (video_pullup/100.0)));
_frames_per_hour = _current_frame_rate * 3600;
_frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second;
_smpte_frames_per_hour = (unsigned long) (smpte_frames_per_second * 3600.0);
}
try {
- sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (path, false, frame_rate())));
+ sources.push_back (boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, path, false, frame_rate())));
} catch (failed_constructor& err) {
error << string_compose (_("tempoize: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;
using namespace ARDOUR;
using namespace PBD;
-SndFileSource::SndFileSource (const XMLNode& node)
- : AudioFileSource (node)
+SndFileSource::SndFileSource (Session& s, const XMLNode& node)
+ : AudioFileSource (s, node)
{
init (_name);
}
}
-SndFileSource::SndFileSource (string idstr, Flag flags)
+SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
/* files created this way are never writable or removable */
- : AudioFileSource (idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
+ : AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{
init (idstr);
}
}
-SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
- : AudioFileSource(idstr, flags, sfmt, hf)
+SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
+ : AudioFileSource (s, idstr, flags, sfmt, hf)
{
int fmt = 0;
delete _broadcast_info;
_broadcast_info = 0;
}
+
+
+
}
jack_nframes_t
using namespace ARDOUR;
-Source::Source (string name)
+Source::Source (Session& s, string name)
+ : _session (s)
{
_name = name;
_timestamp = 0;
}
-Source::Source (const XMLNode& node)
+Source::Source (Session& s, const XMLNode& node)
+ : _session (s)
{
_timestamp = 0;
#ifdef HAVE_COREAUDIO
boost::shared_ptr<Source>
-SourceFactory::create (const XMLNode& node)
+SourceFactory::create (Session& s, const XMLNode& node)
{
if (node.property (X_("destructive")) != 0) {
- boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
+ boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
SourceCreated (ret);
return ret;
} else {
try {
- boost::shared_ptr<Source> ret (new CoreAudioSource (node));
+ boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
SourceCreated (ret);
return ret;
}
catch (failed_constructor& err) {
- boost::shared_ptr<Source> ret (new SndFileSource (node));
+ boost::shared_ptr<Source> ret (new SndFileSource (s, node));
SourceCreated (ret);
return ret;
}
#else
boost::shared_ptr<Source>
-SourceFactory::create (const XMLNode& node)
+SourceFactory::create (Session& s, const XMLNode& node)
{
if (node.property (X_("destructive")) != 0) {
- boost::shared_ptr<Source> ret (new DestructiveFileSource (node));
+ boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
SourceCreated (ret);
return ret;
} else {
- boost::shared_ptr<Source> ret (new SndFileSource (node));
+ boost::shared_ptr<Source> ret (new SndFileSource (s, node));
SourceCreated (ret);
return ret;
}
#ifdef HAVE_COREAUDIO
boost::shared_ptr<Source>
-SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool announce)
+SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
{
if (flags & Destructive) {
- boost::shared_ptr<Source> ret (new DestructiveFileSource (idstr, flags));
+ boost::shared_ptr<Source> ret (new DestructiveFileSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
}
try {
- boost::shared_ptr<Source> ret (new CoreAudioSource (idstr, flags));
+ boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
}
catch (failed_constructor& err) {
- boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
+ boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
#else
boost::shared_ptr<Source>
-SourceFactory::createReadable (string idstr, AudioFileSource::Flag flags, bool announce)
+SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
{
- boost::shared_ptr<Source> ret (new SndFileSource (idstr, flags));
+ boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
if (announce) {
SourceCreated (ret);
}
#endif // HAVE_COREAUDIO
boost::shared_ptr<Source>
-SourceFactory::createWritable (std::string path, bool destructive, jack_nframes_t rate, bool announce)
+SourceFactory::createWritable (Session& s, std::string path, bool destructive, jack_nframes_t rate, bool announce)
{
/* this might throw failed_constructor(), which is OK */
if (destructive) {
- boost::shared_ptr<Source> ret (new DestructiveFileSource (path,
+ boost::shared_ptr<Source> ret (new DestructiveFileSource (s, path,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
rate));
return ret;
} else {
- boost::shared_ptr<Source> ret (new SndFileSource (path,
+ boost::shared_ptr<Source> ret (new SndFileSource (s, path,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
rate));
if (stat (path.c_str(), &sbuf)) {
if (errno == ENOENT) {
- if (mkdir (path.c_str(), 0600)) {
+ if (g_mkdir_with_parents (path.c_str(), 0600)) {
error << string_compose (_("cannot create VST chunk directory: %1"),
- strerror (errno))
+ strerror (errno))
<< endmsg;
return *root;
}
virtual void add_instant_xml (XMLNode&, const std::string& dir);
XMLNode *instant_xml (const std::string& str, const std::string& dir);
- PBD::ID id() { return _id; }
+ const PBD::ID& id() const { return _id; }
protected:
XMLNode *_extra_xml;