diff options
author | David Robillard <d@drobilla.net> | 2007-04-12 23:20:37 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-04-12 23:20:37 +0000 |
commit | 959a7909c1adca430a63f783fd16687242a7be3d (patch) | |
tree | b5048c3cc1bbb60bb680472b97ebba6ebb92d72f /libs/ardour | |
parent | 96ca08b9257e4048294cd1804a65d4ae6cd88814 (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')
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; } |