diff options
author | David Robillard <d@drobilla.net> | 2008-02-16 22:55:47 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-02-16 22:55:47 +0000 |
commit | 859e9106e72a7908fa093d946111d148223225a0 (patch) | |
tree | ec47825b5f5746bcbc5d321d40da7fc798f5c380 /libs/ardour | |
parent | 8aa9508c82f32efcf9c7c00e2c9e76268d4dddce (diff) |
Merge with 2.0-ongoing R3071.
git-svn-id: svn://localhost/ardour2/branches/3.0@3074 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
35 files changed, 599 insertions, 174 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 529a778942..7521bd728a 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -20,6 +20,9 @@ ardour.Append(CXXFLAGS=["-DLIBSIGC_DISABLE_DEPRECATED", "-DGLIBMM_EXCEPTIONS_ENA ardour.Append(PACKAGE = domain) ardour.Append(POTFILE = domain + '.pot') +if ardour['IS_OSX']: + ardour.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048") + # # explicitly reference the control protocol LGPL library for includes # @@ -312,7 +315,7 @@ ardour.Merge ([ libraries['sndfile-ardour'], libraries['vamp'], libraries['vamphost'], - libraries['xml'], + libraries['xml'] ]) if ardour['RUBBERBAND']: @@ -380,5 +383,10 @@ env.Alias('tarball', env.Distribute (env['DISTTREE'], [ 'SConscript', 'i18n.h', 'gettext.h' ] + [ 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] + [ 'rb_effect.cc', 'st_stretch.cc', 'st_pitch.cc' ] + - ardour_files + osc_files + vst_files + coreaudio_files + audiounit_files + + ardour_files + + osc_files + + vst_files + + coreaudio_files + + audiounit_files + + lv2_files + glob.glob('po/*.po') + glob.glob('ardour/*.h'))) diff --git a/libs/ardour/analyser.cc b/libs/ardour/analyser.cc index 7ddb5428e9..2e14c74b86 100644 --- a/libs/ardour/analyser.cc +++ b/libs/ardour/analyser.cc @@ -95,7 +95,7 @@ Analyser::work () boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src); - if (afs) { + if (afs && afs->length()) { analyse_audio_file_source (afs); } } diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h index fcec83394f..6f653f10bf 100644 --- a/libs/ardour/ardour/ardour.h +++ b/libs/ardour/ardour/ardour.h @@ -20,8 +20,10 @@ #ifndef __ardour_ardour_h__ #define __ardour_ardour_h__ -#include <limits.h> +#include <map> #include <string> + +#include <limits.h> #include <signal.h> #include <pbd/error.h> @@ -43,12 +45,15 @@ namespace ARDOUR { extern OSC* osc; static const nframes_t max_frames = JACK_MAX_FRAMES; + extern sigc::signal<void,std::string> BootMessage; int init (bool with_vst, bool try_optimization); int cleanup (); std::string get_ardour_revision (); + void find_bindings_files (std::map<std::string,std::string>&); + const layer_t max_layer = UCHAR_MAX; microseconds_t get_microseconds (); diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index c781e8200d..bdeac0477b 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -32,6 +32,7 @@ #include <ardour/plugin.h> #include <AudioUnit/AudioUnit.h> +#include <appleutility/AUParamInfo.h> #include <boost/shared_ptr.hpp> @@ -45,6 +46,16 @@ namespace ARDOUR { class AudioEngine; class Session; +struct AUParameterDescriptor : public Plugin::ParameterDescriptor { + // additional fields to make operations more efficient + AudioUnitParameterID id; + AudioUnitScope scope; + AudioUnitElement element; + float default_value; + bool automatable; + AudioUnitParameterUnit unit; +}; + class AUPlugin : public ARDOUR::Plugin { public: @@ -105,7 +116,7 @@ class AUPlugin : public ARDOUR::Plugin private: boost::shared_ptr<CAComponent> comp; boost::shared_ptr<CAAudioUnit> unit; - + AudioStreamBasicDescription streamFormat; bool initialized; int format_set; @@ -119,6 +130,7 @@ class AUPlugin : public ARDOUR::Plugin int set_input_format (); int set_stream_format (int scope, uint32_t cnt); int _set_block_size (nframes_t nframes); + void discover_parameters (); std::vector<std::pair<uint32_t, uint32_t> > parameter_map; uint32_t current_maxbuf; @@ -126,6 +138,8 @@ class AUPlugin : public ARDOUR::Plugin nframes_t cb_offset; vector<Sample*>* current_buffers; nframes_t frames_processed; + + std::vector<AUParameterDescriptor> descriptors; }; typedef boost::shared_ptr<AUPlugin> AUPluginPtr; diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h index 1589841baa..d11b829694 100644 --- a/libs/ardour/ardour/audiosource.h +++ b/libs/ardour/ardour/audiosource.h @@ -116,7 +116,6 @@ class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR: static bool _build_peakfiles; bool _peaks_built; - bool _analysed; mutable Glib::Mutex _lock; mutable Glib::Mutex _peaks_ready_lock; Glib::ustring peakpath; diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h index f96ecc0bd1..a2c1d98ae7 100644 --- a/libs/ardour/ardour/automatable.h +++ b/libs/ardour/ardour/automatable.h @@ -57,7 +57,10 @@ public: virtual void add_control(boost::shared_ptr<AutomationControl>); - virtual void automation_snapshot(nframes_t now); + virtual void automation_snapshot(nframes_t now, bool force); + bool should_snapshot (nframes_t now) { + return (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval); + } virtual void transport_stopped(nframes_t now); virtual bool find_next_event(nframes_t start, nframes_t end, ControlEvent& ev) const; diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 134557daeb..015c617425 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -105,6 +105,7 @@ CONFIG_VARIABLE (bool, punch_out, "punch-out", false) CONFIG_VARIABLE (bool, plugins_stop_with_transport, "plugins-stop-with-transport", false) CONFIG_VARIABLE (bool, do_not_record_plugins, "do-not-record-plugins", false) CONFIG_VARIABLE (bool, stop_recording_on_xrun, "stop-recording-on-xrun", false) +CONFIG_VARIABLE (bool, create_xrun_marker, "create-xrun-marker", true) CONFIG_VARIABLE (bool, stop_at_session_end, "stop-at-session-end", true) CONFIG_VARIABLE (bool, seamless_loop, "seamless-loop", false) CONFIG_VARIABLE (nframes_t, preroll, "preroll", 0) diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 0b82844f61..83b6378dae 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -251,8 +251,8 @@ class IO : public Automatable, public Latent void set_parameter_automation_state (Parameter, AutoState); - virtual void transport_stopped (nframes_t now); // interface: matches Insert - void automation_snapshot (nframes_t now); // interface: matches Automatable + virtual void transport_stopped (nframes_t now); + virtual void automation_snapshot (nframes_t now, bool force); void start_pan_touch (uint32_t which); void end_pan_touch (uint32_t which); diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h index 409ad91b15..a535ce3bb4 100644 --- a/libs/ardour/ardour/io_processor.h +++ b/libs/ardour/ardour/io_processor.h @@ -65,7 +65,7 @@ class IOProcessor : public Processor boost::shared_ptr<IO> io() { return _io; } boost::shared_ptr<const IO> io() const { return _io; } - virtual void automation_snapshot (nframes_t now) { _io->automation_snapshot(now); } + virtual void automation_snapshot (nframes_t now, bool force) { _io->automation_snapshot(now, force); } virtual void run_in_place (BufferSet& in, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) = 0; diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index d8a38841f8..4640a8e32f 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -126,7 +126,6 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla sigc::signal<void> LengthChanged; static string bump_name (string old_name, Session&); - static string bump_name_once (string old_name); void freeze (); void thaw (); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 2466f37996..c7c0b77102 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -75,6 +75,8 @@ class Route : public IO Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO); virtual ~Route(); + static std::string ensure_track_or_route_name(std::string, Session &); + std::string comment() { return _comment; } void set_comment (std::string str, void *src); @@ -247,7 +249,7 @@ class Route : public IO return _mute_control; } - void automation_snapshot (nframes_t now); + void automation_snapshot (nframes_t now, bool force=false); void protect_automation (); void set_remote_control_id (uint32_t id); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index c0c178eb02..10167ae5b3 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -353,7 +353,7 @@ class Session : public PBD::StatefulDestructible sigc::signal<void> TransportStateChange; /* generic */ sigc::signal<void,nframes_t> PositionChanged; /* sent after any non-sequential motion */ sigc::signal<void> DurationChanged; - sigc::signal<void> HaltOnXrun; + sigc::signal<void,nframes_t> Xrun; sigc::signal<void> TransportLooped; sigc::signal<void,RouteList&> RouteAdded; @@ -563,8 +563,11 @@ class Session : public PBD::StatefulDestructible /* region info */ - sigc::signal<void,boost::shared_ptr<Region> > RegionAdded; - sigc::signal<void,boost::shared_ptr<Region> > RegionRemoved; + void add_regions (std::vector<boost::shared_ptr<Region> >&); + + sigc::signal<void,boost::weak_ptr<Region> > RegionAdded; + sigc::signal<void,std::vector<boost::weak_ptr<Region> >& > RegionsAdded; + sigc::signal<void,boost::weak_ptr<Region> > RegionRemoved; int region_name (string& result, string base = string(""), bool newlevel = false) const; string new_region_name (string); @@ -586,10 +589,10 @@ class Session : public PBD::StatefulDestructible string doing_what; /* control info */ - bool sample_convert; SrcQuality quality; volatile bool freeze; std::vector<Glib::ustring> paths; + bool replace_existing_source; /* result */ SourceList sources; @@ -1480,6 +1483,12 @@ class Session : public PBD::StatefulDestructible SourceMap sources; + public: + SourceMap get_sources() { return sources; } + + private: + + int load_sources (const XMLNode& node); XMLNode& get_sources_as_xml (); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index fdf8d0b439..efc2e35ecc 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -257,7 +257,8 @@ namespace ARDOUR { enum EditMode { Slide, - Splice + Splice, + Lock }; enum RegionPoint { diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h index e52274eb1f..eecde2e85f 100644 --- a/libs/ardour/ardour/utils.h +++ b/libs/ardour/ardour/utils.h @@ -45,6 +45,8 @@ static inline float f_max(float x, float a) { return (x); } +std::string bump_name_once(std::string s); + int cmp_nocase (const std::string& s, const std::string& s2); int touch_file(Glib::ustring path); diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index bc2f0d9feb..7d55cc343a 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -519,7 +519,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, if (lm.locked()) { // automation snapshot can also be called from the non-rt context // and it uses the redirect list, so we take the lock out here - automation_snapshot (start_frame); + automation_snapshot (start_frame, false); } } diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 387c7f1238..9132957743 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -32,6 +32,7 @@ #include <ardour/utils.h> #include <appleutility/CAAudioUnit.h> +#include <appleutility/CAAUParameter.h> #include <CoreServices/CoreServices.h> #include <AudioUnit/AudioUnit.h> @@ -83,6 +84,7 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAC throw failed_constructor(); } + unit->GetElementCount (kAudioUnitScope_Global, global_elements); unit->GetElementCount (kAudioUnitScope_Input, input_elements); unit->GetElementCount (kAudioUnitScope_Output, output_elements); @@ -106,6 +108,10 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAC error << _("AUPlugin: cannot set processing block size") << endmsg; throw failed_constructor(); } + + discover_parameters (); + + Plugin::setup_controls (); } AUPlugin::~AUPlugin () @@ -119,6 +125,124 @@ AUPlugin::~AUPlugin () } } +void +AUPlugin::discover_parameters () +{ + /* discover writable parameters */ + + cerr << "get param info, there are " << global_elements << " global elements\n"; + + AudioUnitScope scopes[] = { + kAudioUnitScope_Global, + kAudioUnitScope_Output, + kAudioUnitScope_Input + }; + + descriptors.clear (); + + for (uint32_t i = 0; i < sizeof (scopes) / sizeof (scopes[0]); ++i) { + + AUParamInfo param_info (unit->AU(), false, false, scopes[i]); + + cerr << "discovered " << param_info.NumParams() << " parameters in scope " << i << endl; + + for (uint32_t i = 0; i < param_info.NumParams(); ++i) { + + AUParameterDescriptor d; + + d.id = param_info.ParamID (i); + + const CAAUParameter* param = param_info.GetParamInfo (d.id); + const AudioUnitParameterInfo& info (param->ParamInfo()); + + const int len = CFStringGetLength (param->GetName());; + char local_buffer[len*2]; + Boolean good = CFStringGetCString(param->GetName(),local_buffer,len*2,kCFStringEncodingMacRoman); + if (!good) { + d.label = "???"; + } else { + d.label = local_buffer; + } + + d.scope = param_info.GetScope (); + d.element = param_info.GetElement (); + + /* info.units to consider */ + /* + kAudioUnitParameterUnit_Generic = 0 + kAudioUnitParameterUnit_Indexed = 1 + kAudioUnitParameterUnit_Boolean = 2 + kAudioUnitParameterUnit_Percent = 3 + kAudioUnitParameterUnit_Seconds = 4 + kAudioUnitParameterUnit_SampleFrames = 5 + kAudioUnitParameterUnit_Phase = 6 + kAudioUnitParameterUnit_Rate = 7 + kAudioUnitParameterUnit_Hertz = 8 + kAudioUnitParameterUnit_Cents = 9 + kAudioUnitParameterUnit_RelativeSemiTones = 10 + kAudioUnitParameterUnit_MIDINoteNumber = 11 + kAudioUnitParameterUnit_MIDIController = 12 + kAudioUnitParameterUnit_Decibels = 13 + kAudioUnitParameterUnit_LinearGain = 14 + kAudioUnitParameterUnit_Degrees = 15 + kAudioUnitParameterUnit_EqualPowerCrossfade = 16 + kAudioUnitParameterUnit_MixerFaderCurve1 = 17 + kAudioUnitParameterUnit_Pan = 18 + kAudioUnitParameterUnit_Meters = 19 + kAudioUnitParameterUnit_AbsoluteCents = 20 + kAudioUnitParameterUnit_Octaves = 21 + kAudioUnitParameterUnit_BPM = 22 + kAudioUnitParameterUnit_Beats = 23 + kAudioUnitParameterUnit_Milliseconds = 24 + kAudioUnitParameterUnit_Ratio = 25 + */ + + /* info.flags to consider */ + + /* + + kAudioUnitParameterFlag_CFNameRelease = (1L << 4) + kAudioUnitParameterFlag_HasClump = (1L << 20) + kAudioUnitParameterFlag_HasName = (1L << 21) + kAudioUnitParameterFlag_DisplayLogarithmic = (1L << 22) + kAudioUnitParameterFlag_IsHighResolution = (1L << 23) + kAudioUnitParameterFlag_NonRealTime = (1L << 24) + kAudioUnitParameterFlag_CanRamp = (1L << 25) + kAudioUnitParameterFlag_ExpertMode = (1L << 26) + kAudioUnitParameterFlag_HasCFNameString = (1L << 27) + kAudioUnitParameterFlag_IsGlobalMeta = (1L << 28) + kAudioUnitParameterFlag_IsElementMeta = (1L << 29) + kAudioUnitParameterFlag_IsReadable = (1L << 30) + kAudioUnitParameterFlag_IsWritable = (1L << 31) + */ + + d.lower = info.minValue; + d.upper = info.maxValue; + d.default_value = info.defaultValue; + + d.integer_step = (info.unit & kAudioUnitParameterUnit_Indexed); + d.toggled = (info.unit & kAudioUnitParameterUnit_Boolean) || + (d.integer_step && ((d.upper - d.lower) == 1.0)); + d.sr_dependent = (info.unit & kAudioUnitParameterUnit_SampleFrames); + d.automatable = !d.toggled && + !(info.flags & kAudioUnitParameterFlag_NonRealTime) && + (info.flags & kAudioUnitParameterFlag_IsWritable); + + d.logarithmic = (info.flags & kAudioUnitParameterFlag_DisplayLogarithmic); + d.unit = info.unit; + + d.step = 1.0; + d.smallstep = 0.1; + d.largestep = 10.0; + d.min_unbound = 0; // lower is bound + d.max_unbound = 0; // upper is bound + + descriptors.push_back (d); + } + } +} + + string AUPlugin::unique_id () const { @@ -134,13 +258,16 @@ AUPlugin::label () const uint32_t AUPlugin::parameter_count () const { - return 0; + return descriptors.size(); } float AUPlugin::default_value (uint32_t port) { - // AudioUnits don't have default values. Maybe presets though? + if (port < descriptors.size()) { + return descriptors[port].default_value; + } + return 0; } @@ -157,28 +284,41 @@ AUPlugin::signal_latency () const void AUPlugin::set_parameter (uint32_t which, float val) { - // unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val); + if (which < descriptors.size()) { + const AUParameterDescriptor& d (descriptors[which]); + unit->SetParameter (d.id, d.scope, d.element, val); + } } float AUPlugin::get_parameter (uint32_t which) const { - float outValue = 0.0; - - // unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue); - - return outValue; + float val = 0.0; + if (which < descriptors.size()) { + const AUParameterDescriptor& d (descriptors[which]); + unit->GetParameter(d.id, d.scope, d.element, val); + } + return val; } int -AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const +AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& pd) const { - return 0; + if (which < descriptors.size()) { + pd = descriptors[which]; + return 0; + } + return -1; } uint32_t AUPlugin::nth_parameter (uint32_t which, bool& ok) const { + if (which < descriptors.size()) { + ok = true; + return which; + } + ok = false; return 0; } @@ -397,20 +537,26 @@ set<uint32_t> AUPlugin::automatable() const { set<uint32_t> automates; - + + for (uint32_t i = 0; i < descriptors.size(); ++i) { + if (descriptors[i].automatable) { + automates.insert (i); + } + } + return automates; } string -AUPlugin::describe_parameter (uint32_t) +AUPlugin::describe_parameter (uint32_t param) { - return ""; + return descriptors[param].label; } void -AUPlugin::print_parameter (uint32_t, char*, uint32_t len) const +AUPlugin::print_parameter (uint32_t param, char* buf, uint32_t len) const { - + // NameValue stuff here } bool @@ -422,7 +568,7 @@ AUPlugin::parameter_is_audio (uint32_t) const bool AUPlugin::parameter_is_control (uint32_t) const { - return false; + return true; } bool diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index da4f8a642c..8d2589db0e 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -126,6 +126,8 @@ AudioEngine::start () if (session) { nframes_t blocksize = jack_get_buffer_size (_jack); + BootMessage (_("Connect session to engine")); + session->set_block_size (blocksize); session->set_frame_rate (jack_get_sample_rate (_jack)); diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc index 81ad45e08a..00e0f925df 100644 --- a/libs/ardour/audiofilesource.cc +++ b/libs/ardour/audiofilesource.cc @@ -677,20 +677,18 @@ bool AudioFileSource::safe_file_extension(ustring file) { return !(file.rfind(".wav") == ustring::npos && - file.rfind(".aiff")== ustring::npos && - file.rfind(".aif") == ustring::npos && - file.rfind(".snd") == ustring::npos && - file.rfind(".au") == ustring::npos && - file.rfind(".raw") == ustring::npos && - file.rfind(".sf") == ustring::npos && - file.rfind(".cdr") == ustring::npos && - file.rfind(".smp") == ustring::npos && - file.rfind(".maud")== ustring::npos && - file.rfind(".vwe") == ustring::npos && - file.rfind(".paf") == ustring::npos && - /* protools convention */ - file.rfind(".L") == ustring::npos && - file.rfind(".R") == ustring::npos && + file.rfind(".aiff")== ustring::npos && + file.rfind(".aif") == ustring::npos && + file.rfind(".amb") == ustring::npos && + file.rfind(".snd") == ustring::npos && + file.rfind(".au") == ustring::npos && + file.rfind(".raw") == ustring::npos && + file.rfind(".sf") == ustring::npos && + file.rfind(".cdr") == ustring::npos && + file.rfind(".smp") == ustring::npos && + 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 diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 20115ff944..7e2b709abd 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -1316,6 +1316,8 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new) return 0; } + cerr << "startup analysis of " << _name << endl; + TransientDetector t (pl->session().frame_rate()); bool existing_results = !results.empty(); @@ -1328,10 +1330,14 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new) t.reset (); + cerr << "working on channel " << i << endl; + if (t.run ("", this, i, these_results)) { return -1; } + cerr << "done\n"; + /* translate all transients to give absolute position */ for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) { @@ -1357,6 +1363,11 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new) /* make sure ours are clean too */ TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0); + + } else { + + TransientDetector::cleanup_transients (_transients, pl->session().frame_rate(), 3.0); + results = _transients; } _valid_transients = true; diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index cd71dd21e4..01dea08d3e 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -70,6 +70,7 @@ AudioSource::AudioSource (Session& s, ustring name) AudioSource::AudioSource (Session& s, const XMLNode& node) : Source (s, node) { + _peaks_built = false; _peak_byte_max = 0; peakfile = -1; @@ -213,7 +214,7 @@ AudioSource::initialize_peakfile (bool newfile, ustring audio_path) /* we found it in the peaks dir, so check it out */ - if (statbuf.st_size == 0) { + if (statbuf.st_size == 0 || (statbuf.st_size < ((length() / _FPP) * sizeof (PeakData)))) { // empty _peaks_built = false; } else { @@ -221,12 +222,22 @@ AudioSource::initialize_peakfile (bool newfile, ustring audio_path) struct stat stat_file; int err = stat (audio_path.c_str(), &stat_file); - if (!err && stat_file.st_mtime > statbuf.st_mtime){ + if (err) { _peaks_built = false; _peak_byte_max = 0; } else { - _peaks_built = true; - _peak_byte_max = statbuf.st_size; + + /* allow 6 seconds slop on checking peak vs. file times because of various + disk action "races" + */ + + if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) { + _peaks_built = false; + _peak_byte_max = 0; + } else { + _peaks_built = true; + _peak_byte_max = statbuf.st_size; + } } } } diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index 45b19d1997..8b8b843384 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -422,9 +422,9 @@ Automatable::protect_automation () } void -Automatable::automation_snapshot (nframes_t now) +Automatable::automation_snapshot (nframes_t now, bool force) { - if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) { + if (force || _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/filter.cc b/libs/ardour/filter.cc index dc8185db95..be382f72da 100644 --- a/libs/ardour/filter.cc +++ b/libs/ardour/filter.cc @@ -28,6 +28,7 @@ #include <ardour/filter.h> #include <ardour/region_factory.h> #include <ardour/source_factory.h> +#include <ardour/analyser.h> #include "i18n.h" @@ -101,6 +102,10 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi smfs->set_timeline_position (region->position()); smfs->flush_footer (); } + + /* now that there is data there, requeue the file for analysis */ + + Analyser::queue_source_for_analysis (*si, false); } /* create a new region */ diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 6aba688cae..02c4a5ced6 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -19,9 +19,12 @@ #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain #include <sys/stat.h> #include <sys/types.h> +#include <sys/time.h> +#include <sys/resource.h> #include <unistd.h> #include <fcntl.h> #include <locale.h> +#include <errno.h> #ifdef VST_SUPPORT #include <fst.h> @@ -31,12 +34,16 @@ #include <xmmintrin.h> #endif +#include <glibmm/fileutils.h> +#include <glibmm/miscutils.h> + #include <lrdf.h> #include <pbd/error.h> #include <pbd/id.h> #include <pbd/strsplit.h> #include <pbd/fpu.h> +#include <pbd/file_utils.h> #include <midi++/port.h> #include <midi++/manager.h> @@ -54,6 +61,7 @@ #include <ardour/source_factory.h> #include <ardour/control_protocol_manager.h> #include <ardour/audioengine.h> +#include <ardour/filesystem_paths.h> #ifdef HAVE_LIBLO #include <ardour/osc.h> @@ -96,6 +104,8 @@ apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0; mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0; mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0; +sigc::signal<void,std::string> ARDOUR::BootMessage; + #ifdef HAVE_LIBLO static int setup_osc () @@ -107,6 +117,7 @@ setup_osc () osc = new OSC (Config->get_osc_port()); if (Config->get_use_osc ()) { + BootMessage (_("Starting OSC")); return osc->start (); } else { return 0; @@ -122,6 +133,8 @@ setup_midi () return 0; } + BootMessage (_("Configuring MIDI ports")); + for (std::map<string,XMLNode>::iterator i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) { MIDI::Manager::instance()->add_port (i->second); } @@ -253,6 +266,33 @@ setup_hardware_optimization (bool try_optimization) } } +static void +lotsa_files_please () +{ + struct rlimit rl; + + if (getrlimit (RLIMIT_NOFILE, &rl) == 0) { + + rl.rlim_cur = rl.rlim_max; + + if (setrlimit (RLIMIT_NOFILE, &rl) != 0) { + if (rl.rlim_cur == RLIM_INFINITY) { + error << _("Could not set system open files limit to \"unlimited\"") << endmsg; + } else { + error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg; + } + } else { + if (rl.rlim_cur == RLIM_INFINITY) { + info << _("Removed open file count limit. Excellent!") << endmsg; + } else { + info << string_compose (_("Ardour will be limited to %1 open files"), rl.rlim_cur) << endmsg; + } + } + } else { + error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg; + } +} + int ARDOUR::init (bool use_vst, bool try_optimization) { @@ -262,9 +302,14 @@ ARDOUR::init (bool use_vst, bool try_optimization) setup_enum_writer (); + // allow ardour the absolute maximum number of open files + lotsa_files_please (); + lrdf_init(); Library = new AudioLibrary; + BootMessage (_("Loading configuration")); + Config = new Configuration; if (Config->load_state ()) { @@ -367,6 +412,34 @@ ARDOUR::get_ardour_revision () return "$Rev$"; } +void +ARDOUR::find_bindings_files (map<string,string>& files) +{ + vector<sys::path> found; + + SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path(); + + if (getenv ("ARDOUR_SAE")) { + Glib::PatternSpec pattern("*SAE-*.bindings"); + find_matching_files_in_search_path (spath, pattern, found); + } else { + Glib::PatternSpec pattern("*.bindings"); + find_matching_files_in_search_path (spath, pattern, found); + } + + if (found.empty()) { + return; + } + + for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) { + sys::path path = *x; + pair<string,string> namepath; + namepath.second = path.to_string(); + namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.')); + files.insert (namepath); + } +} + ARDOUR::LocaleGuard::LocaleGuard (const char* str) { old = strdup (setlocale (LC_NUMERIC, NULL)); diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 91e5b9850c..2bc3a00a7a 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -46,6 +46,7 @@ #include <ardour/region_factory.h> #include <ardour/source_factory.h> #include <ardour/resampled_source.h> +#include <ardour/analyser.h> #include "i18n.h" @@ -65,7 +66,7 @@ open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQua } static std::string -get_non_existent_filename (const std::string& basename, uint channel, uint channels) +get_non_existent_filename (const bool allow_replacing, const std::string destdir, const std::string& basename, uint channel, uint channels) { char buf[PATH_MAX+1]; bool goodfile = false; @@ -84,7 +85,9 @@ get_non_existent_filename (const std::string& basename, uint channel, uint chann snprintf (buf, sizeof(buf), "%s.wav", base.c_str()); } - if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) { + + string tempname = destdir + "/" + buf; + if (!allow_replacing && Glib::file_test (tempname, 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 @@ -104,7 +107,7 @@ get_non_existent_filename (const std::string& basename, uint channel, uint chann } static vector<string> -get_paths_for_new_sources (const string& import_file_path, const string& session_dir, uint channels) +get_paths_for_new_sources (const bool allow_replacing, const string& import_file_path, const string& session_dir, uint channels) { vector<string> new_paths; const string basename = basename_nosuffix (import_file_path); @@ -115,7 +118,7 @@ get_paths_for_new_sources (const string& import_file_path, const string& session filepath = session_dir; filepath += '/'; - filepath += get_non_existent_filename (basename, n, channels); + filepath += get_non_existent_filename (allow_replacing, session_dir, basename, n, channels); new_paths.push_back (filepath); } @@ -124,6 +127,25 @@ get_paths_for_new_sources (const string& import_file_path, const string& session } static bool +map_existing_mono_sources (const vector<string>& new_paths, Session& sess, + uint samplerate, vector<boost::shared_ptr<AudioFileSource> >& newfiles, Session *session) +{ + for (vector<string>::const_iterator i = new_paths.begin(); + i != new_paths.end(); ++i) + { + boost::shared_ptr<Source> source = session->source_by_path_and_channel(*i, 0); + + if (source == 0) { + error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl; + return false; + } + + newfiles.push_back(boost::dynamic_pointer_cast<AudioFileSource>(source)); + } + return true; +} + +static bool create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess, uint samplerate, vector<boost::shared_ptr<AudioFileSource> >& newfiles) { @@ -228,6 +250,10 @@ remove_file_source (boost::shared_ptr<AudioFileSource> file_source) ::unlink (file_source->path().c_str()); } +// This function is still unable to cleanly update an existing source, even though +// it is possible to set the import_status flag accordingly. The functinality +// is disabled at the GUI until the Source implementations are able to provide +// the necessary API. void Session::import_audiofiles (import_status& status) { @@ -254,13 +280,19 @@ Session::import_audiofiles (import_status& status) return; } - vector<string> new_paths = get_paths_for_new_sources (*p, + vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, + *p, get_best_session_directory_for_new_source (), source->channels()); AudioSources newfiles; - status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles); + if (status.replace_existing_source) { + fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endl; + status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this); + } else { + status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles); + } // copy on cancel/failure so that any files that were created will be removed below std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources)); @@ -286,11 +318,14 @@ Session::import_audiofiles (import_status& status) /* flush the final length(s) to the header(s) */ - for (AudioSources::iterator x = all_new_sources.begin(); - x != all_new_sources.end(); ++x) + for (AudioSources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ++x) { (*x)->update_header(0, *now, xnow); (*x)->done_with_peakfile_writes (); + + /* now that there is data there, requeue the file for analysis */ + + Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false); } /* save state so that we don't lose these new Sources */ diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index babf1e451f..f57d5b39de 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -32,6 +32,7 @@ #include <ardour/audioengine.h> #include <ardour/io.h> +#include <ardour/route.h> #include <ardour/port.h> #include <ardour/audio_port.h> #include <ardour/midi_port.h> @@ -1800,14 +1801,22 @@ IO::parse_gain_string (const string& str, vector<string>& ports) } bool -IO::set_name (const string& str) +IO::set_name (const string& requested_name) { - if (str == _name) { + if (requested_name == _name) { return true; } + string name; + Route *rt; + if ( (rt = dynamic_cast<Route *>(this))) { + name = Route::ensure_track_or_route_name(requested_name, _session); + } else { + name = requested_name; + } + + /* replace all colons in the name. i wish we didn't have to do this */ - string name = str; if (replace_all (name, ":", "-")) { warning << _("you cannot use colons to name objects with I/O connections") << endmsg; @@ -2224,13 +2233,16 @@ IO::end_pan_touch (uint32_t which) } void -IO::automation_snapshot (nframes_t now) +IO::automation_snapshot (nframes_t now, bool force) { - Automatable::automation_snapshot (now); + Automatable::automation_snapshot (now, force); if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) { _panner->snapshot (now); } + + _panner->snapshot (now); + _last_automation_snapshot = now; } void diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index da3a812123..65279499ec 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -1814,50 +1814,12 @@ Playlist::bump_name (string name, Session &session) string newname = name; do { - newname = Playlist::bump_name_once (newname); + newname = bump_name_once (newname); } while (session.playlist_by_name (newname)!=NULL); return newname; } -string -Playlist::bump_name_once (string name) -{ - string::size_type period; - string newname; - - if ((period = name.find_last_of ('.')) == string::npos) { - newname = name; - newname += ".1"; - } else { - int isnumber = 1; - const char *last_element = name.c_str() + period + 1; - for (size_t i = 0; i < strlen(last_element); i++) { - if (!isdigit(last_element[i])) { - isnumber = 0; - break; - } - } - - errno = 0; - long int version = strtol (name.c_str()+period+1, (char **)NULL, 10); - - if (isnumber == 0 || errno != 0) { - // last_element is not a number, or is too large - newname = name; - newname += ".1"; - } else { - char buf[32]; - - snprintf (buf, sizeof(buf), "%ld", version+1); - - newname = name.substr (0, period+1); - newname += buf; - } - } - - return newname; -} layer_t Playlist::top_layer() const diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index 95629f2561..3d218448dd 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -224,6 +224,19 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type) return (*i)->load (session); } } + +#ifdef VST_SUPPORT + /* hmm, we didn't find it. could be because in older versions of Ardour. + we used to store the name of a VST plugin, not its unique ID. so try + again. + */ + + for (i = plugs.begin(); i != plugs.end(); ++i) { + if (identifier == (*i)->name){ + return (*i)->load (session); + } + } +#endif return PluginPtr ((Plugin*) 0); } diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 2193a69908..508f09a480 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -957,14 +957,14 @@ Region::adjust_to_sync (nframes_t pos) // cerr << "adjusting pos = " << pos << " to sync at " << _sync_position << " offset = " << offset << " with dir = " << sync_dir << endl; if (sync_dir > 0) { - if (max_frames - pos > offset) { + if (pos > offset) { pos -= offset; + } else { + pos = 0; } } else { - if (pos > offset) { + if (max_frames - pos > offset) { pos += offset; - } else { - pos = 0; } } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index fd0d99e87a..560946d9da 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -46,6 +46,9 @@ #include <ardour/amp.h> #include <ardour/meter.h> #include <ardour/buffer_set.h> +#include <ardour/mix.h> +#include <ardour/profile.h> + #include "i18n.h" using namespace std; @@ -190,6 +193,20 @@ Route::sync_order_keys () } } +string +Route::ensure_track_or_route_name(string name, Session &session) +{ + string newname = name; + + while (session.route_by_name (newname)!=NULL) + { + newname = bump_name_once (newname); + } + + return newname; +} + + void Route::inc_gain (gain_t fraction, void *src) { @@ -843,8 +860,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* reset_panner (); } - processors_changed (); /* EMIT SIGNAL */ + return 0; } @@ -2291,7 +2308,7 @@ Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_f Glib::RWLock::ReaderLock lm (_processor_lock); if (!did_locate) { - automation_snapshot (now); + automation_snapshot (now, true); } for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { @@ -2398,7 +2415,7 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nfra if (lm.locked()) { // automation snapshot can also be called from the non-rt context // and it uses the processor list, so we take the lock out here - automation_snapshot (_session.transport_frame()); + automation_snapshot (_session.transport_frame(), false); } } @@ -2569,12 +2586,15 @@ Route::set_latency_delay (nframes_t longest_session_latency) } void -Route::automation_snapshot (nframes_t now) +Route::automation_snapshot (nframes_t now, bool force) { - IO::automation_snapshot (now); + if (!force && !should_snapshot(now)) { + return; + } for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - (*i)->automation_snapshot (now); + // IO::automation_snapshot (now, force); ? + (*i)->automation_snapshot (now, force); } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 5a3144b828..4cfcda992e 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -504,9 +504,13 @@ Session::when_engine_running () /* we don't want to run execute this again */ + BootMessage (_("Set block size and sample rate")); + set_block_size (_engine.frames_per_cycle()); set_frame_rate (_engine.frame_rate()); + BootMessage (_("Using configuration")); + Config->map_parameters (mem_fun (*this, &Session::config_changed)); /* every time we reconnect, recompute worst case output latencies */ @@ -562,6 +566,8 @@ Session::when_engine_running () error << _("cannot setup Click I/O") << endmsg; } + BootMessage (_("Compute I/O Latencies")); + set_worst_io_latencies (); if (_clicking) { @@ -572,6 +578,8 @@ Session::when_engine_running () to the physical outputs currently available */ + BootMessage (_("Set up standard connections")); + /* ONE: MONO */ for (uint32_t np = 0; np < n_physical_outputs; ++np) { @@ -672,11 +680,15 @@ Session::when_engine_running () } add_bundle (c); } + + BootMessage (_("Connect ports")); hookup_io (); /* catch up on send+insert cnts */ + BootMessage (_("Catch up with send/insert state")); + insert_cnt = 0; for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) { @@ -704,14 +716,17 @@ Session::when_engine_running () _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty)); - /* hook us up to the engine */ + BootMessage (_("Connect to engine")); + _engine.set_session (this); #ifdef HAVE_LIBLO /* and to OSC */ + BootMessage (_("OSC startup")); + osc->set_session (*this); #endif @@ -2546,41 +2561,54 @@ Session::region_name (string& result, string base, bool newlevel) const void Session::add_region (boost::shared_ptr<Region> region) { + vector<boost::shared_ptr<Region> > v; + v.push_back (region); + add_regions (v); +} + +void +Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions) +{ bool added = false; { Glib::Mutex::Lock lm (region_lock); - if (region == 0) { - error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg; - } else { - - RegionList::iterator x; - - for (x = regions.begin(); x != regions.end(); ++x) { - - if (region->region_list_equivalent (x->second)) { - break; - } - } - - if (x == regions.end()) { - - pair<RegionList::key_type,RegionList::mapped_type> entry; - - entry.first = region->id(); - entry.second = region; + for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) { + + boost::shared_ptr<Region> region = *ii; + + if (region == 0) { - pair<RegionList::iterator,bool> x = regions.insert (entry); + error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg; + } else { - if (!x.second) { - return; + RegionList::iterator x; + + for (x = regions.begin(); x != regions.end(); ++x) { + + if (region->region_list_equivalent (x->second)) { + break; + } } - - added = true; - } - + + if (x == regions.end()) { + + pair<RegionList::key_type,RegionList::mapped_type> entry; + + entry.first = region->id(); + entry.second = region; + + pair<RegionList::iterator,bool> x = regions.insert (entry); + + if (!x.second) { + return; + } + + added = true; + } + } } } @@ -2591,9 +2619,33 @@ Session::add_region (boost::shared_ptr<Region> region) set_dirty(); if (added) { - region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region))); - region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region))); - RegionAdded (region); /* EMIT SIGNAL */ + + vector<boost::weak_ptr<Region> > v; + boost::shared_ptr<Region> first_r; + + for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) { + + boost::shared_ptr<Region> region = *ii; + + if (region == 0) { + + error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg; + + } else { + v.push_back (region); + + if (!first_r) { + first_r = region; + } + } + + region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region))); + region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region))); + } + + if (!v.empty()) { + RegionsAdded (v); /* EMIT SIGNAL */ + } } } @@ -2680,18 +2732,12 @@ Session::destroy_region (boost::shared_ptr<Region> region) vector<boost::shared_ptr<Source> > srcs; { - boost::shared_ptr<AudioRegion> aregion; - - if ((aregion = boost::dynamic_pointer_cast<AudioRegion> (region)) == 0) { - return 0; - } - - if (aregion->playlist()) { - aregion->playlist()->destroy_region (region); + if (region->playlist()) { + region->playlist()->destroy_region (region); } - for (uint32_t n = 0; n < aregion->n_channels(); ++n) { - srcs.push_back (aregion->source (n)); + for (uint32_t n = 0; n < region->n_channels(); ++n) { + srcs.push_back (region->source (n)); } } @@ -2699,17 +2745,10 @@ Session::destroy_region (boost::shared_ptr<Region> region) for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) { - if (!(*i)->used()) { - boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*i); - - if (afs) { - (afs)->mark_for_remove (); - } - + (*i)->mark_for_remove (); (*i)->drop_references (); cerr << "source was not used by any playlist\n"; - } } return 0; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index af4be07dc4..c4448640fd 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -350,11 +350,15 @@ Session::second_stage_init (bool new_session) return -1; } + BootMessage (_("Reset Remote Controls")); + //send_full_time_code (); _engine.transport_locate (0); deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0); deliver_mmc (MIDI::MachineControl::cmdLocate, 0); + BootMessage (_("Reset Control Protocols")); + ControlProtocolManager::instance().set_session (*this); if (new_session) { @@ -364,7 +368,6 @@ Session::second_stage_init (bool new_session) } _state_of_the_state = Clean; - DirtyChanged (); /* EMIT SIGNAL */ @@ -374,6 +377,8 @@ Session::second_stage_init (bool new_session) state_was_pending = false; } + BootMessage (_("Session loading complete")); + return 0; } @@ -1373,6 +1378,8 @@ Session::load_routes (const XMLNode& node) return -1; } + BootMessage (string_compose (_("Loaded track/bus %1"), route->name())); + new_routes.push_back (route); } diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index d422698f30..e6318f5503 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -1267,9 +1267,9 @@ Session::engine_halted () void Session::xrun_recovery () { - if (Config->get_stop_recording_on_xrun() && actively_recording()) { + Xrun (transport_frame()); //EMIT SIGNAL - HaltOnXrun (); /* EMIT SIGNAL */ + if (Config->get_stop_recording_on_xrun() && actively_recording()) { /* it didn't actually halt, but we need to handle things in the same way. diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 7941eb693b..f08d08b86e 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -195,6 +195,7 @@ Source::set_been_analysed (bool yn) } if (yn) { + load_transients (get_transients_path()); AnalysisChanged(); // EMIT SIGNAL } } @@ -265,3 +266,4 @@ Source::check_for_analysis_data_on_disk () set_been_analysed (ok); return ok; } + diff --git a/libs/ardour/transient_detector.cc b/libs/ardour/transient_detector.cc index b92bf5fb2d..d24c4c9442 100644 --- a/libs/ardour/transient_detector.cc +++ b/libs/ardour/transient_detector.cc @@ -6,18 +6,20 @@ using namespace Vamp; using namespace ARDOUR; using namespace std; -string TransientDetector::_op_id; +/* need a static initializer function for this */ + +string TransientDetector::_op_id = X_("libardourvampplugins:percussiononsets:2"); TransientDetector::TransientDetector (float sr) : AudioAnalyser (sr, X_("libardourvampplugins:percussiononsets")) { - if (_op_id.empty()) { - _op_id = X_("libardourvampplugins:percussiononsets"); - - // XXX this should load the above-named plugin and get the current version + /* update the op_id */ - _op_id += ":2"; - } + _op_id = X_("libardourvampplugins:percussiononsets"); + + // XXX this should load the above-named plugin and get the current version + + _op_id += ":2"; } TransientDetector::~TransientDetector() diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index cfd38c5099..99a6dbbc88 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -86,6 +86,45 @@ legalize_for_path (string str) } #endif +string bump_name_once(std::string name) +{ + string::size_type period; + string newname; + + if ((period = name.find_last_of ('.')) == string::npos) { + newname = name; + newname += ".1"; + } else { + int isnumber = 1; + const char *last_element = name.c_str() + period + 1; + for (size_t i = 0; i < strlen(last_element); i++) { + if (!isdigit(last_element[i])) { + isnumber = 0; + break; + } + } + + errno = 0; + long int version = strtol (name.c_str()+period+1, (char **)NULL, 10); + + if (isnumber == 0 || errno != 0) { + // last_element is not a number, or is too large + newname = name; + newname += ".1"; + } else { + char buf[32]; + + snprintf (buf, sizeof(buf), "%ld", version+1); + + newname = name.substr (0, period+1); + newname += buf; + } + } + + return newname; + +} + ostream& operator<< (ostream& o, const BBT_Time& bbt) { @@ -289,6 +328,8 @@ string_to_edit_mode (string str) return Splice; } else if (str == _("Slide Edit")) { return Slide; + } else if (str == _("Lock Edit")) { + return Lock; } fatal << string_compose (_("programming error: unknown edit mode string \"%1\""), str) << endmsg; /*NOTREACHED*/ @@ -302,6 +343,9 @@ edit_mode_to_string (EditMode mode) case Slide: return _("Slide Edit"); + case Lock: + return _("Lock Edit"); + default: case Splice: return _("Splice Edit"); |