summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/SConscript3
-rw-r--r--libs/ardour/ardour/ardour.h2
-rw-r--r--libs/ardour/ardour/audiofilesource.h9
-rw-r--r--libs/ardour/ardour/audiosource.h50
-rw-r--r--libs/ardour/ardour/automatable.h9
-rw-r--r--libs/ardour/ardour/configuration.h12
-rw-r--r--libs/ardour/ardour/configuration_vars.h8
-rw-r--r--libs/ardour/ardour/io.h2
-rw-r--r--libs/ardour/ardour/profile.h8
-rw-r--r--libs/ardour/ardour/resampled_source.h50
-rw-r--r--libs/ardour/ardour/route.h3
-rw-r--r--libs/ardour/ardour/session.h15
-rw-r--r--libs/ardour/ardour/sndfilesource.h4
-rw-r--r--libs/ardour/ardour/source_factory.h17
-rw-r--r--libs/ardour/ardour/types.h9
-rw-r--r--libs/ardour/ardour/utils.h2
-rw-r--r--libs/ardour/audio_playlist.cc4
-rw-r--r--libs/ardour/audioengine.cc4
-rw-r--r--libs/ardour/audiofilesource.cc94
-rw-r--r--libs/ardour/audiosource.cc98
-rw-r--r--libs/ardour/auditioner.cc2
-rw-r--r--libs/ardour/automatable.cc4
-rw-r--r--libs/ardour/configuration.cc70
-rw-r--r--libs/ardour/crossfade.cc14
-rw-r--r--libs/ardour/globals.cc65
-rw-r--r--libs/ardour/import.cc368
-rw-r--r--libs/ardour/io.cc4
-rw-r--r--libs/ardour/playlist.cc4
-rw-r--r--libs/ardour/resampled_source.cc128
-rw-r--r--libs/ardour/route.cc33
-rw-r--r--libs/ardour/session.cc39
-rw-r--r--libs/ardour/session_events.cc2
-rw-r--r--libs/ardour/session_state.cc25
-rw-r--r--libs/ardour/sndfilesource.cc54
-rw-r--r--libs/ardour/source_factory.cc189
-rw-r--r--libs/ardour/utils.cc13
36 files changed, 865 insertions, 552 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index 3892af6e9b..465138d90d 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -12,7 +12,7 @@ ardour = env.Copy()
# this defines the version number of libardour
#
-domain = 'libardour'
+domain = 'libardour2'
ardour.Append(DOMAIN = domain, MAJOR = 2, MINOR = 0, MICRO = 0)
ardour.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
@@ -101,6 +101,7 @@ recent_sessions.cc
region.cc
region_factory.cc
reverse.cc
+resampled_source.cc
quantize.cc
route.cc
route_group.cc
diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h
index 1b9725a04c..6e7b494441 100644
--- a/libs/ardour/ardour/ardour.h
+++ b/libs/ardour/ardour/ardour.h
@@ -47,8 +47,6 @@ namespace ARDOUR {
int init (bool with_vst, bool try_optimization);
int cleanup ();
- int setup_midi(AudioEngine& engine);
-
std::string get_ardour_revision ();
microseconds_t get_microseconds ();
diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h
index 78d10f9d64..4d80c8ddf5 100644
--- a/libs/ardour/ardour/audiofilesource.h
+++ b/libs/ardour/ardour/audiofilesource.h
@@ -61,7 +61,8 @@ class AudioFileSource : public AudioSource {
Glib::ustring path() const { return _path; }
Glib::ustring peak_path (Glib::ustring audio_path);
- Glib::ustring old_peak_path (Glib::ustring audio_path);
+ Glib::ustring find_broken_peakfile (Glib::ustring missing_peak_path,
+ Glib::ustring audio_path);
uint16_t channel() const { return _channel; }
@@ -122,7 +123,7 @@ class AudioFileSource : public AudioSource {
to cause issues.
*/
- virtual void handle_header_position_change ();
+ virtual void handle_header_position_change () {}
protected:
@@ -166,6 +167,10 @@ class AudioFileSource : public AudioSource {
bool find (Glib::ustring& path, bool must_exist, bool& is_new, uint16_t& chan);
bool removable() const;
bool writable() const { return _flags & Writable; }
+
+ private:
+ Glib::ustring old_peak_path (Glib::ustring audio_path);
+ Glib::ustring broken_peak_path (Glib::ustring audio_path);
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h
index 812c30e8c2..7b22528bd1 100644
--- a/libs/ardour/ardour/audiosource.h
+++ b/libs/ardour/ardour/audiosource.h
@@ -40,7 +40,6 @@
using std::list;
using std::vector;
-using Glib::ustring;
namespace ARDOUR {
@@ -49,10 +48,23 @@ const nframes_t frames_per_peak = 256;
class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR::AudioSource>
{
public:
- AudioSource (Session&, ustring name);
+ AudioSource (Session&, Glib::ustring name);
AudioSource (Session&, const XMLNode&);
virtual ~AudioSource ();
+
+ /* one could argue that this should belong to Source, but other data types
+ generally do not come with a model of "offset along an audio timeline"
+ so its here in AudioSource for now.
+ */
+
+ virtual nframes_t natural_position() const { return 0; }
+ /* returns the number of items in this `audio_source' */
+
+ virtual nframes_t length() const {
+ return _length;
+ }
+
virtual nframes_t available_peaks (double zoom) const;
virtual nframes_t read (Sample *dst, nframes_t start, nframes_t cnt) const;
@@ -65,8 +77,8 @@ const nframes_t frames_per_peak = 256;
virtual bool can_truncate_peaks() const { return true; }
- void set_captured_for (ustring str) { _captured_for = str; }
- ustring captured_for() const { return _captured_for; }
+ void set_captured_for (Glib::ustring str) { _captured_for = str; }
+ Glib::ustring captured_for() const { return _captured_for; }
uint32_t read_data_count() const { return _read_data_count; }
uint32_t write_data_count() const { return _write_data_count; }
@@ -81,7 +93,7 @@ const nframes_t frames_per_peak = 256;
XMLNode& get_state ();
int set_state (const XMLNode&);
- int rename_peakfile (ustring newpath);
+ int rename_peakfile (Glib::ustring newpath);
void touch_peakfile ();
static void set_build_missing_peakfiles (bool yn) {
@@ -92,35 +104,43 @@ const nframes_t frames_per_peak = 256;
_build_peakfiles = yn;
}
+ static bool get_build_peakfiles () {
+ return _build_peakfiles;
+ }
+
virtual int setup_peakfile () { return 0; }
int prepare_for_peakfile_writes ();
- void done_with_peakfile_writes ();
+ void done_with_peakfile_writes (bool done = true);
protected:
static bool _build_missing_peakfiles;
static bool _build_peakfiles;
- bool _peaks_built;
- mutable Glib::Mutex _lock;
- ustring peakpath;
- ustring _captured_for;
+ bool _peaks_built;
+ mutable Glib::Mutex _lock;
+ mutable Glib::Mutex _peaks_ready_lock;
+ nframes_t _length;
+ Glib::ustring peakpath;
+ Glib::ustring _captured_for;
mutable uint32_t _read_data_count; // modified in read()
mutable uint32_t _write_data_count; // modified in write()
- int initialize_peakfile (bool newfile, ustring path);
+ int initialize_peakfile (bool newfile, Glib::ustring path);
int build_peaks_from_scratch ();
- int compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force);
+ int compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force, bool intermediate_peaks_ready_signal);
void truncate_peakfile();
mutable off_t _peak_byte_max; // modified in compute_and_write_peak()
virtual nframes_t read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const = 0;
virtual nframes_t write_unlocked (Sample *dst, nframes_t cnt) = 0;
- virtual ustring peak_path(ustring audio_path) = 0;
- virtual ustring old_peak_path(ustring audio_path) = 0;
+ virtual Glib::ustring peak_path(Glib::ustring audio_path) = 0;
+ virtual Glib::ustring find_broken_peakfile (Glib::ustring missing_peak_path, Glib::ustring audio_path) = 0;
+ void update_length (nframes_t pos, nframes_t cnt);
+
private:
int peakfile;
nframes_t peak_leftover_cnt;
@@ -128,7 +148,7 @@ const nframes_t frames_per_peak = 256;
Sample* peak_leftovers;
nframes_t peak_leftover_frame;
- bool file_changed (ustring path);
+ bool file_changed (Glib::ustring path);
};
}
diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h
index fe47614a1f..f96ecc0bd1 100644
--- a/libs/ardour/ardour/automatable.h
+++ b/libs/ardour/ardour/automatable.h
@@ -83,6 +83,14 @@ public:
Glib::Mutex& automation_lock() const { return _automation_lock; }
+ static void set_automation_interval (jack_nframes_t frames) {
+ _automation_interval = frames;
+ }
+
+ static jack_nframes_t automation_interval() {
+ return _automation_interval;
+ }
+
protected:
void can_automate(Parameter);
@@ -102,6 +110,7 @@ protected:
std::set<Parameter> _can_automate_list;
nframes_t _last_automation_snapshot;
+ static nframes_t _automation_interval;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/configuration.h b/libs/ardour/ardour/configuration.h
index 70b7e166c1..7b890500d8 100644
--- a/libs/ardour/ardour/configuration.h
+++ b/libs/ardour/ardour/configuration.h
@@ -42,17 +42,7 @@ class Configuration : public PBD::Stateful
Configuration();
virtual ~Configuration();
- struct MidiPortDescriptor {
- std::string tag;
- std::string device;
- std::string type;
- std::string mode;
-
- MidiPortDescriptor (const XMLNode&);
- XMLNode& get_state();
- };
-
- std::map<std::string,MidiPortDescriptor *> midi_ports;
+ std::map<std::string,XMLNode> midi_ports;
void map_parameters (sigc::slot<void,const char*> theSlot);
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 4d5579a9a0..b592a9f721 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -138,11 +138,15 @@ CONFIG_VARIABLE (bool, verify_remove_last_capture, "verify-remove-last-capture",
CONFIG_VARIABLE (bool, no_new_session_dialog, "no-new-session-dialog", false)
CONFIG_VARIABLE (bool, use_vst, "use-vst", true)
CONFIG_VARIABLE (uint32_t, subframes_per_frame, "subframes-per-frame", 100)
-CONFIG_VARIABLE (uint32_t, saved_history_depth, "save-history-depth", 100)
+CONFIG_VARIABLE (bool, save_history, "save-history", true)
+CONFIG_VARIABLE (int32_t, saved_history_depth, "save-history-depth", 20)
+CONFIG_VARIABLE (int32_t, history_depth, "history-depth", 20)
CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false)
CONFIG_VARIABLE (bool, periodic_safety_backups, "periodic-safety-backups", true)
CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-backup-interval", 120)
-CONFIG_VARIABLE (string, possible_audio_file_regexp, "possible-audio-file-regexp", "\\.(wav|aiff|caf|w64|L|R)$")
+CONFIG_VARIABLE (float, automation_interval, "automation-interval", 50)
+CONFIG_VARIABLE (bool, sync_all_route_ordering, "sync-all-route-ordering", true)
+CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", true)
/* denormal management */
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 6c040be63e..6e68c01d8c 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -219,7 +219,7 @@ class IO : public Automatable, public Latent
public:
/* automation */
-
+
struct GainControl : public AutomationControl {
GainControl (std::string name, IO& i, boost::shared_ptr<AutomationList> al)
: AutomationControl (i._session, al, name)
diff --git a/libs/ardour/ardour/profile.h b/libs/ardour/ardour/profile.h
index 3347447915..b016063c4d 100644
--- a/libs/ardour/ardour/profile.h
+++ b/libs/ardour/ardour/profile.h
@@ -29,6 +29,8 @@ class RuntimeProfile {
public:
enum Element {
SmallScreen,
+ SAE,
+ SinglePackage,
LastElement
};
@@ -38,6 +40,12 @@ class RuntimeProfile {
void set_small_screen() { bits[SmallScreen] = true; }
bool get_small_screen() const { return bits[SmallScreen]; }
+ void set_sae () { bits[SAE] = true; }
+ bool get_sae () const { return bits[SAE]; }
+
+ void set_single_package () { bits[SinglePackage] = true; }
+ bool get_single_package () const { return bits[SinglePackage]; }
+
private:
boost::dynamic_bitset<uint64_t> bits;
diff --git a/libs/ardour/ardour/resampled_source.h b/libs/ardour/ardour/resampled_source.h
new file mode 100644
index 0000000000..9a88ca9644
--- /dev/null
+++ b/libs/ardour/ardour/resampled_source.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2007 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_resampled_source_h__
+#define __ardour_resampled_source_h__
+
+#include <samplerate.h>
+
+#include <ardour/types.h>
+#include <ardour/importable_source.h>
+
+namespace ARDOUR {
+
+class ResampledImportableSource : public ImportableSource
+{
+ public:
+ ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate, SrcQuality);
+ ~ResampledImportableSource ();
+
+ nframes_t read (Sample* buffer, nframes_t nframes);
+
+ float ratio() const { return src_data.src_ratio; }
+
+ static const uint32_t blocksize;
+
+ private:
+ float* input;
+ SRC_STATE* src_state;
+ SRC_DATA src_data;
+};
+
+}
+
+#endif /* __ardour_resampled_source_h__ */
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 1fd6eff0f8..fc17af06ee 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -258,6 +258,9 @@ class Route : public IO
uint32_t remote_control_id () const;
sigc::signal<void> RemoteControlIDChanged;
+ void sync_order_keys ();
+ static sigc::signal<void> SyncOrderKeys;
+
protected:
friend class Session;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 94caf8a242..bbcae6e91d 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -261,6 +261,8 @@ class Session : public PBD::StatefulDestructible
std::string automation_dir () const;
+ Glib::ustring peak_path (Glib::ustring) const;
+
static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
static string change_midi_path_by_name (string oldpath, string oldname, string newname, bool destructive);
@@ -422,6 +424,7 @@ class Session : public PBD::StatefulDestructible
int restore_history (string snapshot_name);
void remove_state (string snapshot_name);
void rename_state (string old_name, string new_name);
+ void remove_pending_capture_state ();
sigc::signal<void,string> StateSaved;
sigc::signal<void> StateReady;
@@ -568,13 +571,14 @@ class Session : public PBD::StatefulDestructible
string doing_what;
/* control info */
- bool multichan;
bool sample_convert;
+ SrcQuality quality;
volatile bool freeze;
std::vector<Glib::ustring> paths;
/* result */
- std::vector<boost::shared_ptr<Region> > new_regions;
+ SourceList sources;
+
};
int import_audiofile (import_status&);
@@ -650,8 +654,6 @@ class Session : public PBD::StatefulDestructible
void add_curve(Curve*);
void add_automation_list(AutomationList*);
- nframes_t automation_interval () const { return _automation_interval; }
-
/* fade curves */
float get_default_fade_length () const { return default_fade_msecs; }
@@ -1650,8 +1652,6 @@ class Session : public PBD::StatefulDestructible
void allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force);
uint32_t _npan_buffers;
- nframes_t _automation_interval;
-
/* VST support */
long _vst_callback (VSTPlugin*,
@@ -1668,7 +1668,6 @@ class Session : public PBD::StatefulDestructible
uint32_t n_physical_outputs;
uint32_t n_physical_inputs;
- void remove_pending_capture_state ();
int find_all_sources (std::string path, std::set<std::string>& result);
int find_all_sources_across_snapshots (std::set<std::string>& result, bool exclude_this_snapshot);
@@ -1688,6 +1687,8 @@ class Session : public PBD::StatefulDestructible
XMLNode& get_control_protocol_state ();
+ void set_history_depth (uint32_t depth);
+ void sync_order_keys ();
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h
index 916e9da49e..4fd71a4c96 100644
--- a/libs/ardour/ardour/sndfilesource.h
+++ b/libs/ardour/ardour/sndfilesource.h
@@ -76,9 +76,6 @@ class SndFileSource : public AudioFileSource {
SF_INFO _info;
SF_BROADCAST_INFO *_broadcast_info;
- mutable float *interleave_buf;
- mutable nframes_t interleave_bufsize;
-
void init ();
int open();
void close();
@@ -105,6 +102,7 @@ class SndFileSource : public AudioFileSource {
void handle_header_position_change ();
static int64_t get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists);
+ static Sample* get_interleave_buffer (nframes_t size);
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h
index fb591216bf..01f50126a4 100644
--- a/libs/ardour/ardour/source_factory.h
+++ b/libs/ardour/ardour/source_factory.h
@@ -36,16 +36,23 @@ class Session;
class SourceFactory {
public:
+ static void init ();
+
static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
- static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
+ static boost::shared_ptr<Source> create (Session&, const XMLNode& node, bool async = false);
static boost::shared_ptr<Source> createSilent (Session&, const XMLNode& node, nframes_t nframes, float sample_rate);
- static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true);
- static boost::shared_ptr<Source> createWritable (DataType type, Session&, std::string name, bool destructive, nframes_t rate, bool announce = true);
+ static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string path, int chn, AudioFileSource::Flag flags,
+ bool announce = true, bool async = false);
+ static boost::shared_ptr<Source> createWritable (DataType type, Session&, std::string name, bool destructive, nframes_t rate,
+ bool announce = true, bool async = true);
+
+ static Glib::Cond* PeaksToBuild;
+ static Glib::StaticMutex peak_building_lock;
+ static std::list<boost::weak_ptr<AudioSource> > files_with_peaks;
- private:
- static int setup_peakfile (boost::shared_ptr<Source>);
+ static int setup_peakfile (boost::shared_ptr<Source>, bool async);
};
}
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index e13bd09d83..5b50713313 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -370,6 +370,15 @@ namespace ARDOUR {
};
typedef std::vector<boost::shared_ptr<Source> > SourceList;
+
+ enum SrcQuality {
+ SrcBest,
+ SrcGood,
+ SrcQuick,
+ SrcFast,
+ SrcFastest
+ };
+
} // namespace ARDOUR
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h
index cde17d8b49..e52274eb1f 100644
--- a/libs/ardour/ardour/utils.h
+++ b/libs/ardour/ardour/utils.h
@@ -50,7 +50,7 @@ int cmp_nocase (const std::string& s, const std::string& s2);
int touch_file(Glib::ustring path);
Glib::ustring path_expand (Glib::ustring);
-Glib::ustring region_name_from_path (Glib::ustring path, bool strip_channels);
+Glib::ustring region_name_from_path (Glib::ustring path, bool strip_channels, bool add_channel_suffix = false, uint32_t total = 0, uint32_t this_one = 0);
bool path_is_paired (Glib::ustring path, Glib::ustring& pair_base);
void compute_equal_power_fades (nframes_t nframes, float* in, float* out);
diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc
index d28d88488e..d5c6120946 100644
--- a/libs/ardour/audio_playlist.cc
+++ b/libs/ardour/audio_playlist.cc
@@ -379,7 +379,9 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
bottom = region;
}
-
+ if (!top->opaque()) {
+ continue;
+ }
OverlapType c = top->coverage (bottom->position(), bottom->last_frame());
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index a4ce5f291d..2a4b36f7d8 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -156,7 +156,7 @@ AudioEngine::start ()
_has_run = true;
Running(); /* EMIT SIGNAL */
} else {
- error << _("cannot activate JACK client") << endmsg;
+ // error << _("cannot activate JACK client") << endmsg;
}
}
@@ -1078,7 +1078,7 @@ AudioEngine::connect_to_jack (string client_name)
error << _("Unable to connect to JACK server") << endmsg;
}
- error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
+ // error message is not useful here
return -1;
}
diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc
index 1044dd10d2..1284dd343b 100644
--- a/libs/ardour/audiofilesource.cc
+++ b/libs/ardour/audiofilesource.cc
@@ -21,10 +21,13 @@
#include <sys/time.h>
#include <sys/stat.h>
+#include <stdio.h> // for rename(), sigh
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <pbd/convert.h>
+#include <pbd/basename.h>
#include <pbd/mountpoint.h>
#include <pbd/stl_delete.h>
#include <pbd/strsplit.h>
@@ -40,6 +43,7 @@
#include <ardour/sndfile_helpers.h>
#include <ardour/sndfilesource.h>
#include <ardour/session.h>
+#include <ardour/session_directory.h>
#include <ardour/source_factory.h>
#include <ardour/filename_extensions.h>
@@ -153,7 +157,60 @@ AudioFileSource::init (ustring pathstr, bool must_exist)
ustring
AudioFileSource::peak_path (ustring audio_path)
{
- return _session.peak_path_from_audio_path (audio_path);
+ ustring base;
+
+ base = PBD::basename_nosuffix (audio_path);
+ base += '%';
+ base += (char) ('A' + _channel);
+
+ return _session.peak_path (base);
+}
+
+ustring
+AudioFileSource::find_broken_peakfile (ustring peak_path, ustring audio_path)
+{
+ ustring str;
+
+ /* check for the broken location in use by 2.0 for several months */
+
+ str = broken_peak_path (audio_path);
+
+ if (Glib::file_test (str, Glib::FILE_TEST_EXISTS)) {
+
+ if (is_embedded()) {
+
+ /* it would be nice to rename it but the nature of
+ the bug means that we can't reliably use it.
+ */
+
+ peak_path = str;
+
+ } else {
+ /* all native files are mono, so we can just rename
+ it.
+ */
+ ::rename (str.c_str(), peak_path.c_str());
+ }
+
+ } else {
+ /* Nasty band-aid for older sessions that were created before we
+ used libsndfile for all audio files.
+ */
+
+
+ str = old_peak_path (audio_path);
+ if (Glib::file_test (str, Glib::FILE_TEST_EXISTS)) {
+ peak_path = str;
+ }
+ }
+
+ return peak_path;
+}
+
+ustring
+AudioFileSource::broken_peak_path (ustring audio_path)
+{
+ return _session.peak_path (audio_path);
}
ustring
@@ -171,9 +228,9 @@ AudioFileSource::old_peak_path (ustring audio_path)
char buf[32];
#ifdef __APPLE__
- snprintf (buf, sizeof (buf), "%u-%u-%d", stat_mount.st_ino, stat_file.st_ino, _channel);
+ snprintf (buf, sizeof (buf), "%u-%u-%d.peak", stat_mount.st_ino, stat_file.st_ino, _channel);
#else
- snprintf (buf, sizeof (buf), "%ld-%ld-%d", stat_mount.st_ino, stat_file.st_ino, _channel);
+ snprintf (buf, sizeof (buf), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, _channel);
#endif
ustring res = peak_dir;
@@ -227,7 +284,7 @@ AudioFileSource::set_state (const XMLNode& node)
}
if ((prop = node.property (X_("channel"))) != 0) {
- _channel = atoi (prop->value().c_str());
+ _channel = atoi (prop->value());
} else {
_channel = 0;
}
@@ -265,6 +322,10 @@ AudioFileSource::mark_streaming_write_completed ()
if (!writable()) {
return;
}
+
+ /* XXX notice that we're readers of _peaks_built
+ but we must hold a solid lock on PeaksReady.
+ */
Glib::Mutex::Lock lm (_lock);
@@ -432,7 +493,7 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t&
fullpath += shorter;
if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
- chan = atoi (pathstr.substr (pos+1).c_str());
+ chan = atoi (pathstr.substr (pos+1));
pathstr = shorter;
keeppath = fullpath;
++cnt;
@@ -484,7 +545,7 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t&
ustring shorter = pathstr.substr (0, pos);
if (Glib::file_test (shorter, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
- chan = atoi (pathstr.substr (pos+1).c_str());
+ chan = atoi (pathstr.substr (pos+1));
pathstr = shorter;
}
}
@@ -542,15 +603,6 @@ AudioFileSource::set_header_position_offset (nframes_t offset)
HeaderPositionOffsetChanged ();
}
-void
-AudioFileSource::handle_header_position_change ()
-{
- if (writable()) {
- set_header_timeline_position ();
- flush_header ();
- }
-}
-
void
AudioFileSource::set_timeline_position (int64_t pos)
{
@@ -603,15 +655,15 @@ AudioFileSource::set_source_name (ustring newname, bool destructive)
bool
AudioFileSource::is_empty (Session& s, ustring path)
{
- bool ret = false;
+ SoundFileInfo info;
+ string err;
- boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, s, path, 0, NoPeakFile, false));
-
- if (afs) {
- ret = (afs->length() == 0);
+ if (!get_soundfile_info (path, info, err)) {
+ /* dangerous: we can't get info, so assume that its not empty */
+ return false;
}
- return ret;
+ return info.length == 0;
}
int
diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc
index d09a9b29cd..a2ce7209f6 100644
--- a/libs/ardour/audiosource.cc
+++ b/libs/ardour/audiosource.cc
@@ -20,6 +20,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
+#include <poll.h>
#include <float.h>
#include <utime.h>
#include <cerrno>
@@ -29,18 +30,21 @@
#include <algorithm>
#include <vector>
+#include <glibmm/fileutils.h>
+
#include <pbd/xml++.h>
#include <pbd/pthread_utils.h>
#include <ardour/audiosource.h>
#include <ardour/cycle_timer.h>
-#include <ardour/runtime_functions.h>
+#include <ardour/session.h>
#include "i18n.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
+using Glib::ustring;
bool AudioSource::_build_missing_peakfiles = false;
bool AudioSource::_build_peakfiles = false;
@@ -126,12 +130,12 @@ bool
AudioSource::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
{
bool ret;
- Glib::Mutex::Lock lm (_lock);
+ Glib::Mutex::Lock lm (_peaks_ready_lock);
/* check to see if the peak data is ready. if not
connect the slot while still holding the lock.
*/
-
+
if (!(ret = _peaks_built)) {
conn = PeaksReady.connect (the_slot);
}
@@ -182,15 +186,10 @@ AudioSource::initialize_peakfile (bool newfile, ustring audio_path)
peakpath = peak_path (audio_path);
- /* Nasty band-aid for older sessions that were created before we
- used libsndfile for all audio files.
- */
+ /* if the peak file should be there, but isn't .... */
- if (!newfile && access (peakpath.c_str(), R_OK) != 0) {
- ustring str = old_peak_path (audio_path);
- if (access (str.c_str(), R_OK) == 0) {
- peakpath = str;
- }
+ if (!newfile && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
+ peakpath = find_broken_peakfile (peakpath, audio_path);
}
if (newfile) {
@@ -332,7 +331,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
/* open, read, close */
if ((_peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
- error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ error << string_compose(_("AudioSource: cannot open peakpath (a) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
@@ -406,7 +405,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
/* open ... close during out: handling */
if ((_peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
- error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return 0;
}
@@ -581,9 +580,11 @@ AudioSource::build_peaks_from_scratch ()
{
nframes_t current_frame;
nframes_t cnt;
- Sample buf[frames_per_peak];
+ Sample* buf = 0;
nframes_t frames_read;
nframes_t frames_to_read;
+ const nframes_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
+
int ret = -1;
{
@@ -598,39 +599,41 @@ AudioSource::build_peaks_from_scratch ()
current_frame = 0;
cnt = _length;
_peaks_built = false;
+ buf = new Sample[bufsize];
while (cnt) {
- frames_to_read = min (frames_per_peak, cnt);
+ frames_to_read = min (bufsize, cnt);
if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) {
error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
- done_with_peakfile_writes ();
+ done_with_peakfile_writes (false);
goto out;
}
- if (compute_and_write_peaks (buf, current_frame, frames_read, true)) {
+ if (compute_and_write_peaks (buf, current_frame, frames_read, true, false)) {
break;
}
current_frame += frames_read;
cnt -= frames_read;
}
-
+
if (cnt == 0) {
/* success */
truncate_peakfile();
- _peaks_built = true;
}
- done_with_peakfile_writes ();
+ done_with_peakfile_writes ((cnt == 0));
}
-
- /* lock no longer held, safe to signal */
-
- if (_peaks_built) {
- PeaksReady (); /* EMIT SIGNAL */
- ret = 0;
+
+ {
+ Glib::Mutex::Lock lm (_peaks_ready_lock);
+
+ if (_peaks_built) {
+ PeaksReady (); /* EMIT SIGNAL */
+ ret = 0;
+ }
}
out:
@@ -638,6 +641,10 @@ AudioSource::build_peaks_from_scratch ()
unlink (peakpath.c_str());
}
+ if (buf) {
+ delete [] buf;
+ }
+
return ret;
}
@@ -645,17 +652,21 @@ int
AudioSource::prepare_for_peakfile_writes ()
{
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
- error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
return 0;
}
void
-AudioSource::done_with_peakfile_writes ()
+AudioSource::done_with_peakfile_writes (bool done)
{
if (peak_leftover_cnt) {
- compute_and_write_peaks (0, 0, 0, true);
+ compute_and_write_peaks (0, 0, 0, true, false);
+ }
+
+ if (done) {
+ _peaks_built = true;
}
if (peakfile >= 0) {
@@ -665,7 +676,7 @@ AudioSource::done_with_peakfile_writes ()
}
int
-AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force)
+AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force, bool intermediate_peaks_ready)
{
Sample* buf2 = 0;
nframes_t to_do;
@@ -695,7 +706,8 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
x.min = peak_leftovers[0];
x.max = peak_leftovers[0];
- find_peaks (peak_leftovers + 1, peak_leftover_cnt - 1, &x.min, &x.max);
+
+ ARDOUR::find_peaks (peak_leftovers + 1, peak_leftover_cnt - 1, &x.min, &x.max);
off_t byte = (peak_leftover_frame / frames_per_peak) * sizeof (PeakData);
@@ -706,8 +718,13 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
_peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
- PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
- PeaksReady (); /* EMIT SIGNAL */
+ {
+ Glib::Mutex::Lock lm (_peaks_ready_lock);
+ PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
+ if (intermediate_peaks_ready) {
+ PeaksReady (); /* EMIT SIGNAL */
+ }
+ }
/* left overs are done */
@@ -778,7 +795,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
peakbuf[peaks_computed].max = buf[0];
peakbuf[peaks_computed].min = buf[0];
- find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
+ ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
peaks_computed++;
buf += this_time;
@@ -814,8 +831,11 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe
_peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaks_computed));
if (frames_done) {
+ Glib::Mutex::Lock lm (_peaks_ready_lock);
PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
- PeaksReady (); /* EMIT SIGNAL */
+ if (intermediate_peaks_ready) {
+ PeaksReady (); /* EMIT SIGNAL */
+ }
}
ret = 0;
@@ -882,3 +902,11 @@ AudioSource::available_peaks (double zoom_factor) const
return (end/sizeof(PeakData)) * frames_per_peak;
}
+void
+AudioSource::update_length (nframes_t pos, nframes_t cnt)
+{
+ if (pos + cnt > _length) {
+ _length = pos+cnt;
+ }
+}
+
diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc
index e344d5f2a6..c509997b2e 100644
--- a/libs/ardour/auditioner.cc
+++ b/libs/ardour/auditioner.cc
@@ -137,7 +137,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
boost::shared_ptr<AudioRegion> the_region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
the_region->set_position (0, this);
- _diskstream->playlist()->clear ();
+ _diskstream->playlist()->drop_regions ();
_diskstream->playlist()->add_region (the_region, 0, 1);
if (_diskstream->n_channels().n_audio() < the_region->n_channels()) {
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 0609b8d380..45b19d1997 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -34,6 +34,8 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
+nframes_t Automatable::_automation_interval = 0;
+
Automatable::Automatable(Session& _session, const string& name)
: SessionObject(_session, name)
, _last_automation_snapshot(0)
@@ -422,7 +424,7 @@ Automatable::protect_automation ()
void
Automatable::automation_snapshot (nframes_t now)
{
- if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _session.automation_interval()) {
+ if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
for (Controls::iterator i = _controls.begin(); i != _controls.end(); ++i) {
if (i->second->list()->automation_write()) {
diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc
index 5faab7c0ab..1460491180 100644
--- a/libs/ardour/configuration.cc
+++ b/libs/ardour/configuration.cc
@@ -25,6 +25,9 @@
#include <pbd/filesystem.h>
#include <pbd/file_utils.h>
+#include <midi++/manager.h>
+
+#include <ardour/ardour.h>
#include <ardour/configuration.h>
#include <ardour/audio_diskstream.h>
#include <ardour/control_protocol_manager.h>
@@ -195,9 +198,12 @@ Configuration::get_state ()
LocaleGuard lg (X_("POSIX"));
root = new XMLNode("Ardour");
- typedef map<string, MidiPortDescriptor*>::const_iterator CI;
- for(CI m = midi_ports.begin(); m != midi_ports.end(); ++m){
- root->add_child_nocopy(m->second->get_state());
+
+ MIDI::Manager::PortMap::const_iterator i;
+ const MIDI::Manager::PortMap& ports = MIDI::Manager::instance()->get_midi_ports();
+
+ for (i = ports.begin(); i != ports.end(); ++i) {
+ root->add_child_nocopy(i->second->get_state());
}
root->add_child_nocopy (get_variables (sigc::mem_fun (*this, &Configuration::save_config_options_predicate), "Config"));
@@ -250,10 +256,13 @@ Configuration::set_state (const XMLNode& root)
if (node->name() == "MIDI-port") {
try {
- pair<string,MidiPortDescriptor*> newpair;
- newpair.second = new MidiPortDescriptor (*node);
- newpair.first = newpair.second->tag;
- midi_ports.insert (newpair);
+
+ MIDI::Port::Descriptor desc (*node);
+ map<string,XMLNode>::iterator x;
+ if ((x = midi_ports.find (desc.tag)) != midi_ports.end()) {
+ midi_ports.erase (x);
+ }
+ midi_ports.insert (pair<string,XMLNode>(desc.tag,*node));
}
catch (failed_constructor& err) {
@@ -296,53 +305,6 @@ Configuration::set_variables (const XMLNode& node, ConfigVariableBase::Owner own
#undef CONFIG_VARIABLE_SPECIAL
}
-
-Configuration::MidiPortDescriptor::MidiPortDescriptor (const XMLNode& node)
-{
- const XMLProperty *prop;
- bool have_tag = false;
- bool have_device = false;
- bool have_type = false;
- bool have_mode = false;
-
- if ((prop = node.property ("tag")) != 0) {
- tag = prop->value();
- have_tag = true;
- }
-
- if ((prop = node.property ("device")) != 0) {
- device = prop->value();
- have_device = true;
- }
-
- if ((prop = node.property ("type")) != 0) {
- type = prop->value();
- have_type = true;
- }
-
- if ((prop = node.property ("mode")) != 0) {
- mode = prop->value();
- have_mode = true;
- }
-
- if (!have_tag || !have_device || !have_type || !have_mode) {
- throw failed_constructor();
- }
-}
-
-XMLNode&
-Configuration::MidiPortDescriptor::get_state()
-{
- XMLNode* root = new XMLNode("MIDI-port");
-
- root->add_property("tag", tag);
- root->add_property("device", device);
- root->add_property("type", type);
- root->add_property("mode", mode);
-
- return *root;
-}
-
void
Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
{
diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc
index 556f11125e..d45d5efa9f 100644
--- a/libs/ardour/crossfade.cc
+++ b/libs/ardour/crossfade.cc
@@ -294,6 +294,13 @@ Crossfade::read_at (Sample *buf, Sample *mixdown_buffer,
offset = start - _position;
+ /* Prevent data from piling up inthe crossfade buffers when reading a transparent region */
+ if (!(_out->opaque())) {
+ memset (crossfade_buffer_out, 0, sizeof (Sample) * to_write);
+ } else if (!(_in->opaque())) {
+ memset (crossfade_buffer_in, 0, sizeof (Sample) * to_write);
+ }
+
_out->read_at (crossfade_buffer_out, mixdown_buffer, gain_buffer, start, to_write, chan_n);
_in->read_at (crossfade_buffer_in, mixdown_buffer, gain_buffer, start, to_write, chan_n);
@@ -358,6 +365,13 @@ Crossfade::refresh ()
return false;
}
+ /* Top layer shouldn't be transparent */
+
+ if (!((layer_relation > 0 ? _in : _out)->opaque())) {
+ Invalidated (shared_from_this());
+ return false;
+ }
+
/* layer ordering cannot change */
int32_t new_layer_relation = (int32_t) (_in->layer() - _out->layer());
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 52be946f1e..c3eae5ad86 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -39,7 +39,6 @@
#include <pbd/fpu.h>
#include <midi++/port.h>
-#include <midi++/port_request.h>
#include <midi++/manager.h>
#include <midi++/mmc.h>
@@ -51,6 +50,7 @@
#include <ardour/audiosource.h>
#include <ardour/utils.h>
#include <ardour/session.h>
+#include <ardour/source_factory.h>
#include <ardour/control_protocol_manager.h>
#include <ardour/audioengine.h>
@@ -114,47 +114,25 @@ setup_osc ()
#endif
int
-ARDOUR::setup_midi (AudioEngine& engine)
+setup_midi ()
{
- std::map<string,Configuration::MidiPortDescriptor*>::iterator i;
- int nports;
-
- if ((nports = Config->midi_ports.size()) == 0) {
+ if (Config->midi_ports.size() == 0) {
warning << _("no MIDI ports specified: no MMC or MTC control possible") << endmsg;
return 0;
}
- MIDI::Manager::instance()->set_api_data(engine.jack());
-
- for (i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) {
- Configuration::MidiPortDescriptor* port_descriptor;
-
- port_descriptor = (*i).second;
-
- MIDI::PortRequest request (port_descriptor->device,
- port_descriptor->tag,
- port_descriptor->mode,
- port_descriptor->type);
-
- if (request.status != MIDI::PortRequest::OK) {
- error << string_compose(_("MIDI port specifications for \"%1\" are not understandable."), port_descriptor->tag) << endmsg;
- continue;
- }
-
- MIDI::Manager::instance()->add_port (request);
-
- nports++;
+ for (std::map<string,XMLNode>::iterator i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) {
+ MIDI::Manager::instance()->add_port (i->second);
}
MIDI::Port* first;
const MIDI::Manager::PortMap& ports = MIDI::Manager::instance()->get_midi_ports();
- first = ports.begin()->second;
- if (nports > 1) {
+ if (ports.size() > 1) {
- /* More than one port, so try using specific names for each port */
+ first = ports.begin()->second;
- map<string,Configuration::MidiPortDescriptor *>::iterator i;
+ /* More than one port, so try using specific names for each port */
if (Config->get_mmc_port_name() != N_("default")) {
default_mmc_port = MIDI::Manager::instance()->port (Config->get_mmc_port_name());
@@ -182,11 +160,13 @@ ARDOUR::setup_midi (AudioEngine& engine)
default_midi_port = first;
}
- } else {
+ } else if (ports.size() == 1) {
+
+ first = ports.begin()->second;
/* Only one port described, so use it for both MTC and MMC */
- default_mmc_port = MIDI::Manager::instance()->port ("");
+ default_mmc_port = first;
default_mtc_port = default_mmc_port;
default_midi_port = default_mmc_port;
}
@@ -209,15 +189,16 @@ ARDOUR::setup_midi (AudioEngine& engine)
return 0;
}
-
+
void
setup_hardware_optimization (bool try_optimization)
{
bool generic_mix_functions = true;
- FPU fpu;
if (try_optimization) {
+ FPU fpu;
+
#if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
if (fpu.has_sse()) {
@@ -253,6 +234,10 @@ setup_hardware_optimization (bool try_optimization)
info << "Apple VecLib H/W specific optimizations in use" << endmsg;
}
#endif
+
+ /* consider FPU denormal handling to be "h/w optimization" */
+
+ setup_fpu ();
}
if (generic_mix_functions) {
@@ -265,9 +250,6 @@ setup_hardware_optimization (bool try_optimization)
info << "No H/W specific optimizations in use" << endmsg;
}
-
- setup_fpu ();
-
}
int
@@ -306,6 +288,8 @@ ARDOUR::init (bool use_vst, bool try_optimization)
setup_hardware_optimization (try_optimization);
+ SourceFactory::init ();
+
/* singleton - first object is "it" */
new PluginManager ();
@@ -387,6 +371,13 @@ ARDOUR::LocaleGuard::~LocaleGuard ()
void
ARDOUR::setup_fpu ()
{
+
+ if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
+ // valgrind doesn't understand this assembler stuff
+ // September 10th, 2007
+ return;
+ }
+
#if defined(ARCH_X86) && defined(USE_XMMINTRIN)
int MXCSR;
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index bc16cde156..bd6351cf05 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -32,9 +32,9 @@
#include <glibmm.h>
#include <pbd/basename.h>
+#include <pbd/convert.h>
#include <ardour/ardour.h>
-#include <ardour/types.h>
#include <ardour/session.h>
#include <ardour/session_directory.h>
#include <ardour/audio_diskstream.h>
@@ -43,82 +43,22 @@
#include <ardour/audioregion.h>
#include <ardour/region_factory.h>
#include <ardour/source_factory.h>
-
+#include <ardour/resampled_source.h>
#include "i18n.h"
using namespace ARDOUR;
using namespace PBD;
-#define BLOCKSIZE 4096U
-
-class ImportableSource {
- public:
- ImportableSource (SNDFILE* sf, SF_INFO* info) : in (sf), sf_info (info) {}
- virtual ~ImportableSource() {}
-
- virtual nframes_t read (Sample* buffer, nframes_t nframes) {
- nframes_t per_channel = nframes / sf_info->channels;
- per_channel = sf_readf_float (in, buffer, per_channel);
- return per_channel * sf_info->channels;
- }
-
- virtual float ratio() const { return 1.0f; }
-
-protected:
- SNDFILE* in;
- SF_INFO* sf_info;
-};
-
-class ResampledImportableSource : public ImportableSource {
- public:
- ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate) : ImportableSource (sf, info) {
- int err;
-
- sf_seek (in, 0, SEEK_SET) ;
-
- /* Initialize the sample rate converter. */
-
- if ((src_state = src_new (SRC_SINC_BEST_QUALITY, sf_info->channels, &err)) == 0) {
- error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
- throw failed_constructor ();
- }
-
- src_data.end_of_input = 0 ; /* Set this later. */
-
- /* Start with zero to force load in while loop. */
-
- src_data.input_frames = 0 ;
- src_data.data_in = input ;
-
- src_data.src_ratio = ((float) rate) / sf_info->samplerate ;
-
- }
-
- ~ResampledImportableSource () {
- src_state = src_delete (src_state) ;
- }
-
- nframes_t read (Sample* buffer, nframes_t nframes);
-
- float ratio() const { return src_data.src_ratio; }
-
- private:
- float input[BLOCKSIZE];
- SRC_STATE* src_state;
- SRC_DATA src_data;
-};
-
int
Session::import_audiofile (import_status& status)
{
SNDFILE *in;
vector<boost::shared_ptr<AudioFileSource> > newfiles;
- SourceList sources;
SF_INFO info;
float *data = 0;
Sample **channel_data = 0;
- long nfiles = 0;
+ int nfiles = 0;
string basepath;
string sounds_dir;
nframes_t so_far;
@@ -127,178 +67,166 @@ Session::import_audiofile (import_status& status)
vector<string> new_paths;
struct tm* now;
ImportableSource* importable = 0;
- const nframes_t nframes = BLOCKSIZE;
-
- status.new_regions.clear ();
-
- if ((in = sf_open (status.paths.front().c_str(), SFM_READ, &info)) == 0) {
- error << string_compose(_("Import: cannot open input sound file \"%1\""), status.paths.front()) << endmsg;
- status.done = 1;
- status.cancel = 1;
- return -1;
- }
-
- if ((nframes_t) info.samplerate != frame_rate()) {
- importable = new ResampledImportableSource (in, &info, frame_rate());
- } else {
- importable = new ImportableSource (in, &info);
- }
-
- for (int n = 0; n < info.channels; ++n) {
- newfiles.push_back (boost::shared_ptr<AudioFileSource>());
- }
+ const nframes_t nframes = ResampledImportableSource::blocksize;
+ uint32_t cnt = 1;
- SessionDirectory sdir(get_best_session_directory_for_new_source ());
- sounds_dir = sdir.sound_path().to_string();
-
- basepath = PBD::basename_nosuffix (status.paths.front());
+ status.sources.clear ();
+
+ for (vector<Glib::ustring>::iterator p = status.paths.begin(); p != status.paths.end(); ++p, ++cnt) {
- for (int n = 0; n < info.channels; ++n) {
+ if ((in = sf_open ((*p).c_str(), SFM_READ, &info)) == 0) {
+ error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
+ status.done = 1;
+ status.cancel = 1;
+ return -1;
+ }
+
+ if ((nframes_t) info.samplerate != frame_rate()) {
+ importable = new ResampledImportableSource (in, &info, frame_rate(), status.quality);
+ } else {
+ importable = new ImportableSource (in, &info);
+ }
+
+ newfiles.clear ();
- bool goodfile = false;
+ for (int n = 0; n < info.channels; ++n) {
+ newfiles.push_back (boost::shared_ptr<AudioFileSource>());
+ }
+
+ SessionDirectory sdir(get_best_session_directory_for_new_source ());
+ sounds_dir = sdir.sound_path().to_string();
- do {
- if (info.channels == 2) {
- if (n == 0) {
- snprintf (buf, sizeof(buf), "%s/%s-L.wav", sounds_dir.c_str(), basepath.c_str());
+ basepath = PBD::basename_nosuffix ((*p));
+
+ for (int n = 0; n < info.channels; ++n) {
+
+ bool goodfile = false;
+
+ do {
+ if (info.channels == 2) {
+ if (n == 0) {
+ snprintf (buf, sizeof(buf), "%s/%s-L.wav", sounds_dir.c_str(), basepath.c_str());
+ } else {
+ snprintf (buf, sizeof(buf), "%s/%s-R.wav", sounds_dir.c_str(), basepath.c_str());
+ }
+ } else if (info.channels > 1) {
+ snprintf (buf, sizeof(buf), "%s/%s-c%d.wav", sounds_dir.c_str(), basepath.c_str(), n+1);
} else {
- snprintf (buf, sizeof(buf), "%s/%s-R.wav", sounds_dir.c_str(), basepath.c_str());
+ snprintf (buf, sizeof(buf), "%s/%s.wav", sounds_dir.c_str(), basepath.c_str());
}
- } else if (info.channels > 1) {
- snprintf (buf, sizeof(buf), "%s/%s-c%d.wav", sounds_dir.c_str(), basepath.c_str(), n+1);
- } else {
- snprintf (buf, sizeof(buf), "%s/%s.wav", sounds_dir.c_str(), basepath.c_str());
- }
- if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
+ if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
- /* if the file already exists, we must come up with
- * a new name for it. for now we just keep appending
- * _ to basepath
- */
+ /* if the file already exists, we must come up with
+ * a new name for it. for now we just keep appending
+ * _ to basepath
+ */
- basepath += "_";
+ basepath += "_";
- } else {
+ } else {
- goodfile = true;
- }
+ goodfile = true;
+ }
- } while ( !goodfile);
+ } while ( !goodfile);
- try {
- newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (
- SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
- }
+ try {
+ newfiles[n] = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
+ }
- catch (failed_constructor& err) {
- error << string_compose(_("Session::import_audiofile: cannot open new file source for channel %1"), n+1) << endmsg;
- goto out;
- }
+ catch (failed_constructor& err) {
+ error << string_compose(_("Session::import_audiofile: cannot open new file source for channel %1"), n+1) << endmsg;
+ goto out;
+ }
- new_paths.push_back (buf);
- nfiles++;
- }
+ new_paths.push_back (buf);
+ newfiles[n]->prepare_for_peakfile_writes ();
+ nfiles++;
+ }
- data = new float[nframes * info.channels];
- channel_data = new Sample * [ info.channels ];
+ data = new float[nframes * info.channels];
+ channel_data = new Sample * [ info.channels ];
- for (int n = 0; n < info.channels; ++n) {
- channel_data[n] = new Sample[nframes];
- }
+ for (int n = 0; n < info.channels; ++n) {
+ channel_data[n] = new Sample[nframes];
+ }
- so_far = 0;
+ so_far = 0;
- status.doing_what = _("converting audio");
- status.progress = 0.0;
+ if ((nframes_t) info.samplerate != frame_rate()) {
+ status.doing_what = string_compose (_("converting %1\n(resample from %2KHz to %3KHz)\n(%4 of %5)"),
+ basepath,
+ info.samplerate/1000.0f,
+ frame_rate()/1000.0f,
+ cnt, status.paths.size());
+
+ } else {
+ status.doing_what = string_compose (_("converting %1\n(%2 of %3)"),
+ basepath,
+ cnt, status.paths.size());
- while (!status.cancel) {
+ }
+
+ status.progress = 0.0;
+
+ while (!status.cancel) {
- nframes_t nread, nfread;
- long x;
- long chn;
+ nframes_t nread, nfread;
+ long x;
+ long chn;
- if ((nread = importable->read (data, nframes)) == 0) {
- break;
- }
- nfread = nread / info.channels;
+ if ((nread = importable->read (data, nframes)) == 0) {
+ break;
+ }
+ nfread = nread / info.channels;
- /* de-interleave */
+ /* de-interleave */
- for (chn = 0; chn < info.channels; ++chn) {
+ for (chn = 0; chn < info.channels; ++chn) {
- nframes_t n;
- for (x = chn, n = 0; n < nfread; x += info.channels, ++n) {
- channel_data[chn][n] = (Sample) data[x];
+ nframes_t n;
+ for (x = chn, n = 0; n < nfread; x += info.channels, ++n) {
+ channel_data[chn][n] = (Sample) data[x];
+ }
}
- }
- /* flush to disk */
+ /* flush to disk */
- for (chn = 0; chn < info.channels; ++chn) {
- newfiles[chn]->write (channel_data[chn], nfread);
- }
+ for (chn = 0; chn < info.channels; ++chn) {
+ newfiles[chn]->write (channel_data[chn], nfread);
+ }
- so_far += nread;
- status.progress = so_far / (importable->ratio () * info.frames * info.channels);
- }
+ so_far += nread;
+ status.progress = so_far / (importable->ratio () * info.frames * info.channels);
+ }
- if (status.cancel) {
- goto out;
- }
+ if (status.cancel) {
+ goto out;
+ }
+
+ for (int n = 0; n < info.channels; ++n) {
+ status.sources.push_back (newfiles[n]);
+ }
- if (status.multichan) {
- status.doing_what = _("building region");
- } else {
- status.doing_what = _("building regions");
+ if (status.cancel) {
+ goto out;
+ }
}
-
+
status.freeze = true;
time_t xnow;
time (&xnow);
now = localtime (&xnow);
- if (status.multichan) {
- /* all sources are used in a single multichannel region */
+ /* flush the final length(s) to the header(s) */
- for (int n = 0; n < nfiles && !status.cancel; ++n) {
- /* flush the final length to the header */
- newfiles[n]->update_header(0, *now, xnow);
- sources.push_back(newfiles[n]);
- }
-
- bool strip_paired_suffixes = (newfiles.size() > 1);
-
- boost::shared_ptr<AudioRegion> r (boost::dynamic_pointer_cast<AudioRegion>
- (RegionFactory::create (sources, 0,
- newfiles[0]->length(),
- region_name_from_path (basepath, strip_paired_suffixes),
- 0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile))));
-
- status.new_regions.push_back (r);
-
- } else {
- for (int n = 0; n < nfiles && !status.cancel; ++n) {
-
- /* flush the final length to the header */
-
- newfiles[n]->update_header(0, *now, xnow);
-
- /* The sources had zero-length when created, which means that the Session
- did not bother to create whole-file AudioRegions for them. Do it now.
-
- Note: leave any trailing paired indicators from the file names as part
- of the region name.
- */
-
- status.new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion>
- (RegionFactory::create (boost::static_pointer_cast<Source> (newfiles[n]), 0, newfiles[n]->length(),
- region_name_from_path (newfiles[n]->name(), false),
- 0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile | AudioRegion::Import))));
- }
+ for (SourceList::iterator x = status.sources.begin(); x != status.sources.end() && !status.cancel; ++x) {
+ boost::dynamic_pointer_cast<AudioFileSource>(*x)->update_header(0, *now, xnow);
+ boost::dynamic_pointer_cast<AudioSource>(*x)->done_with_peakfile_writes ();
}
-
+
/* save state so that we don't lose these new Sources */
if (!status.cancel) {
@@ -321,7 +249,8 @@ Session::import_audiofile (import_status& status)
}
if (status.cancel) {
- status.new_regions.clear ();
+
+ status.sources.clear ();
for (vector<string>::iterator i = new_paths.begin(); i != new_paths.end(); ++i) {
unlink ((*i).c_str());
@@ -337,50 +266,3 @@ Session::import_audiofile (import_status& status)
return ret;
}
-
-nframes_t
-ResampledImportableSource::read (Sample* output, nframes_t nframes)
-{
- int err;
-
- /* If the input buffer is empty, refill it. */
-
- if (src_data.input_frames == 0) {
-
- src_data.input_frames = ImportableSource::read (input, BLOCKSIZE);
-
- /* The last read will not be a full buffer, so set end_of_input. */
-
- if ((nframes_t) src_data.input_frames < BLOCKSIZE) {
- src_data.end_of_input = SF_TRUE ;
- }
-
- src_data.input_frames /= sf_info->channels;
- src_data.data_in = input ;
- }
-
- src_data.data_out = output;
-
- if (!src_data.end_of_input) {
- src_data.output_frames = nframes / sf_info->channels ;
- } else {
- src_data.output_frames = src_data.input_frames;
- }
-
- if ((err = src_process (src_state, &src_data))) {
- error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ;
- return 0 ;
- }
-
- /* Terminate if at end */
-
- if (src_data.end_of_input && src_data.output_frames_gen == 0) {
- return 0;
- }
-
- src_data.data_in += src_data.input_frames_used * sf_info->channels ;
- src_data.input_frames -= src_data.input_frames_used ;
-
- return src_data.output_frames_gen * sf_info->channels;
-}
-
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index a708821c20..bff8c18bc9 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -1307,7 +1307,7 @@ IO::state (bool full_state)
int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
- snprintf (buf, sizeof(buf)-1, "%zd,%d,%zd,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
+ snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
node->add_property ("iolimits", buf);
@@ -2335,7 +2335,7 @@ IO::automation_snapshot (nframes_t now)
{
Automatable::automation_snapshot (now);
- if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _session.automation_interval()) {
+ if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
_panner->snapshot (now);
}
}
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 4af7e2b907..09b54000d8 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -1176,8 +1176,8 @@ Playlist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
save = !(_splicing || _nudging);
}
- if ((what_changed & Region::MuteChanged) &&
- !(what_changed & Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged))) {
+ if ((what_changed & our_interests) &&
+ !(what_changed & Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged))) {
check_dependents (region, false);
}
diff --git a/libs/ardour/resampled_source.cc b/libs/ardour/resampled_source.cc
new file mode 100644
index 0000000000..38aa3832b9
--- /dev/null
+++ b/libs/ardour/resampled_source.cc
@@ -0,0 +1,128 @@
+/*
+ Copyright (C) 2007 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <pbd/error.h>
+#include <ardour/resampled_source.h>
+#include <pbd/failed_constructor.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+const uint32_t ResampledImportableSource::blocksize = 4096U;
+
+ResampledImportableSource::ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate, SrcQuality srcq)
+ : ImportableSource (sf, info)
+{
+ int err;
+
+ sf_seek (in, 0, SEEK_SET) ;
+
+ /* Initialize the sample rate converter. */
+
+ int src_type;
+
+ switch (srcq) {
+ case SrcBest:
+ src_type = SRC_SINC_BEST_QUALITY;
+ break;
+ case SrcGood:
+ src_type = SRC_SINC_MEDIUM_QUALITY;
+ break;
+ case SrcQuick:
+ src_type = SRC_SINC_FASTEST;
+ break;
+ case SrcFast:
+ src_type = SRC_ZERO_ORDER_HOLD;
+ break;
+ case SrcFastest:
+ src_type = SRC_LINEAR;
+ break;
+ }
+
+ if ((src_state = src_new (src_type, sf_info->channels, &err)) == 0) {
+ error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
+ throw failed_constructor ();
+ }
+
+ src_data.end_of_input = 0 ; /* Set this later. */
+
+ /* Start with zero to force load in while loop. */
+
+ src_data.input_frames = 0 ;
+ src_data.data_in = input ;
+
+ src_data.src_ratio = ((float) rate) / sf_info->samplerate ;
+
+ input = new float[blocksize];
+}
+
+ResampledImportableSource::~ResampledImportableSource ()
+{
+ src_state = src_delete (src_state) ;
+ delete [] input;
+}
+
+nframes_t
+ResampledImportableSource::read (Sample* output, nframes_t nframes)
+{
+ int err;
+
+ /* If the input buffer is empty, refill it. */
+
+ if (src_data.input_frames == 0) {
+
+ src_data.input_frames = ImportableSource::read (input, blocksize);
+
+ /* The last read will not be a full buffer, so set end_of_input. */
+
+ if ((nframes_t) src_data.input_frames < blocksize) {
+ src_data.end_of_input = SF_TRUE ;
+ }
+
+ src_data.input_frames /= sf_info->channels;
+ src_data.data_in = input ;
+ }
+
+ src_data.data_out = output;
+
+ if (!src_data.end_of_input) {
+ src_data.output_frames = nframes / sf_info->channels ;
+ } else {
+ src_data.output_frames = src_data.input_frames;
+ }
+
+ if ((err = src_process (src_state, &src_data))) {
+ error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ;
+ return 0 ;
+ }
+
+ /* Terminate if at end */
+
+ if (src_data.end_of_input && src_data.output_frames_gen == 0) {
+ return 0;
+ }
+
+ src_data.data_in += src_data.input_frames_used * sf_info->channels ;
+ src_data.input_frames -= src_data.input_frames_used ;
+
+ return src_data.output_frames_gen * sf_info->channels;
+}
+
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 19095425f2..be7dfb8469 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -53,7 +53,7 @@ using namespace ARDOUR;
using namespace PBD;
uint32_t Route::order_key_cnt = 0;
-
+sigc::signal<void> Route::SyncOrderKeys;
Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type)
: IO (sess, name, input_min, input_max, output_min, output_max, default_type),
@@ -161,10 +161,35 @@ void
Route::set_order_key (const char* name, long n)
{
order_keys[strdup(name)] = n;
+
+ if (Config->get_sync_all_route_ordering()) {
+ for (OrderKeys::iterator x = order_keys.begin(); x != order_keys.end(); ++x) {
+ x->second = n;
+ }
+ }
+
_session.set_dirty ();
}
void
+Route::sync_order_keys ()
+{
+ uint32_t key;
+
+ if (order_keys.empty()) {
+ return;
+ }
+
+ OrderKeys::iterator x = order_keys.begin();
+ key = x->second;
+ ++x;
+
+ for (; x != order_keys.end(); ++x) {
+ x->second = key;
+ }
+}
+
+void
Route::inc_gain (gain_t fraction, void *src)
{
IO::inc_gain (fraction, src);
@@ -460,13 +485,9 @@ Route::process_output_buffers (BufferSet& bufs,
// OR recording
- // h/w monitoring not in use
-
- (!Config->get_monitoring_model() == HardwareMonitoring &&
-
// AND software monitoring required
- Config->get_monitoring_model() == SoftwareMonitoring)) {
+ Config->get_monitoring_model() == SoftwareMonitoring) {
if (apply_gain_automation) {
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 742b17af2c..e7f2c542e6 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -124,8 +124,7 @@ Session::Session (AudioEngine &eng,
routes (new RouteList),
auditioner ((Auditioner*) 0),
_click_io ((IO*) 0),
- main_outs (0),
- _automation_interval (0)
+ main_outs (0)
{
if (!eng.connected()) {
throw failed_constructor();
@@ -224,8 +223,7 @@ Session::Session (AudioEngine &eng,
_send_smpte_update (false),
diskstreams (new DiskstreamList),
routes (new RouteList),
- main_outs (0),
- _automation_interval (0)
+ main_outs (0)
{
if (!eng.connected()) {
@@ -1257,8 +1255,10 @@ Session::set_frame_rate (nframes_t frames_per_second)
sync_time_vars();
- _automation_interval = ((nframes_t) ceil ((double) frames_per_second * 0.25));
+ Automatable::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
+ clear_clicks ();
+
// XXX we need some equivalent to this, somehow
// SndFileSource::setup_standard_crossfades (frames_per_second);
@@ -2755,13 +2755,11 @@ Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
return boost::shared_ptr<Source>();
}
-string
-Session::peak_path_from_audio_path (string audio_path) const
+Glib::ustring
+Session::peak_path (Glib::ustring base) const
{
sys::path peakfile_path(_session_dir->peak_path());
-
- peakfile_path /= basename_nosuffix (audio_path) + peakfile_suffix;
-
+ peakfile_path /= basename_nosuffix (base) + peakfile_suffix;
return peakfile_path.to_string();
}
@@ -3387,8 +3385,8 @@ Session::remove_empty_sounds ()
try
{
sys::remove (audio_file_path);
- const string peak_path = peak_path_from_audio_path (audio_file_path.to_string());
- sys::remove (peak_path);
+ const string peakfile = peak_path (audio_file_path.to_string());
+ sys::remove (peakfile);
}
catch (const sys::filesystem_error& err)
{
@@ -4124,6 +4122,23 @@ Session::compute_initial_length ()
}
void
+Session::sync_order_keys ()
+{
+ if (!Config->get_sync_all_route_ordering()) {
+ /* leave order keys as they are */
+ return;
+ }
+
+ boost::shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ (*i)->sync_order_keys ();
+ }
+
+ Route::SyncOrderKeys (); // EMIT SIGNAL
+}
+
+void
Session::foreach_bundle (sigc::slot<void, boost::shared_ptr<Bundle> > sl)
{
Glib::Mutex::Lock lm (bundle_lock);
diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc
index 35c1019c0e..aa5a1b87d4 100644
--- a/libs/ardour/session_events.cc
+++ b/libs/ardour/session_events.cc
@@ -410,6 +410,8 @@ Session::process_event (Event* ev)
case Event::Audition:
set_audition (ev->region);
+ // drop reference to region
+ ev->region.reset ();
break;
case Event::InputConfigurationChange:
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index f2f396cbee..0534da6c89 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -138,10 +138,14 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_name = _current_snapshot_name = snapshot_name;
+ set_history_depth (Config->get_history_depth());
+
_current_frame_rate = _engine.frame_rate ();
_tempo_map = new TempoMap (_current_frame_rate);
_tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
+
+
g_atomic_int_set (&processing_prohibited, 0);
insert_cnt = 0;
_transport_speed = 0;
@@ -501,7 +505,7 @@ void
Session::remove_pending_capture_state ()
{
sys::path pending_state_file_path(_session_dir->root_path());
-
+
pending_state_file_path /= _current_snapshot_name + pending_suffix;
try
@@ -2668,8 +2672,6 @@ Session::save_history (string snapshot_name)
{
XMLTree tree;
- tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
-
if (snapshot_name.empty()) {
snapshot_name = _current_snapshot_name;
}
@@ -2691,6 +2693,13 @@ Session::save_history (string snapshot_name)
}
}
+
+ if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
+ return 0;
+ }
+
+ tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
+
if (!tree.write (xml_path.to_string()))
{
error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
@@ -2977,6 +2986,10 @@ Session::config_changed (const char* parameter_name)
set_remote_control_ids ();
} else if (PARAM_IS ("denormal-model")) {
setup_fpu ();
+ } else if (PARAM_IS ("history-depth")) {
+ set_history_depth (Config->get_history_depth());
+ } else if (PARAM_IS ("sync-all-route-ordering")) {
+ sync_order_keys ();
}
set_dirty ();
@@ -2984,3 +2997,9 @@ Session::config_changed (const char* parameter_name)
#undef PARAM_IS
}
+
+void
+Session::set_history_depth (uint32_t d)
+{
+ _history.set_depth (d);
+}
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index 6977eef6bd..7c4859aa55 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -25,7 +25,7 @@
#include <sys/stat.h>
#include <glibmm/miscutils.h>
-
+#include <glibmm/thread.h>
#include <ardour/sndfilesource.h>
#include <ardour/sndfile_helpers.h>
#include <ardour/utils.h>
@@ -45,6 +45,21 @@ const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSou
AudioFileSource::RemovableIfEmpty|
AudioFileSource::CanRename);
+struct SizedSampleBuffer {
+ nframes_t size;
+ Sample* buf;
+
+ SizedSampleBuffer (nframes_t sz) : size (sz) {
+ buf = new Sample[size];
+ }
+
+ ~SizedSampleBuffer() {
+ delete [] buf;
+ }
+};
+
+Glib::StaticPrivate<SizedSampleBuffer> thread_interleave_buffer = GLIBMM_STATIC_PRIVATE_INIT;
+
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
: AudioFileSource (s, node)
{
@@ -186,8 +201,6 @@ SndFileSource::init ()
// lets try to keep the object initalizations here at the top
xfade_buf = 0;
- interleave_buf = 0;
- interleave_bufsize = 0;
sf = 0;
_broadcast_info = 0;
@@ -272,10 +285,6 @@ SndFileSource::~SndFileSource ()
touch_peakfile ();
}
- if (interleave_buf) {
- delete [] interleave_buf;
- }
-
if (_broadcast_info) {
delete _broadcast_info;
}
@@ -341,14 +350,7 @@ SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
real_cnt = cnt * _info.channels;
- if (interleave_bufsize < real_cnt) {
-
- if (interleave_buf) {
- delete [] interleave_buf;
- }
- interleave_bufsize = real_cnt;
- interleave_buf = new float[interleave_bufsize];
- }
+ Sample* interleave_buf = get_interleave_buffer (real_cnt);
nread = sf_read_float (sf, interleave_buf, real_cnt);
ptr = interleave_buf + _channel;
@@ -401,7 +403,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
update_length (oldlen, cnt);
if (_build_peakfiles) {
- compute_and_write_peaks (data, frame_pos, cnt, false);
+ compute_and_write_peaks (data, frame_pos, cnt, false, true);
}
_write_data_count = cnt;
@@ -493,7 +495,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
update_length (file_pos, cnt);
if (_build_peakfiles) {
- compute_and_write_peaks (data, file_pos, cnt, false);
+ compute_and_write_peaks (data, file_pos, cnt, false, true);
}
file_pos += cnt;
@@ -904,3 +906,21 @@ SndFileSource::one_of_several_channels () const
{
return _info.channels > 1;
}
+
+Sample*
+SndFileSource::get_interleave_buffer (nframes_t size)
+{
+ SizedSampleBuffer* ssb;
+
+ if ((ssb = thread_interleave_buffer.get()) == 0) {
+ ssb = new SizedSampleBuffer (size);
+ thread_interleave_buffer.set (ssb);
+ }
+
+ if (ssb->size < size) {
+ ssb = new SizedSampleBuffer (size);
+ thread_interleave_buffer.set (ssb);
+ }
+
+ return ssb->buf;
+}
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 148f737551..c6b19c8600 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -19,6 +19,8 @@
*/
#include <pbd/error.h>
+#include <pbd/convert.h>
+#include <pbd/pthread_utils.h>
#include <ardour/source_factory.h>
#include <ardour/sndfilesource.h>
@@ -37,15 +39,69 @@ using namespace std;
using namespace PBD;
sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
+Glib::Cond* SourceFactory::PeaksToBuild;
+Glib::StaticMutex SourceFactory::peak_building_lock;
+std::list<boost::weak_ptr<AudioSource> > SourceFactory::files_with_peaks;
+
+static void
+peak_thread_work ()
+{
+ PBD::ThreadCreated (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec));
+
+ while (true) {
+
+ SourceFactory::peak_building_lock.lock ();
+
+ wait:
+ if (SourceFactory::files_with_peaks.empty()) {
+ SourceFactory::PeaksToBuild->wait (SourceFactory::peak_building_lock);
+ }
+
+ if (SourceFactory::files_with_peaks.empty()) {
+ goto wait;
+ }
+
+ boost::shared_ptr<AudioSource> as (SourceFactory::files_with_peaks.front().lock());
+ SourceFactory::files_with_peaks.pop_front ();
+ SourceFactory::peak_building_lock.unlock ();
+
+ if (!as) {
+ continue;
+ }
+
+ as->setup_peakfile ();
+ }
+}
+
+void
+SourceFactory::init ()
+{
+ PeaksToBuild = new Glib::Cond();
+
+ for (int n = 0; n < 2; ++n) {
+ Glib::Thread::create (sigc::ptr_fun (::peak_thread_work), false);
+ }
+}
int
-SourceFactory::setup_peakfile (boost::shared_ptr<Source> s)
+SourceFactory::setup_peakfile (boost::shared_ptr<Source> s, bool async)
{
boost::shared_ptr<AudioSource> as (boost::dynamic_pointer_cast<AudioSource> (s));
+
if (as) {
- if (as->setup_peakfile ()) {
- error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg;
- return -1;
+
+ if (async) {
+
+ Glib::Mutex::Lock lm (peak_building_lock);
+ files_with_peaks.push_back (boost::weak_ptr<AudioSource> (as));
+ PeaksToBuild->broadcast ();
+
+ } else {
+
+ if (as->setup_peakfile ()) {
+ error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg;
+ return -1;
+ }
}
}
@@ -60,84 +116,85 @@ SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes,
return ret;
}
+#ifdef USE_COREAUDIO_FOR_FILES
boost::shared_ptr<Source>
-SourceFactory::create (Session& s, const XMLNode& node)
+SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
{
- /* this is allowed to throw */
-
- DataType type = DataType::AUDIO;
- const XMLProperty* prop = node.property("type");
- if (prop) {
- type = DataType(prop->value());
- }
-
- if (type == DataType::AUDIO) {
-
-#ifdef HAVE_COREAUDIO
- try {
- boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
- if (setup_peakfile (ret)) {
+ try {
+ boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
+ if (!defer_peaks) {
+ if (setup_peakfile (ret, false)) {
return boost::shared_ptr<Source>();
}
- SourceCreated (ret);
- return ret;
- }
+ }
+ SourceCreated (ret);
+ return ret;
+ }
- catch (failed_constructor& err) {
-
- /* this is allowed to throw */
-
- boost::shared_ptr<Source> ret (new SndFileSource (s, node));
- if (setup_peakfile (ret)) {
+
+ catch (failed_constructor& err) {
+
+ /* this is allowed to throw */
+
+ boost::shared_ptr<Source> ret (new SndFileSource (s, node));
+ if (!defer_peaks) {
+ if (setup_peakfile (ret, false)) {
return boost::shared_ptr<Source>();
}
- SourceCreated (ret);
- return ret;
}
-#else
- boost::shared_ptr<Source> ret (new SndFileSource (s, node));
-
- if (setup_peakfile (ret)) {
- return boost::shared_ptr<Source>();
- }
-
SourceCreated (ret);
return ret;
-#endif
+ }
- } else if (type == DataType::MIDI) {
+ return boost::shared_ptr<Source>();
+}
- boost::shared_ptr<Source> ret (new SMFSource (s, node));
-
- SourceCreated (ret);
- return ret;
+#else
+
+boost::shared_ptr<Source>
+SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
+{
+ /* this is allowed to throw */
+ boost::shared_ptr<Source> ret (new SndFileSource (s, node));
+
+ if (!defer_peaks) {
+ if (setup_peakfile (ret, false)) {
+ return boost::shared_ptr<Source>();
+ }
}
- return boost::shared_ptr<Source> ();
+ SourceCreated (ret);
+ return ret;
}
+#endif // USE_COREAUDIO_FOR_FILES
+
boost::shared_ptr<Source>
-SourceFactory::createReadable (DataType type, Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce)
+SourceFactory::createReadable (DataType type, Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce, bool defer_peaks)
{
if (type == DataType::AUDIO) {
#ifdef HAVE_COREAUDIO
try {
boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, chn, flags));
- if (setup_peakfile (ret)) {
- return boost::shared_ptr<Source>();
+ if (!defer_peaks) {
+ if (setup_peakfile (ret, false)) {
+ return boost::shared_ptr<Source>();
+ }
}
if (announce) {
SourceCreated (ret);
}
return ret;
}
-
+
catch (failed_constructor& err) {
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
- if (setup_peakfile (ret)) {
- return boost::shared_ptr<Source>();
+ if (!defer_peaks) {
+ if (setup_peakfile (ret, false)) {
+ return boost::shared_ptr<Source>();
+ }
}
if (announce) {
SourceCreated (ret);
@@ -147,8 +204,10 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
#else
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
- if (setup_peakfile (ret)) {
- return boost::shared_ptr<Source>();
+ if (!defer_peaks) {
+ if (setup_peakfile (ret, false)) {
+ return boost::shared_ptr<Source>();
+ }
}
if (announce) {
@@ -157,7 +216,7 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
return ret;
#endif
-
+
} else if (type == DataType::MIDI) {
// FIXME: flags?
@@ -174,21 +233,23 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
}
boost::shared_ptr<Source>
-SourceFactory::createWritable (DataType type, Session& s, std::string path, bool destructive, nframes_t rate, bool announce)
+SourceFactory::createWritable (DataType type, Session& s, std::string path, bool destructive, nframes_t rate, bool announce, bool defer_peaks)
{
/* this might throw failed_constructor(), which is OK */
-
+
if (type == DataType::AUDIO) {
boost::shared_ptr<Source> ret (new SndFileSource
- (s, path,
- Config->get_native_file_data_format(),
- Config->get_native_file_header_format(),
- rate,
- (destructive ? AudioFileSource::Flag (SndFileSource::default_writable_flags | AudioFileSource::Destructive) :
- SndFileSource::default_writable_flags)));
-
- if (setup_peakfile (ret)) {
- return boost::shared_ptr<Source>();
+ (s, path,
+ Config->get_native_file_data_format(),
+ Config->get_native_file_header_format(),
+ rate,
+ (destructive ? AudioFileSource::Flag (SndFileSource::default_writable_flags | AudioFileSource::Destructive) :
+ SndFileSource::default_writable_flags)));
+
+ if (!defer_peaks) {
+ if (setup_peakfile (ret, false)) {
+ return boost::shared_ptr<Source>();
+ }
}
if (announce) {
SourceCreated (ret);
diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc
index 01e070e920..cfd38c5099 100644
--- a/libs/ardour/utils.cc
+++ b/libs/ardour/utils.cc
@@ -143,7 +143,7 @@ touch_file (ustring path)
}
ustring
-region_name_from_path (ustring path, bool strip_channels)
+region_name_from_path (ustring path, bool strip_channels, bool add_channel_suffix, uint32_t total, uint32_t this_one)
{
path = PBD::basename_nosuffix (path);
@@ -160,6 +160,17 @@ region_name_from_path (ustring path, bool strip_channels)
}
}
+ if (add_channel_suffix) {
+
+ path += '%';
+
+ if (total > 2) {
+ path += (char) ('a' + this_one);
+ } else {
+ path += (char) (this_one == 0 ? 'L' : 'R');
+ }
+ }
+
return path;
}