summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-04-12 23:20:37 +0000
committerDavid Robillard <d@drobilla.net>2007-04-12 23:20:37 +0000
commit959a7909c1adca430a63f783fd16687242a7be3d (patch)
treeb5048c3cc1bbb60bb680472b97ebba6ebb92d72f /libs/ardour
parent96ca08b9257e4048294cd1804a65d4ae6cd88814 (diff)
Merged with trunk R1705.
Synced .po files with trunk. Fixed more editor operations to be type agnostic (ie not audio only). git-svn-id: svn://localhost/ardour2/branches/midi@1709 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/audiofilesource.h3
-rw-r--r--libs/ardour/ardour/audioregion.h2
-rw-r--r--libs/ardour/ardour/configuration_vars.h1
-rw-r--r--libs/ardour/ardour/coreaudiosource.h2
-rw-r--r--libs/ardour/ardour/diskstream.h1
-rw-r--r--libs/ardour/ardour/playlist.h7
-rw-r--r--libs/ardour/ardour/profile.h31
-rw-r--r--libs/ardour/ardour/route.h4
-rw-r--r--libs/ardour/ardour/send.h2
-rw-r--r--libs/ardour/ardour/session.h4
-rw-r--r--libs/ardour/ardour/sndfilesource.h2
-rw-r--r--libs/ardour/ardour/source.h4
-rw-r--r--libs/ardour/audio_diskstream.cc10
-rw-r--r--libs/ardour/audiofilesource.cc104
-rw-r--r--libs/ardour/audioregion.cc72
-rw-r--r--libs/ardour/coreaudiosource.cc13
-rw-r--r--libs/ardour/diskstream.cc5
-rw-r--r--libs/ardour/globals.cc6
-rw-r--r--libs/ardour/insert.cc4
-rw-r--r--libs/ardour/ladspa_plugin.cc12
-rw-r--r--libs/ardour/midi_port.cc8
-rw-r--r--libs/ardour/panner.cc19
-rw-r--r--libs/ardour/playlist.cc23
-rw-r--r--libs/ardour/region.cc5
-rw-r--r--libs/ardour/route.cc44
-rw-r--r--libs/ardour/session.cc6
-rw-r--r--libs/ardour/session_butler.cc2
-rw-r--r--libs/ardour/session_midi.cc18
-rw-r--r--libs/ardour/session_process.cc3
-rw-r--r--libs/ardour/session_state.cc59
-rw-r--r--libs/ardour/session_time.cc1
-rw-r--r--libs/ardour/session_transport.cc10
-rw-r--r--libs/ardour/sndfilesource.cc6
-rw-r--r--libs/ardour/source.cc21
-rw-r--r--libs/ardour/vst_plugin.cc5
35 files changed, 392 insertions, 127 deletions
diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h
index 913cd7d5ed..149ceb7dc3 100644
--- a/libs/ardour/ardour/audiofilesource.h
+++ b/libs/ardour/ardour/audiofilesource.h
@@ -81,6 +81,7 @@ class AudioFileSource : public AudioSource {
virtual void mark_capture_start (nframes_t) {}
virtual void mark_capture_end () {}
virtual void clear_capture_marks() {}
+ virtual bool one_of_several_channels () const { return false; }
virtual int update_header (nframes_t when, struct tm&, time_t) = 0;
virtual int flush_header () = 0;
@@ -161,7 +162,7 @@ class AudioFileSource : public AudioSource {
virtual void set_timeline_position (int64_t pos);
virtual void set_header_timeline_position () = 0;
- bool find (Glib::ustring& path, bool must_exist, bool& is_new);
+ bool find (Glib::ustring& path, bool must_exist, bool& is_new, uint16_t& chan);
bool removable() const;
bool writable() const { return _flags & Writable; }
};
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index 3b592a54ee..e25278cce9 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -89,6 +89,8 @@ class AudioRegion : public Region
int set_state (const XMLNode&);
static void set_default_fade (float steepness, nframes_t len);
+ bool fade_in_is_default () const;
+ bool fade_out_is_default () const;
enum FadeShape {
Linear,
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 674a9232b5..4f0bae1208 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -17,7 +17,6 @@ CONFIG_VARIABLE (bool, send_mtc, "send-mtc", false)
CONFIG_VARIABLE (bool, send_mmc, "send-mmc", false)
CONFIG_VARIABLE (bool, mmc_control, "mmc-control", false)
CONFIG_VARIABLE (bool, midi_feedback, "midi-feedback", false)
-CONFIG_VARIABLE (bool, midi_control, "midi-control", false)
CONFIG_VARIABLE (uint8_t, mmc_device_id, "mmc-device-id", 0)
/* control surfaces */
diff --git a/libs/ardour/ardour/coreaudiosource.h b/libs/ardour/ardour/coreaudiosource.h
index 63c50d7cfb..ad21188531 100644
--- a/libs/ardour/ardour/coreaudiosource.h
+++ b/libs/ardour/ardour/coreaudiosource.h
@@ -52,7 +52,7 @@ class CoreAudioSource : public AudioFileSource {
mutable nframes_t tmpbufsize;
mutable Glib::Mutex _tmpbuf_lock;
- void init (string str);
+ void init ();
};
}; /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
index 10b3bbfe92..4809e17868 100644
--- a/libs/ardour/ardour/diskstream.h
+++ b/libs/ardour/ardour/diskstream.h
@@ -281,6 +281,7 @@ class Diskstream : public PBD::StatefulDestructible
nframes_t file_frame;
nframes_t playback_sample;
nframes_t playback_distance;
+ bool commit_should_unlock;
uint32_t _read_data_count;
uint32_t _write_data_count;
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 54863b6fb0..b1612f39d5 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -141,6 +141,12 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
virtual bool destroy_region (boost::shared_ptr<Region>) = 0;
+ /* special case function used by UI selection objects, which have playlists that actually own the regions
+ within them.
+ */
+
+ void drop_regions ();
+
protected:
friend class Session;
@@ -180,6 +186,7 @@ class Playlist : public PBD::StatefulDestructible, public boost::enable_shared_f
bool save_on_thaw;
string last_save_reason;
uint32_t in_set_state;
+ bool first_set_state;
bool _hidden;
bool _splicing;
bool _nudging;
diff --git a/libs/ardour/ardour/profile.h b/libs/ardour/ardour/profile.h
new file mode 100644
index 0000000000..2ee47d39ea
--- /dev/null
+++ b/libs/ardour/ardour/profile.h
@@ -0,0 +1,31 @@
+#ifndef __ardour_profile_h__
+#define __ardour_profile_h__
+
+#include <boost/dynamic_bitset.hpp>
+#include <stdint.h>
+
+namespace ARDOUR {
+
+class RuntimeProfile {
+ public:
+ enum Element {
+ SmallScreen,
+ LastElement
+ };
+
+ RuntimeProfile() { bits.resize (LastElement); }
+ ~RuntimeProfile() {}
+
+ void set_small_screen() { bits[SmallScreen] = true; }
+ bool get_small_screen() const { return bits[SmallScreen]; }
+
+ private:
+ boost::dynamic_bitset<uint64_t> bits;
+
+};
+
+extern RuntimeProfile* Profile;
+
+}; // namespace ARDOUR
+
+#endif /* __ardour_profile_h__ */
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 70091ef85d..6247d79a27 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -169,9 +169,9 @@ class Route : public IO
int copy_redirects (const Route&, Placement, uint32_t* err_streams = 0);
int sort_redirects (uint32_t* err_streams = 0);
- void clear_redirects (void *src);
+ void clear_redirects (Placement, void *src);
void all_redirects_flip();
- void all_redirects_active (bool state);
+ void all_redirects_active (Placement, bool state);
virtual nframes_t update_total_latency();
nframes_t signal_latency() const { return _own_latency; }
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index d4c0572811..4e3c0fbe2d 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -38,7 +38,7 @@ class Send : public Redirect
Send (Session&, Placement);
Send (Session&, const XMLNode&);
Send (const Send&);
- ~Send ();
+ virtual ~Send ();
uint32_t bit_slot() const { return bitslot; }
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 2022b21a05..a95b07a2e7 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -371,6 +371,7 @@ class Session : public PBD::StatefulDestructible
void set_session_start (nframes_t start) { start_location->set_start(start); }
void set_session_end (nframes_t end) { end_location->set_start(end); _end_location_is_free = false; }
void use_rf_shuttle_speed ();
+ void allow_auto_play (bool yn);
void request_transport_speed (float speed);
void request_overwrite_buffer (Diskstream*);
void request_diskstream_speed (Diskstream&, float speed);
@@ -424,6 +425,8 @@ class Session : public PBD::StatefulDestructible
int save_template (string template_name);
int save_history (string snapshot_name = "");
int restore_history (string snapshot_name);
+ void remove_state (string snapshot_name);
+ void rename_state (string old_name, string new_name);
static int rename_template (string old_name, string new_name);
@@ -1004,6 +1007,7 @@ class Session : public PBD::StatefulDestructible
volatile float _transport_speed;
volatile float _desired_transport_speed;
float _last_transport_speed;
+ bool auto_play_legal;
nframes_t _last_slave_transport_frame;
nframes_t maximum_output_latency;
nframes_t last_stop_frame;
diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h
index 2fc3872887..916e9da49e 100644
--- a/libs/ardour/ardour/sndfilesource.h
+++ b/libs/ardour/ardour/sndfilesource.h
@@ -56,6 +56,8 @@ class SndFileSource : public AudioFileSource {
bool set_destructive (bool yn);
+ bool one_of_several_channels () const;
+
static void setup_standard_crossfades (nframes_t sample_rate);
static const AudioFileSource::Flag default_writable_flags;
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index 45c91950fc..7b1179b81a 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -82,7 +82,9 @@ class Source : public PBD::StatefulDestructible
time_t _timestamp;
jack_nframes_t _length;
- std::set<boost::shared_ptr<ARDOUR::Playlist> > _playlists;
+ Glib::Mutex playlist_lock;
+ typedef std::map<boost::shared_ptr<ARDOUR::Playlist>, uint32_t > PlaylistMap;
+ PlaylistMap _playlists;
private:
uint32_t _in_use;
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index eeaa095fbd..2c878fbd4d 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -526,6 +526,8 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
return 0;
}
+ commit_should_unlock = false;
+
check_record_status (transport_frame, nframes, can_record);
nominally_recording = (can_record && re);
@@ -544,7 +546,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
if (!state_lock.trylock()) {
return 1;
}
-
+ commit_should_unlock = true;
adjust_capture_position = 0;
for (chan = c->begin(); chan != c->end(); ++chan) {
@@ -796,6 +798,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
be called. unlock the state lock.
*/
+ commit_should_unlock = false;
state_lock.unlock();
}
@@ -835,7 +838,10 @@ AudioDiskstream::commit (nframes_t nframes)
|| c->front()->capture_buf->read_space() >= disk_io_chunk_frames;
}
- state_lock.unlock();
+ if (commit_should_unlock) {
+ state_lock.unlock();
+ }
+
_processed = false;
return need_butler;
diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc
index 1d10109aa1..84ccef905c 100644
--- a/libs/ardour/audiofilesource.cc
+++ b/libs/ardour/audiofilesource.cc
@@ -29,11 +29,13 @@
#include <pbd/pathscanner.h>
#include <pbd/stl_delete.h>
#include <pbd/strsplit.h>
+#include <pbd/shortpath.h>
#include <pbd/enumwriter.h>
#include <sndfile.h>
#include <glibmm/miscutils.h>
+#include <glibmm/fileutils.h>
#include <ardour/audiofilesource.h>
#include <ardour/sndfile_helpers.h>
@@ -91,15 +93,17 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFo
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
- /* _channel is set in set_state() */
+ /* _channel is set in set_state() or init() */
{
/* constructor used for existing internal-to-session files. file must exist */
if (set_state (node)) {
throw failed_constructor ();
}
+
+ string foo = _name;
- if (init (_name, must_exist)) {
+ if (init (foo, must_exist)) {
throw failed_constructor ();
}
}
@@ -134,7 +138,7 @@ AudioFileSource::init (ustring pathstr, bool must_exist)
_peaks_built = false;
file_is_new = false;
- if (!find (pathstr, must_exist, is_new)) {
+ if (!find (pathstr, must_exist, is_new, _channel)) {
throw non_existent_source ();
}
@@ -244,7 +248,10 @@ AudioFileSource::set_state (const XMLNode& node)
void
AudioFileSource::mark_for_remove ()
{
- if (!writable()) {
+ // This operation is not allowed for sources for destructive tracks or embedded files.
+ // Fortunately mark_for_remove() is never called for embedded files. This function
+ // must be fixed if that ever happens.
+ if (_flags & Destructive) {
return;
}
@@ -359,19 +366,13 @@ AudioFileSource::move_to_trash (const ustring& trash_dir_name)
}
bool
-AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew)
+AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t& chan)
{
ustring::size_type pos;
bool ret = false;
isnew = false;
- /* clean up PATH:CHANNEL notation so that we are looking for the correct path */
-
- if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
- pathstr = pathstr.substr (0, pos);
- }
-
if (pathstr[0] != '/') {
/* non-absolute pathname: find pathstr in search path */
@@ -396,12 +397,60 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew)
if (fullpath[fullpath.length()-1] != '/') {
fullpath += '/';
}
+
fullpath += pathstr;
+
+ /* i (paul) made a nasty design error by using ':' as a special character in
+ Ardour 0.99 .. this hack tries to make things sort of work.
+ */
- if (access (fullpath.c_str(), R_OK) == 0) {
- keeppath = fullpath;
- ++cnt;
- }
+ if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
+
+ if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+
+ /* its a real file, no problem */
+
+ keeppath = fullpath;
+ ++cnt;
+
+ } else {
+
+ if (must_exist) {
+
+ /* might be an older session using file:channel syntax. see if the version
+ without the :suffix exists
+ */
+
+ ustring shorter = pathstr.substr (0, pos);
+ fullpath = *i;
+
+ if (fullpath[fullpath.length()-1] != '/') {
+ fullpath += '/';
+ }
+
+ fullpath += shorter;
+
+ if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ chan = atoi (pathstr.substr (pos+1));
+ pathstr = shorter;
+ keeppath = fullpath;
+ ++cnt;
+ }
+
+ } else {
+
+ /* new derived file (e.g. for timefx) being created in a newer session */
+
+ }
+ }
+
+ } else {
+
+ if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ keeppath = fullpath;
+ ++cnt;
+ }
+ }
}
if (cnt > 1) {
@@ -418,7 +467,7 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew)
isnew = true;
}
}
-
+
_name = pathstr;
_path = keeppath;
ret = true;
@@ -426,18 +475,31 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew)
} else {
/* external files and/or very very old style sessions include full paths */
+
+ /* ugh, handle ':' situation */
+
+ if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
+
+ 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));
+ pathstr = shorter;
+ }
+ }
_path = pathstr;
+
if (is_embedded()) {
_name = pathstr;
} else {
_name = pathstr.substr (pathstr.find_last_of ('/') + 1);
}
-
- if (access (_path.c_str(), R_OK) != 0) {
- /* file does not exist or we cannot read it */
+ if (!Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ /* file does not exist or we cannot read it */
+
if (must_exist) {
error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
goto out;
@@ -458,6 +520,7 @@ AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew)
/* already exists */
ret = true;
+
}
}
@@ -575,6 +638,9 @@ AudioFileSource::safe_file_extension(ustring file)
file.rfind(".maud")== ustring::npos &&
file.rfind(".vwe") == ustring::npos &&
file.rfind(".paf") == ustring::npos &&
+#ifdef HAVE_FLAC
+ file.rfind(".flac")== ustring::npos &&
+#endif // HAVE_FLAC
#ifdef HAVE_COREAUDIO
file.rfind(".mp3") == ustring::npos &&
file.rfind(".aac") == ustring::npos &&
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 8bb40e9bcb..68b77a1199 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -332,12 +332,12 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
nframes_t buf_offset;
nframes_t to_read;
- /* precondition: caller has verified that we cover the desired section */
-
- if (chan_n >= _sources.size()) {
+ if (muted()) {
return 0; /* read nothing */
}
-
+
+ /* precondition: caller has verified that we cover the desired section */
+
if (position < _position) {
internal_offset = 0;
buf_offset = _position - position;
@@ -362,18 +362,30 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
mixdown_buffer += buf_offset;
}
- if (muted()) {
- return 0; /* read nothing */
- }
-
_read_data_count = 0;
- boost::shared_ptr<AudioSource> src = audio_source(chan_n);
- if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
- return 0; /* "read nothing" */
- }
+ if (chan_n < n_channels()) {
+
+ boost::shared_ptr<AudioSource> src = audio_source(chan_n);
+ if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) {
+
+ return 0; /* "read nothing" */
+ }
+
+ _read_data_count += src->read_data_count();
- _read_data_count += src->read_data_count();
+ } else {
+
+ /* track is N-channel, this region has less channels; silence the ones
+ we don't have.
+ */
+
+ memset (mixdown_buffer, 0, sizeof (Sample) * cnt);
+
+ /* no fades required */
+
+ goto merge;
+ }
/* fade in */
@@ -384,7 +396,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
/* see if this read is within the fade in */
if (internal_offset < fade_in_length) {
-
+
nframes_t limit;
limit = min (to_read, fade_in_length - internal_offset);
@@ -458,13 +470,15 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude);
}
+ merge:
+
if (!opaque()) {
/* gack. the things we do for users.
*/
buf += buf_offset;
-
+
for (nframes_t n = 0; n < to_read; ++n) {
buf[n] += mixdown_buffer[n];
}
@@ -827,6 +841,18 @@ AudioRegion::set_fade_out_active (bool yn)
send_change (FadeOutActiveChanged);
}
+bool
+AudioRegion::fade_in_is_default () const
+{
+ return _fade_in_shape == Linear && _fade_in.back()->when == 64;
+}
+
+bool
+AudioRegion::fade_out_is_default () const
+{
+ return _fade_out_shape == Linear && _fade_out.back()->when == 64;
+}
+
void
AudioRegion::set_default_fade_in ()
{
@@ -938,7 +964,6 @@ AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<Aud
boost::shared_ptr<Region> r = RegionFactory::create (srcs, _start, _length, new_name, _layer, f);
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
- cerr << "new region name is " << ar->name() << endl;
v.push_back (ar);
@@ -1099,7 +1124,6 @@ AudioRegion::normalize_to (float target_dB)
boost::shared_ptr<Playlist> pl (playlist());
if (pl) {
- cerr << "Send modified\n";
pl->Modified();
}
@@ -1130,14 +1154,16 @@ void
AudioRegion::suspend_fade_in ()
{
if (++_fade_in_disabled == 1) {
- set_fade_in_active (false);
+ if (fade_in_is_default()) {
+ set_fade_in_active (false);
+ }
}
}
void
AudioRegion::resume_fade_in ()
{
- if (_fade_in_disabled && --_fade_in_disabled == 0) {
+ if (--_fade_in_disabled == 0 && _fade_in_disabled) {
set_fade_in_active (true);
}
}
@@ -1146,14 +1172,16 @@ void
AudioRegion::suspend_fade_out ()
{
if (++_fade_out_disabled == 1) {
- set_fade_out_active (false);
+ if (fade_out_is_default()) {
+ set_fade_out_active (false);
+ }
}
}
void
AudioRegion::resume_fade_out ()
{
- if (_fade_out_disabled && --_fade_out_disabled == 0) {
+ if (--_fade_out_disabled == 0 &&_fade_out_disabled) {
set_fade_out_active (true);
}
}
@@ -1185,7 +1213,7 @@ AudioRegion::source_offset_changed ()
boost::shared_ptr<AudioSource>
AudioRegion::audio_source (uint32_t n) const
{
- // Guaranteed to succeed (use a static cast?)
+ // Guaranteed to succeed (use a static cast for speed?)
return boost::dynamic_pointer_cast<AudioSource>(source(n));
}
diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc
index 572fd9ef81..703225e502 100644
--- a/libs/ardour/coreaudiosource.cc
+++ b/libs/ardour/coreaudiosource.cc
@@ -38,9 +38,10 @@ CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
}
CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag flags)
- : AudioFileSource(s, path, flags),
+ /* files created this way are never writable or removable */
+ : AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{
- channel = chn;
+ _channel = chn;
init ();
}
@@ -60,8 +61,8 @@ CoreAudioSource::init ()
n_channels = file_asbd.NumberChannels();
cerr << "number of channels: " << n_channels << endl;
- if (channel >= n_channels) {
- error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, channel, name()) << endmsg;
+ if (_channel >= n_channels) {
+ error << string_compose("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number (%3)", n_channels, _channel, name()) << endmsg;
throw failed_constructor();
}
@@ -132,14 +133,14 @@ CoreAudioSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) con
abl.mBuffers[0].mDataByteSize = tmpbufsize * sizeof(Sample);
abl.mBuffers[0].mData = tmpbuf;
- cerr << "channel: " << channel << endl;
+ cerr << "channel: " << _channel << endl;
try {
af.Read (real_cnt, &abl);
} catch (CAXException& cax) {
error << string_compose("CoreAudioSource: %1 (%2)", cax.mOperation, _name);
}
- float *ptr = tmpbuf + channel;
+ float *ptr = tmpbuf + _channel;
real_cnt /= n_channels;
/* stride through the interleaved data */
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index c8fd2e48bf..18aeb32931 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -114,6 +114,7 @@ Diskstream::init (Flag f)
playback_distance = 0;
_read_data_count = 0;
_write_data_count = 0;
+ commit_should_unlock = false;
pending_overwrite = false;
overwrite_frame = 0;
@@ -212,7 +213,9 @@ Diskstream::prepare ()
void
Diskstream::recover ()
{
- state_lock.unlock();
+ if (commit_should_unlock) {
+ state_lock.unlock();
+ }
_processed = false;
}
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index f5e841f00f..a310bd598f 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -41,6 +41,7 @@
#include <ardour/ardour.h>
#include <ardour/audio_library.h>
#include <ardour/configuration.h>
+#include <ardour/profile.h>
#include <ardour/plugin_manager.h>
#include <ardour/audiosource.h>
#include <ardour/utils.h>
@@ -61,6 +62,7 @@
#include "i18n.h"
ARDOUR::Configuration* ARDOUR::Config = 0;
+ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
ARDOUR::AudioLibrary* ARDOUR::Library = 0;
#ifdef HAVE_LIBLO
@@ -296,10 +298,12 @@ ARDOUR::init (ARDOUR::AudioEngine& engine, bool use_vst, bool try_optimization)
Config->set_use_vst (use_vst);
+ Profile = new RuntimeProfile;
+
if (setup_midi (engine)) {
return -1;
}
-
+
#ifdef HAVE_LIBLO
if (setup_osc ()) {
return -1;
diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc
index e5d77c3951..956f693f13 100644
--- a/libs/ardour/insert.cc
+++ b/libs/ardour/insert.cc
@@ -493,9 +493,11 @@ PluginInsert::protect_automation ()
switch (al.automation_state()) {
case Write:
- case Touch:
al.set_automation_state (Off);
break;
+ case Touch:
+ al.set_automation_state (Play);
+ break;
default:
break;
}
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index ba944f3c08..082d673fbc 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -195,6 +195,7 @@ LadspaPlugin::default_value (uint32_t port)
float ret = 0.0f;
bool bounds_given = false;
bool sr_scaling = false;
+ bool earlier_hint = false;
/* defaults - case 1 */
@@ -203,6 +204,7 @@ LadspaPlugin::default_value (uint32_t port)
ret = prh[port].LowerBound;
bounds_given = true;
sr_scaling = true;
+ earlier_hint = true;
}
/* FIXME: add support for logarithmic defaults */
@@ -211,33 +213,41 @@ LadspaPlugin::default_value (uint32_t port)
ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f;
bounds_given = true;
sr_scaling = true;
+ earlier_hint = true;
}
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(prh[port].HintDescriptor)) {
ret = prh[port].LowerBound * 0.50f + prh[port].UpperBound * 0.50f;
bounds_given = true;
sr_scaling = true;
+ earlier_hint = true;
}
else if (LADSPA_IS_HINT_DEFAULT_HIGH(prh[port].HintDescriptor)) {
ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f;
bounds_given = true;
sr_scaling = true;
+ earlier_hint = true;
}
else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(prh[port].HintDescriptor)) {
ret = prh[port].UpperBound;
bounds_given = true;
sr_scaling = true;
+ earlier_hint = true;
}
else if (LADSPA_IS_HINT_DEFAULT_0(prh[port].HintDescriptor)) {
ret = 0.0f;
+ earlier_hint = true;
}
else if (LADSPA_IS_HINT_DEFAULT_1(prh[port].HintDescriptor)) {
ret = 1.0f;
+ earlier_hint = true;
}
else if (LADSPA_IS_HINT_DEFAULT_100(prh[port].HintDescriptor)) {
ret = 100.0f;
+ earlier_hint = true;
}
else if (LADSPA_IS_HINT_DEFAULT_440(prh[port].HintDescriptor)) {
ret = 440.0f;
+ earlier_hint = true;
}
else {
/* no hint found */
@@ -290,7 +300,7 @@ LadspaPlugin::default_value (uint32_t port)
/* defaults - case 5 */
- if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor)) {
+ if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor) && !earlier_hint) {
if (bounds_given) {
if (sr_scaling) {
ret *= sample_rate;
diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc
index d7ce12d411..8fbccf17f7 100644
--- a/libs/ardour/midi_port.cc
+++ b/libs/ardour/midi_port.cc
@@ -61,7 +61,7 @@ MidiPort::cycle_start (jack_nframes_t nframes)
void* jack_buffer = jack_port_get_buffer(_port, nframes);
const jack_nframes_t event_count
- = jack_midi_get_event_count(jack_buffer, nframes);
+ = jack_midi_get_event_count(jack_buffer);
assert(event_count < _buffer.capacity());
@@ -71,7 +71,7 @@ MidiPort::cycle_start (jack_nframes_t nframes)
for (jack_nframes_t i=0; i < event_count; ++i) {
// This will fail to compile if we change MidiEvent to our own class
- jack_midi_event_get(static_cast<jack_midi_event_t*>(&ev), jack_buffer, i, nframes);
+ jack_midi_event_get(static_cast<jack_midi_event_t*>(&ev), jack_buffer, i);
_buffer.push_back(ev);
// Convert note ons with velocity 0 to proper note offs
@@ -103,11 +103,11 @@ MidiPort::cycle_end()
//if (event_count > 0)
// cerr << "MIDIPort writing " << event_count << " events." << endl;
- jack_midi_clear_buffer(jack_buffer, _nframes_this_cycle);
+ jack_midi_clear_buffer(jack_buffer);
for (jack_nframes_t i=0; i < event_count; ++i) {
const jack_midi_event_t& ev = _buffer[i];
assert(ev.time < _nframes_this_cycle);
- jack_midi_event_write(jack_buffer, ev.time, ev.buffer, ev.size, _nframes_this_cycle);
+ jack_midi_event_write(jack_buffer, ev.time, ev.buffer, ev.size);
}
_nframes_this_cycle = 0;
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 8e41e70687..e12857da93 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -666,10 +666,7 @@ Multi2dPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co
}
pan = left * gain_coeff;
-
- for (; n < nframes; ++n) {
- dst[n] += src[n] * pan;
- }
+ Session::mix_buffers_with_gain(dst+n,src+n,nframes-n,pan);
} else {
@@ -679,20 +676,10 @@ Multi2dPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co
if ((pan *= gain_coeff) != 1.0f) {
if (pan != 0.0f) {
-
- for (nframes_t n = 0; n < nframes; ++n) {
- dst[n] += src[n] * pan;
- }
-
+ Session::mix_buffers_with_gain(dst,src,nframes,pan);
}
-
-
} else {
-
- for (nframes_t n = 0; n < nframes; ++n) {
- dst[n] += src[n];
- }
-
+ Session::mix_buffers_no_gain(dst,src,nframes);
}
#endif
#ifdef CAN_INTERP
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 325ef27a18..0d743a5c9d 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -75,6 +75,7 @@ Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
, _type(type)
{
init (hide);
+ first_set_state = false;
_name = nom;
}
@@ -113,6 +114,7 @@ Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, boo
_edit_mode = other->_edit_mode;
in_set_state = 0;
+ first_set_state = false;
in_flush = false;
in_partition = false;
subcnt = 0;
@@ -185,6 +187,7 @@ Playlist::Playlist (boost::shared_ptr<const Playlist> other, nframes_t start, nf
}
in_set_state--;
+ first_set_state = false;
/* this constructor does NOT notify others (session) */
}
@@ -225,6 +228,7 @@ Playlist::init (bool hide)
g_atomic_int_set (&ignore_state_changes, 0);
pending_modified = false;
pending_length = false;
+ first_set_state = true;
_refcnt = 0;
_hidden = hide;
_splicing = false;
@@ -515,10 +519,10 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t posit
old_length = _get_maximum_extent();
}
- if (!in_set_state) {
+ if (!first_set_state) {
boost::shared_ptr<Playlist> foo (shared_from_this());
region->set_playlist (boost::weak_ptr<Playlist>(foo));
- }
+ }
region->set_position (position, this);
@@ -581,6 +585,11 @@ Playlist::remove_region_internal (boost::shared_ptr<Region>region)
old_length = _get_maximum_extent();
}
+ if (!in_set_state) {
+ /* unset playlist */
+ region->set_playlist (boost::weak_ptr<Playlist>());
+ }
+
for (i = regions.begin(); i != regions.end(); ++i) {
if (*i == region) {
@@ -1182,6 +1191,14 @@ Playlist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
}
void
+Playlist::drop_regions ()
+{
+ RegionLock rl (this);
+ regions.clear ();
+ all_regions.clear ();
+}
+
+void
Playlist::clear (bool with_signals)
{
{
@@ -1412,7 +1429,7 @@ Playlist::set_state (const XMLNode& node)
}
in_set_state--;
-
+ first_set_state = false;
return 0;
}
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 15609706b2..b972c20589 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -272,12 +272,15 @@ void
Region::set_playlist (boost::weak_ptr<Playlist> wpl)
{
boost::shared_ptr<Playlist> old_playlist = (_playlist.lock());
+
boost::shared_ptr<Playlist> pl (wpl.lock());
if (old_playlist == pl) {
return;
}
+ _playlist = pl;
+
if (pl) {
if (old_playlist) {
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
@@ -292,7 +295,7 @@ Region::set_playlist (boost::weak_ptr<Playlist> wpl)
} else {
if (old_playlist) {
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
- (*i)->remove_playlist (_playlist);
+ (*i)->remove_playlist (old_playlist);
}
}
}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 43c233e4d7..d37ae725af 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -113,7 +113,8 @@ Route::init ()
Route::~Route ()
{
- clear_redirects (this);
+ clear_redirects (PreFader, this);
+ clear_redirects (PostFader, this);
for (OrderKeys::iterator i = order_keys.begin(); i != order_keys.end(); ++i) {
free ((void*)(i->first));
@@ -884,10 +885,13 @@ Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_strea
return 0;
}
+/** Remove redirects with a given placement.
+ * @param p Placement of redirects to remove.
+ */
void
-Route::clear_redirects (void *src)
+Route::clear_redirects (Placement p, void *src)
{
- ChanCount old_rmo = redirect_max_outs;
+ const ChanCount old_rmo = redirect_max_outs;
if (!_session.engine().connected()) {
return;
@@ -895,13 +899,22 @@ Route::clear_redirects (void *src)
{
Glib::RWLock::WriterLock lm (redirect_lock);
- RedirectList::iterator i;
- for (i = _redirects.begin(); i != _redirects.end(); ++i) {
- (*i)->drop_references ();
+ RedirectList new_list;
+
+ for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+ if ((*i)->placement() == p) {
+ /* it's the placement we want to get rid of */
+ (*i)->drop_references ();
+ } else {
+ /* it's a different placement, so keep it */
+ new_list.push_back (*i);
+ }
}
- _redirects.clear ();
+
+ _redirects = new_list;
}
+ /* FIXME: can't see how this test can ever fire */
if (redirect_max_outs != old_rmo) {
reset_panner ();
}
@@ -1269,8 +1282,12 @@ Route::all_redirects_flip ()
}
}
+/** Set all redirects with a given placement to a given active state.
+ * @param p Placement of redirects to change.
+ * @param state New active state for those redirects.
+ */
void
-Route::all_redirects_active (bool state)
+Route::all_redirects_active (Placement p, bool state)
{
Glib::RWLock::ReaderLock lm (redirect_lock);
@@ -1279,7 +1296,9 @@ Route::all_redirects_active (bool state)
}
for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
- (*i)->set_active (state, this);
+ if ((*i)->placement() == p) {
+ (*i)->set_active (state, this);
+ }
}
}
@@ -2263,8 +2282,9 @@ Route::protect_automation ()
{
switch (gain_automation_state()) {
case Write:
- case Touch:
set_gain_automation_state (Off);
+ case Touch:
+ set_gain_automation_state (Play);
break;
default:
break;
@@ -2272,9 +2292,11 @@ Route::protect_automation ()
switch (panner().automation_state ()) {
case Write:
- case Touch:
panner().set_automation_state (Off);
break;
+ case Touch:
+ panner().set_automation_state (Play);
+ break;
default:
break;
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 9d0b13fccd..d775e9c69b 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1909,7 +1909,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
- if (!(*i)->hidden()) {
+ if (!(*i)->hidden() && (*i)->name() != _("master")) {
bus_id++;
}
}
@@ -1926,15 +1926,13 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
while (how_many) {
do {
- ++bus_id;
-
snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, bus_id);
if (route_by_name (bus_name) == 0) {
break;
}
- } while (bus_id < (UINT_MAX-1));
+ } while (++bus_id < (UINT_MAX-1));
try {
shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc
index 16c8d9cffa..afb284b0f4 100644
--- a/libs/ardour/session_butler.cc
+++ b/libs/ardour/session_butler.cc
@@ -248,7 +248,7 @@ Session::butler_thread_work ()
gettimeofday (&begin, 0);
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader ();
-
+
for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
boost::shared_ptr<Diskstream> ds = *i;
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index 2a078565b5..7d20a05b45 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -451,24 +451,6 @@ Session::setup_midi_control ()
mtc_msg[10] = 0xf1;
mtc_msg[12] = 0xf1;
mtc_msg[14] = 0xf1;
-
- if (_mmc_port != 0) {
-
- Config->set_send_mmc (session_send_mmc);
-
- } else {
-
- mmc = 0;
- session_send_mmc = false;
- }
-
- if (_mtc_port != 0) {
-
- Config->set_send_mtc (session_send_mtc);
-
- } else {
- session_send_mtc = false;
- }
}
#if 0
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 9b8b7f1d24..f0c4a29aa9 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -222,6 +222,9 @@ Session::commit_diskstreams (nframes_t nframes, bool &needs_butler)
}
/* force all diskstreams not handled by a Route to call do their stuff.
+ Note: the diskstreams that were handled by a route will just return zero
+ from this call, because they know they were processed. So in fact, this
+ also runs commit() for every diskstream.
*/
if ((dret = (*i)->process (_transport_frame, nframes, 0, actively_recording(), get_rec_monitors_input())) == 0) {
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index aae5830b34..a588015eac 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -141,6 +141,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
insert_cnt = 0;
_transport_speed = 0;
_last_transport_speed = 0;
+ auto_play_legal = false;
transport_sub_state = 0;
_transport_frame = 0;
last_stop_frame = 0;
@@ -611,6 +612,48 @@ Session::remove_pending_capture_state ()
unlink (xml_path.c_str());
}
+/** Rename a state file.
+ * @param snapshot_name Snapshot name.
+ */
+void
+Session::rename_state (string old_name, string new_name)
+{
+ if (old_name == _current_snapshot_name || old_name == _name) {
+ /* refuse to rename the current snapshot or the "main" one */
+ return;
+ }
+
+ const string old_xml_path = _path + old_name + _statefile_suffix;
+ const string new_xml_path = _path + new_name + _statefile_suffix;
+
+ if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
+ error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
+ }
+}
+
+/** Remove a state file.
+ * @param snapshot_name Snapshot name.
+ */
+void
+Session::remove_state (string snapshot_name)
+{
+ if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
+ /* refuse to remove the current snapshot or the "main" one */
+ return;
+ }
+
+ const string xml_path = _path + snapshot_name + _statefile_suffix;
+
+ /* make a backup copy of the state file */
+ const string bak_path = xml_path + ".bak";
+ if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
+ copy_file (xml_path, bak_path);
+ }
+
+ /* and delete it */
+ unlink (xml_path.c_str());
+}
+
int
Session::save_state (string snapshot_name, bool pending)
{
@@ -636,10 +679,12 @@ Session::save_state (string snapshot_name, bool pending)
if (!pending) {
+ /* proper save: use _statefile_suffix (.ardour in English) */
xml_path = _path;
xml_path += snapshot_name;
xml_path += _statefile_suffix;
+ /* make a backup copy of the old file */
bak_path = xml_path;
bak_path += ".bak";
@@ -649,6 +694,7 @@ Session::save_state (string snapshot_name, bool pending)
} else {
+ /* pending save: use _pending_suffix (.pending in English) */
xml_path = _path;
xml_path += snapshot_name;
xml_path += _pending_suffix;
@@ -2751,6 +2797,9 @@ Session::cleanup_sources (Session::cleanup_report& rep)
}
}
+ char tmppath1[PATH_MAX+1];
+ char tmppath2[PATH_MAX+1];
+
for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
used = false;
@@ -2758,7 +2807,10 @@ Session::cleanup_sources (Session::cleanup_report& rep)
for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
- if (spath == *i) {
+ realpath(spath.c_str(), tmppath1);
+ realpath((*i).c_str(), tmppath2);
+
+ if (strcmp(tmppath1, tmppath2) == 0) {
used = true;
break;
}
@@ -3284,6 +3336,8 @@ Session::config_changed (const char* parameter_name)
/* mark us ready to send */
next_quarter_frame_to_send = 0;
}
+ } else {
+ session_send_mtc = false;
}
} else if (PARAM_IS ("send-mmc")) {
@@ -3294,6 +3348,9 @@ Session::config_changed (const char* parameter_name)
if (_mmc_port != 0) {
session_send_mmc = Config->get_send_mmc();
+ } else {
+ mmc = 0;
+ session_send_mmc = false;
}
} else if (PARAM_IS ("midi-feedback")) {
diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc
index 836958f667..281c3a3315 100644
--- a/libs/ardour/session_time.cc
+++ b/libs/ardour/session_time.cc
@@ -25,6 +25,7 @@
#include <ardour/timestamps.h>
#include <pbd/error.h>
+#include <pbd/enumwriter.h>
#include <pbd/stacktrace.h>
#include <ardour/ardour.h>
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 3ee74231e0..d9150d235a 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -646,7 +646,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
}
}
- if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) {
+ if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
realtime_stop (false);
}
@@ -936,7 +936,7 @@ Session::post_transport ()
if (post_transport_work & PostTransportLocate) {
- if (((Config->get_slave_source() == None && Config->get_auto_play()) && !_exporting) || (post_transport_work & PostTransportRoll)) {
+ if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
start_transport ();
} else {
@@ -1261,3 +1261,9 @@ Session::update_latency_compensation_proxy (void* ignored)
{
update_latency_compensation (false, false);
}
+
+void
+Session::allow_auto_play (bool yn)
+{
+ auto_play_legal = yn;
+}
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index d11afa736b..8f795db111 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -894,3 +894,9 @@ SndFileSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& e
ret |= (uint32_t) binfo->time_reference_low;
return ret;
}
+
+bool
+SndFileSource::one_of_several_channels () const
+{
+ return _info.channels > 1;
+}
diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc
index c4cf1156cd..86afe4cb8d 100644
--- a/libs/ardour/source.cc
+++ b/libs/ardour/source.cc
@@ -132,7 +132,17 @@ Source::update_length (jack_nframes_t pos, jack_nframes_t cnt)
void
Source::add_playlist (boost::shared_ptr<Playlist> pl)
{
- _playlists.insert (pl);
+ std::pair<PlaylistMap::iterator,bool> res;
+ std::pair<boost::shared_ptr<Playlist>, uint32_t> newpair (pl, 1);
+ Glib::Mutex::Lock lm (playlist_lock);
+
+ res = _playlists.insert (newpair);
+
+ if (!res.second) {
+ /* it already existed, bump count */
+ res.first->second++;
+ }
+
pl->GoingAway.connect (bind (mem_fun (*this, &Source::remove_playlist), boost::weak_ptr<Playlist> (pl)));
}
@@ -145,10 +155,15 @@ Source::remove_playlist (boost::weak_ptr<Playlist> wpl)
return;
}
- std::set<boost::shared_ptr<Playlist> >::iterator x;
+ PlaylistMap::iterator x;
+ Glib::Mutex::Lock lm (playlist_lock);
if ((x = _playlists.find (pl)) != _playlists.end()) {
- _playlists.erase (x);
+ if (x->second > 1) {
+ x->second--;
+ } else {
+ _playlists.erase (x);
+ }
}
}
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index ed78b0942d..afba6b5cfb 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -172,9 +172,8 @@ VSTPlugin::get_state()
} else {
- error << string_compose (_("cannot check VST chunk directory: %1"),
- strerror (errno))
- << endmsg;
+ warning << string_compose (_("cannot check VST chunk directory: %1"), strerror (errno))
+ << endmsg;
return *root;
}