diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-09-10 15:03:30 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-09-10 15:03:30 +0000 |
commit | 68e943265edf04e63a8e8b8f62bab20f99d9c637 (patch) | |
tree | ff8941a59662fc0c4622944b65f7b2d5e3bdd0c3 /libs | |
parent | e4372df05b7d74a6b80dbbf4b6c00cc2b31c4723 (diff) |
merge from 2.0-ongoing @ 3581
git-svn-id: svn://localhost/ardour2/branches/3.0@3711 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
137 files changed, 2519 insertions, 1141 deletions
diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CAAudioUnit.cpp index 9244877d29..aaf57f233d 100644 --- a/libs/appleutility/CAAudioUnit.cpp +++ b/libs/appleutility/CAAudioUnit.cpp @@ -328,6 +328,46 @@ bool CAAudioUnit::CanDo ( int inChannelsIn, return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo))); } +int CAAudioUnit::GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt) +{ + // this is the default assumption of an audio effect unit + Boolean* isWritable = 0; + UInt32 dataSize = 0; + // lets see if the unit has any channel restrictions + OSStatus result = AudioUnitGetPropertyInfo (AU(), + kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + &dataSize, isWritable); //don't care if this is writable + + // if this property is NOT implemented an FX unit + // is expected to deal with same channel valance in and out + + if (result) + { + if (Comp().Desc().IsEffect()) + { + return 1; + } + else + { + // the au should either really tell us about this + // or we will assume the worst + return -1; + } + } + + *chaninfo = (AUChannelInfo*) malloc (dataSize); + cnt = dataSize / sizeof (AUChannelInfo); + + result = GetProperty (kAudioUnitProperty_SupportedNumChannels, + kAudioUnitScope_Global, 0, + *chaninfo, &dataSize); + + if (result) { return -1; } + return 0; +} + + bool CAAudioUnit::ValidateChannelPair (int inChannelsIn, int inChannelsOut, const AUChannelInfo * info, diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CAAudioUnit.h index 6bc31bf30b..810b81be2f 100644 --- a/libs/appleutility/CAAudioUnit.h +++ b/libs/appleutility/CAAudioUnit.h @@ -218,6 +218,7 @@ public: bool HasChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl) const; + int GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt); bool GetChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl, ChannelTagVector &outChannelVector) const; diff --git a/libs/appleutility/SConscript b/libs/appleutility/SConscript index bddca04032..c4f65ec81e 100644 --- a/libs/appleutility/SConscript +++ b/libs/appleutility/SConscript @@ -7,7 +7,7 @@ import glob appleutility_files = glob.glob('*.cpp') Import('env install_prefix') -appleutility = env.Copy() +appleutility = env.Clone() appleutility.Append(LINKFLAGS='-framework AudioToolbox') appleutility.Append(LINKFLAGS='-framework AudioUnit') diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 44f4718384..ca6fc0553e 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -ardour = env.Copy() +ardour = env.Clone() # # this defines the version number of libardour @@ -95,6 +95,7 @@ mtc_slave.cc midi_clock_slave.cc named_selection.cc note.cc +onset_detector.cc panner.cc parameter.cc pcm_utils.cc @@ -357,7 +358,7 @@ env['BUILDERS']['SharedAsmObject'] = Builder (action = '$CXX -c -fPIC $SOURCE -o always_sse_objects = [] -sse_env = ardour.Copy() +sse_env = ardour.Clone() sse_env.Append (CXXFLAGS="-msse") if env['FPU_OPTIMIZATION']: diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h index fecd0fcf4e..fd873f9a6f 100644 --- a/libs/ardour/ardour/ardour.h +++ b/libs/ardour/ardour/ardour.h @@ -32,6 +32,8 @@ #include <ardour/configuration.h> #include <ardour/types.h> +// #include <jack/jack.h> need this to inline jack_get_microseconds + namespace MIDI { class MachineControl; class Port; @@ -57,7 +59,12 @@ namespace ARDOUR { const layer_t max_layer = UCHAR_MAX; microseconds_t get_microseconds (); - +/* { + JACK has exported this functionality for a long time now + but inlining this causes problems + return (microseconds_t) jack_get_time(); + } +*/ Change new_change (); extern Change StartChanged; diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 3546545329..fe7dcb58ff 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -58,8 +58,8 @@ class AudioTrack : public Track void freeze (InterThreadInfo&); void unfreeze (); - void bounce (InterThreadInfo&); - void bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); + boost::shared_ptr<Region> bounce (InterThreadInfo&); + boost::shared_ptr<Region> bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); int set_state(const XMLNode& node); diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index dc9a52d5d3..497954092f 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -100,11 +100,12 @@ class AUPlugin : public ARDOUR::Plugin bool has_editor () const; - bool fixed_io() const { return false; } - int32_t can_support_input_configuration (int32_t in); - int32_t compute_output_streams (int32_t nplugins); - uint32_t output_streams() const; - uint32_t input_streams() const; + bool reconfigurable_io() const { return true; } + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; + int32_t count_for_configuration (const ChanCount& in, ChanCount out) const; + bool configure_io (ChanCount in, ChanCount& out); + ChanCount output_streams() const; + ChanCount input_streams() const; boost::shared_ptr<CAAudioUnit> get_au () { return unit; } boost::shared_ptr<CAComponent> get_comp () const { return comp; } @@ -118,18 +119,19 @@ class AUPlugin : public ARDOUR::Plugin boost::shared_ptr<CAComponent> comp; boost::shared_ptr<CAAudioUnit> unit; - AudioStreamBasicDescription streamFormat; bool initialized; - int format_set; + int32_t input_channels; + int32_t output_channels; + std::vector<std::pair<int,int> > io_configs; AudioBufferList* buffers; UInt32 global_elements; UInt32 output_elements; UInt32 input_elements; - int set_output_format (); - int set_input_format (); - int set_stream_format (int scope, uint32_t cnt); + int set_output_format (AudioStreamBasicDescription&); + int set_input_format (AudioStreamBasicDescription&); + int set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription&); int _set_block_size (nframes_t nframes); void discover_parameters (); @@ -142,10 +144,15 @@ class AUPlugin : public ARDOUR::Plugin std::vector<AUParameterDescriptor> descriptors; void init (); + }; typedef boost::shared_ptr<AUPlugin> AUPluginPtr; +struct AUPluginCachedInfo { + std::vector<std::pair<int,int> > io_configs; +}; + class AUPluginInfo : public PluginInfo { public: AUPluginInfo (boost::shared_ptr<CAComponentDescription>); @@ -153,16 +160,29 @@ class AUPluginInfo : public PluginInfo { PluginPtr load (Session& session); + AUPluginCachedInfo cache; + static PluginInfoList discover (); static void get_names (CAComponentDescription&, std::string& name, Glib::ustring& maker); static std::string stringify_descriptor (const CAComponentDescription&); + static int load_cached_info (); + private: boost::shared_ptr<CAComponentDescription> descriptor; + UInt32 version; static void discover_music (PluginInfoList&); static void discover_fx (PluginInfoList&); static void discover_by_description (PluginInfoList&, CAComponentDescription&); + static Glib::ustring au_cache_path (); + + typedef std::map<std::string,AUPluginCachedInfo> CachedInfoMap; + static CachedInfoMap cached_info; + + static bool cached_io_configuration (const std::string&, UInt32, CAComponent&, AUPluginCachedInfo&, const std::string& name); + static void add_cached_info (const std::string&, AUPluginCachedInfo&); + static void save_cached_info (); }; typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr; diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index e1d5e50cc2..89abc6669a 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -130,13 +130,13 @@ class AudioEngine : public sigc::trackable const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags); - uint32_t n_physical_outputs () const; - uint32_t n_physical_inputs () const; - bool can_request_hardware_monitoring (); - void get_physical_outputs (std::vector<std::string>&); - void get_physical_inputs (std::vector<std::string>&); + uint32_t n_physical_outputs (DataType type) const; + uint32_t n_physical_inputs (DataType type) const; + + void get_physical_outputs (DataType type, std::vector<std::string>&); + void get_physical_inputs (DataType type, std::vector<std::string>&); std::string get_nth_physical_output (DataType type, uint32_t n) { return get_nth_physical (type, n, JackPortIsInput); @@ -152,7 +152,7 @@ class AudioEngine : public sigc::trackable /** Caller may not delete the object pointed to by the return value */ - Port *get_port_by_name (const std::string& name, bool keep = true) const; + Port *get_port_by_name (const std::string& name, bool keep = true); enum TransportState { TransportStopped = JackTransportStopped, @@ -204,27 +204,28 @@ class AudioEngine : public sigc::trackable std::string make_port_name_non_relative (std::string); private: - ARDOUR::Session *session; - jack_client_t *_jack; - std::string jack_client_name; - mutable Glib::Mutex _process_lock; - Glib::Cond session_removed; - bool session_remove_pending; - bool _running; - bool _has_run; - nframes_t _buffer_size; - nframes_t _frame_rate; + ARDOUR::Session* session; + jack_client_t* _jack; + std::string jack_client_name; + Glib::Mutex _process_lock; + Glib::Cond session_removed; + bool session_remove_pending; + bool _running; + bool _has_run; + nframes_t _buffer_size; + nframes_t _frame_rate; /// number of frames between each check for changes in monitor input - nframes_t monitor_check_interval; + nframes_t monitor_check_interval; /// time of the last monitor check in frames - nframes_t last_monitor_check; + nframes_t last_monitor_check; /// the number of frames processed since start() was called - nframes_t _processed_frames; - bool _freewheeling; - bool _freewheel_thread_registered; - sigc::slot<int,nframes_t> freewheel_action; - bool reconnect_on_halt; - int _usecs_per_cycle; + nframes_t _processed_frames; + bool _freewheeling; + bool _freewheel_pending; + bool _freewheel_thread_registered; + sigc::slot<int,nframes_t> freewheel_action; + bool reconnect_on_halt; + int _usecs_per_cycle; SerializedRCUManager<Ports> ports; diff --git a/libs/ardour/ardour/auto_bundle.h b/libs/ardour/ardour/auto_bundle.h index 685a083e8d..9df26a449b 100644 --- a/libs/ardour/ardour/auto_bundle.h +++ b/libs/ardour/ardour/auto_bundle.h @@ -32,7 +32,7 @@ class AutoBundle : public Bundle { AutoBundle (bool i = true); AutoBundle (std::string const &, bool i = true); - uint32_t nchannels () const; + ChanCount nchannels () const; const PortList& channel_ports (uint32_t) const; void set_channels (uint32_t); diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h index fd94360226..72df6c7fd6 100644 --- a/libs/ardour/ardour/buffer.h +++ b/libs/ardour/ardour/buffer.h @@ -21,8 +21,10 @@ #include <cstdlib> #include <cassert> +#include <cstring> #include <iostream> #include <boost/utility.hpp> + #include <ardour/types.h> #include <ardour/data_type.h> #include <ardour/runtime_functions.h> diff --git a/libs/ardour/ardour/bundle.h b/libs/ardour/ardour/bundle.h index ba92063b30..46ba13152e 100644 --- a/libs/ardour/ardour/bundle.h +++ b/libs/ardour/ardour/bundle.h @@ -22,7 +22,9 @@ #include <string> #include <sigc++/signal.h> + #include "ardour/data_type.h" +#include "ardour/chan_count.h" namespace ARDOUR { @@ -37,12 +39,13 @@ class Bundle { Bundle () : _type (DataType::AUDIO) {} Bundle (bool i) : _type (DataType::AUDIO), _ports_are_inputs (i) {} Bundle (std::string const & n, bool i = true) : _name (n), _type (DataType::AUDIO), _ports_are_inputs (i) {} + virtual ~Bundle() {} /** * @return Number of channels that this Bundle has. */ - virtual uint32_t nchannels () const = 0; + virtual ChanCount nchannels () const = 0; virtual const PortList& channel_ports (uint32_t) const = 0; void set_name (std::string const & n) { diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 7a7a2ce419..1f455dc308 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -124,6 +124,7 @@ CONFIG_VARIABLE (bool, quieten_at_speed, "quieten-at-speed", true) CONFIG_VARIABLE (bool, primary_clock_delta_edit_cursor, "primary-clock-delta-edit-cursor", false) CONFIG_VARIABLE (bool, secondary_clock_delta_edit_cursor, "secondary-clock-delta-edit-cursor", false) CONFIG_VARIABLE (bool, show_track_meters, "show-track-meters", true) +CONFIG_VARIABLE (bool, locate_while_waiting_for_sync, "locate-while-waiting-for-sync", false) /* timecode and sync */ @@ -159,6 +160,7 @@ CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", tru CONFIG_VARIABLE (std::string, keyboard_layout, "keyboard-layout", "ansi") CONFIG_VARIABLE (std::string, default_bindings, "default-bindings", "ardour") CONFIG_VARIABLE (bool, default_narrow_ms, "default-narrow_ms", false) +CONFIG_VARIABLE (bool, name_new_markers, "name-new-markers", false) CONFIG_VARIABLE (bool, rubberbanding_snaps_to_grid, "rubberbanding-snaps-to-grid", false) CONFIG_VARIABLE (long, font_scale, "font-scale", 102400) diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 83b6378dae..b44e131d8a 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -368,6 +368,7 @@ class IO : public Automatable, public Latent int create_ports (const XMLNode&); int make_connections (const XMLNode&); + boost::shared_ptr<Bundle> find_possible_bundle (const string &desired_name, const string &default_name, const string &connection_type_name); void setup_peak_meters (); void meter (); diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h index e19c0a51ca..112f306ccb 100644 --- a/libs/ardour/ardour/meter.h +++ b/libs/ardour/ardour/meter.h @@ -40,6 +40,7 @@ public: void reset (); void reset_max (); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; } bool configure_io (ChanCount in, ChanCount out); /** Compute peaks */ diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 500502ac4b..6e4677df22 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -65,8 +65,8 @@ public: void freeze (InterThreadInfo&); void unfreeze (); - void bounce (InterThreadInfo&); - void bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); + boost::shared_ptr<Region> bounce (InterThreadInfo&); + boost::shared_ptr<Region> bounce_range (nframes_t start, nframes_t end, InterThreadInfo&); int set_state(const XMLNode& node); diff --git a/libs/ardour/ardour/onset_detector.h b/libs/ardour/ardour/onset_detector.h new file mode 100644 index 0000000000..9243653d94 --- /dev/null +++ b/libs/ardour/ardour/onset_detector.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2008 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_onset_detector_h__ +#define __ardour_onset_detector_h__ + +#include <ardour/audioanalyser.h> + +namespace ARDOUR { + +class AudioSource; +class Session; + +class OnsetDetector : public AudioAnalyser +{ + + public: + OnsetDetector (float sample_rate); + ~OnsetDetector(); + + static std::string operational_identifier(); + + void set_silence_threshold (float); + void set_peak_threshold (float); + void set_function (int); + + int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results); + + static void cleanup_onsets (AnalysisFeatureList&, float sr, float gap_msecs); + + protected: + AnalysisFeatureList* current_results; + int use_features (Vamp::Plugin::FeatureSet&, std::ostream*); + + static std::string _op_id; +}; + +} /* namespace */ + +#endif /* __ardour_audioanalyser_h__ */ diff --git a/libs/ardour/ardour/osc.h b/libs/ardour/ardour/osc.h index 3f1ce03445..d7c2f4bd85 100644 --- a/libs/ardour/ardour/osc.h +++ b/libs/ardour/ardour/osc.h @@ -54,12 +54,13 @@ class OSC : public BasicUI, public sigc::trackable lo_server _osc_server; lo_server _osc_unix_server; std::string _osc_unix_socket_path; - std::string _osc_url_file; + std::string _osc_url_file; pthread_t _osc_thread; int _request_pipe[2]; static void * _osc_receiver(void * arg); void osc_receiver(); + void send(); // This should accept an OSC payload bool init_osc_thread (); void terminate_osc_thread (); @@ -69,6 +70,11 @@ class OSC : public BasicUI, public sigc::trackable void session_going_away (); + // Handlers for "Application Hook" signals + void session_loaded( ARDOUR::Session& ); + void session_exported( std::string, std::string ); + // end "Application Hook" handles + std::string get_server_url (); std::string get_unix_server_url (); @@ -101,18 +107,19 @@ class OSC : public BasicUI, public sigc::trackable PATH_CALLBACK(rec_enable_toggle); PATH_CALLBACK(toggle_all_rec_enables); -#define PATH_CALLBACK1(name,type) \ +#define PATH_CALLBACK1(name,type,optional) \ static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \ return static_cast<OSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \ } \ int cb_ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data) { \ - if (argc > 0) { \ - name (argv[0]->type); \ - }\ - return 0; \ + if (argc > 0) { \ + name (optional argv[0]->type); \ + } \ + return 0; \ } - PATH_CALLBACK1(set_transport_speed,f); + PATH_CALLBACK1(set_transport_speed,f,); + PATH_CALLBACK1(access_action,s,&); }; } diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index 73f89f1a91..fec044e885 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -145,6 +145,33 @@ class Plugin : public PBD::StatefulDestructible, public Latent virtual bool has_editor() const = 0; + sigc::signal<void,uint32_t,float> ParameterChanged; + + /* NOTE: this block of virtual methods looks like the interface + to a Processor, but Plugin does not inherit from Processor. + It is therefore not required that these precisely match + the interface, but it is likely that they will evolve together. + */ + + /* this returns true if the plugin can change its inputs or outputs on demand. + LADSPA, LV2 and VST plugins cannot do this. AudioUnits can. + */ + + virtual bool reconfigurable_io() const { return false; } + + /* this is only called if reconfigurable_io() returns true */ + virtual bool configure_io (ChanCount in, ChanCount out) { return true; } + + /* specific types of plugins can overload this. As of September 2008, only + AUPlugin does this. + */ + virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return false; } + virtual ChanCount output_streams() const; + virtual ChanCount input_streams() const; + + PBD::Controllable *get_nth_control (uint32_t, bool do_not_create = false); + void make_nth_control (uint32_t, const XMLNode&); + PluginInfoPtr get_info() { return _info; } void set_info (const PluginInfoPtr inf) { _info = inf; } diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index 42c53c487c..c19d113256 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -69,13 +69,12 @@ class PluginInsert : public Processor bool set_count (uint32_t num); uint32_t get_count () const { return _plugins.size(); } - virtual bool can_support_input_configuration (ChanCount in) const; - virtual ChanCount output_for_input_configuration (ChanCount in) const; - virtual bool configure_io (ChanCount in, ChanCount out); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; + bool configure_io (ChanCount in, ChanCount out); bool is_generator() const; - void set_parameter (Parameter param, float val); + void set_parameter (Parameter param, float val); float get_parameter (Parameter param); float default_parameter_value (Parameter param); diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h index 892c8bd75a..858decd0e5 100644 --- a/libs/ardour/ardour/plugin_manager.h +++ b/libs/ardour/ardour/plugin_manager.h @@ -23,6 +23,7 @@ #include <list> #include <map> #include <string> +#include <set> #include <ardour/types.h> #include <ardour/plugin.h> @@ -54,7 +55,31 @@ class PluginManager { static PluginManager* the_manager() { return _manager; } + void load_favorites (); + void save_favorites (); + void add_favorite (ARDOUR::PluginType type, std::string unique_id); + void remove_favorite (ARDOUR::PluginType type, std::string unique_id); + bool is_a_favorite_plugin (const PluginInfoPtr&); + private: + struct FavoritePlugin { + ARDOUR::PluginType type; + std::string unique_id; + + FavoritePlugin (ARDOUR::PluginType t, std::string id) + : type (t), unique_id (id) {} + + bool operator==(const FavoritePlugin& other) const { + return other.type == type && other.unique_id == unique_id; + } + + bool operator<(const FavoritePlugin& other) const { + return other.type < type || other.unique_id < unique_id; + } + }; + typedef std::set<FavoritePlugin> FavoritePluginList; + FavoritePluginList favorites; + ARDOUR::PluginInfoList _vst_plugin_info; ARDOUR::PluginInfoList _ladspa_plugin_info; ARDOUR::PluginInfoList _lv2_plugin_info; diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h index 93c34da16d..084022541d 100644 --- a/libs/ardour/ardour/port.h +++ b/libs/ardour/ardour/port.h @@ -23,7 +23,7 @@ #include <set> #include <vector> #include <string> - +#include <cstring> #include <sigc++/signal.h> #include <pbd/failed_constructor.h> #include <ardour/ardour.h> diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h index 1743040bf5..72f02ff9c7 100644 --- a/libs/ardour/ardour/port_insert.h +++ b/libs/ardour/ardour/port_insert.h @@ -58,9 +58,8 @@ class PortInsert : public IOProcessor ChanCount output_streams() const; ChanCount input_streams() const; - virtual bool can_support_input_configuration (ChanCount in) const; - virtual ChanCount output_for_input_configuration (ChanCount in) const; - virtual bool configure_io (ChanCount in, ChanCount out); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; } + bool configure_io (ChanCount in, ChanCount out); uint32_t bit_slot() const { return bitslot; } diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h index d3e95e8ebf..8c4ac8dfe5 100644 --- a/libs/ardour/ardour/processor.h +++ b/libs/ardour/ardour/processor.h @@ -80,7 +80,7 @@ class Processor : public Automatable, public Latent virtual void activate () { _active = true; ActiveChanged.emit(); } virtual void deactivate () { _active = false; ActiveChanged.emit(); } - virtual bool configure_io (ChanCount in, ChanCount out) { _configured_input = in; return (_configured = true); } + virtual bool configure_io (ChanCount in, ChanCount out); /* Derived classes should override these, or processor appears as an in-place pass-through */ @@ -91,8 +91,7 @@ class Processor : public Automatable, public Latent * and write to their output parameter */ virtual bool is_out_of_place () const { return false; } - virtual bool can_support_input_configuration (ChanCount in) const { return true; } - virtual ChanCount output_for_input_configuration (ChanCount in) const { return in; } + virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const = 0; virtual ChanCount output_streams() const { return _configured_input; } virtual ChanCount input_streams () const { return _configured_input; } diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index c7c0b77102..fb98cb57a7 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -359,8 +359,8 @@ class Route : public IO void input_change_handler (IOChange, void *src); void output_change_handler (IOChange, void *src); - int reset_plugin_counts (ProcessorStreams*); /* locked */ - int _reset_plugin_counts (ProcessorStreams*); /* unlocked */ + int reset_processor_counts (ProcessorStreams*); /* locked */ + int _reset_processor_counts (ProcessorStreams*); /* unlocked */ /* processor I/O channels and plugin count handling */ @@ -372,8 +372,8 @@ class Route : public IO ProcessorCount (boost::shared_ptr<ARDOUR::Processor> ins) : processor(ins) {} }; - int32_t apply_some_plugin_counts (std::list<ProcessorCount>& iclist); - bool check_some_plugin_counts (std::list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err_streams); + int32_t apply_some_processor_counts (std::list<ProcessorCount>& iclist); + bool check_some_processor_counts (std::list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err_streams); void set_deferred_state (); void add_processor_from_xml (const XMLNode&); diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h index 1ee8bbceca..d5078bd7df 100644 --- a/libs/ardour/ardour/send.h +++ b/libs/ardour/ardour/send.h @@ -57,16 +57,17 @@ class Send : public IOProcessor int set_state(const XMLNode& node); uint32_t pans_required() const { return _configured_input.n_audio(); } + void expect_inputs (const ChanCount&); - virtual bool can_support_input_configuration (ChanCount in) const; - virtual ChanCount output_for_input_configuration (ChanCount in) const; - virtual bool configure_io (ChanCount in, ChanCount out); + bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; + bool configure_io (ChanCount in, ChanCount out); static uint32_t how_many_sends(); private: bool _metering; - uint32_t bitslot; + ChanCount expected_inputs; + uint32_t bitslot; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 00cbc9922e..08315c3010 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -434,15 +434,18 @@ class Session : public PBD::StatefulDestructible nframes_t worst_input_latency () const { return _worst_input_latency; } nframes_t worst_track_latency () const { return _worst_track_latency; } - int save_state (string snapshot_name, bool pending = false); - int restore_state (string snapshot_name); - 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); + int save_state (std::string snapshot_name, bool pending = false); + int restore_state (std::string snapshot_name); + int save_template (std::string template_name); + int save_history (std::string snapshot_name = ""); + int restore_history (std::string snapshot_name); + void remove_state (std::string snapshot_name); + void rename_state (std::string old_name, std::string new_name); void remove_pending_capture_state (); + static int rename_template (std::string old_name, std::string new_name); + static int delete_template (std::string name); + sigc::signal<void,string> StateSaved; sigc::signal<void> StateReady; @@ -579,7 +582,7 @@ class Session : public PBD::StatefulDestructible 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; + int region_name (string& result, string base = string(""), bool newlevel = false); string new_region_name (string); string path_from_region_name (DataType type, string name, string identifier); @@ -616,9 +619,11 @@ class Session : public PBD::StatefulDestructible SlaveSource post_export_slave; nframes_t post_export_position; - int start_export (ARDOUR::ExportSpecification&); - int stop_export (ARDOUR::ExportSpecification&); - void finalize_audio_export (); + int pre_export (); + int start_export (ARDOUR::ExportSpecification&); + int stop_export (ARDOUR::ExportSpecification&); + void finalize_export (); + static sigc::signal<void, std::string, std::string> Exported; void add_source (boost::shared_ptr<Source>); void remove_source (boost::weak_ptr<Source>); @@ -706,9 +711,8 @@ class Session : public PBD::StatefulDestructible /* flattening stuff */ - int write_one_audio_track (AudioTrack&, nframes_t start, nframes_t cnt, bool overwrite, - vector<boost::shared_ptr<Source> >&, InterThreadInfo& wot); - + boost::shared_ptr<Region> write_one_track (AudioTrack&, nframes_t start, nframes_t end, bool overwrite, vector<boost::shared_ptr<Source> >&, + InterThreadInfo& wot); int freeze (InterThreadInfo&); /* session-wide solo/mute/rec-enable */ @@ -910,7 +914,7 @@ class Session : public PBD::StatefulDestructible void reset_playback_load_min (); void reset_capture_load_min (); - float read_data_rate () const; + float read_data_rate () const; // in usec float write_data_rate () const; /* ranges */ @@ -1072,6 +1076,7 @@ class Session : public PBD::StatefulDestructible void set_slave_source (SlaveSource); bool _exporting; + int prepare_to_export (ARDOUR::ExportSpecification&); void prepare_diskstreams (); @@ -1393,6 +1398,7 @@ class Session : public PBD::StatefulDestructible void set_play_loop (bool yn); void overwrite_some_buffers (Diskstream*); void flush_all_inserts (); + int micro_locate (nframes_t distance); void locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void force_locate (nframes_t frame, bool with_roll = false); @@ -1457,6 +1463,9 @@ class Session : public PBD::StatefulDestructible /* REGION MANAGEMENT */ + std::map<std::string,uint32_t> region_name_map; + void update_region_name_map (boost::shared_ptr<Region>); + mutable Glib::Mutex region_lock; typedef map<PBD::ID,boost::shared_ptr<Region> > RegionList; RegionList regions; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 4d5545c0dc..fedd83ba68 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -76,8 +76,8 @@ class Track : public Route virtual void freeze (InterThreadInfo&) = 0; virtual void unfreeze () = 0; - virtual void bounce (InterThreadInfo&) = 0; - virtual void bounce_range (nframes_t start, nframes_t end, InterThreadInfo&) = 0; + virtual boost::shared_ptr<Region> bounce (InterThreadInfo&) = 0; + virtual boost::shared_ptr<Region> bounce_range (nframes_t start, nframes_t end, InterThreadInfo&) = 0; XMLNode& get_state(); XMLNode& get_template(); diff --git a/libs/ardour/ardour/user_bundle.h b/libs/ardour/ardour/user_bundle.h index 954e93d5d1..c33ddeaed9 100644 --- a/libs/ardour/ardour/user_bundle.h +++ b/libs/ardour/ardour/user_bundle.h @@ -35,7 +35,7 @@ class UserBundle : public Bundle, public PBD::Stateful { UserBundle (std::string const &); UserBundle (XMLNode const &, bool); - uint32_t nchannels () const; + ChanCount nchannels () const; const ARDOUR::PortList& channel_ports (uint32_t) const; void add_channel (); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 091e1df30f..2953c9e074 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -399,7 +399,7 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram /* if per-track or global rec-enable turned on while the other was already on, we've started recording */ if (((change & track_rec_enabled) && record_enabled() && (!(change & global_rec_enabled) && can_record)) || - (((change & global_rec_enabled) && can_record && (!(change & track_rec_enabled) && record_enabled())))) { + ((change & global_rec_enabled) && can_record && (!(change & track_rec_enabled) && record_enabled()))) { /* starting to record: compute first+last frames */ @@ -524,7 +524,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ commit_should_unlock = false; - if (!_io->active()) { + if (!_io || !_io->active()) { _processed = true; return 0; } @@ -835,7 +835,7 @@ AudioDiskstream::commit (nframes_t nframes) { bool need_butler = false; - if (!_io->active()) { + if (!_io || !_io->active()) { return false; } diff --git a/libs/ardour/audio_library.cc b/libs/ardour/audio_library.cc index a35846ab29..cd473d933f 100644 --- a/libs/ardour/audio_library.cc +++ b/libs/ardour/audio_library.cc @@ -22,6 +22,7 @@ #include <libxml/uri.h> #include <lrdf.h> +#include <glibmm/miscutils.h> #include <glibmm/convert.h> @@ -52,6 +53,7 @@ AudioLibrary::AudioLibrary () // workaround for possible bug in raptor that crashes when saving to a // non-existant file. + touch_file(sfdb_file_path.to_string()); lrdf_read_file(src.c_str()); diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 53f918ec4e..cd05e5fc86 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -743,21 +743,18 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes return 0; } -void +boost::shared_ptr<Region> AudioTrack::bounce (InterThreadInfo& itt) { vector<boost::shared_ptr<Source> > srcs; - _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt); - itt.done = true; + return _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), false, srcs, itt); } - -void +boost::shared_ptr<Region> AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt) { vector<boost::shared_ptr<Source> > srcs; - _session.write_one_audio_track (*this, start, end, false, srcs, itt); - itt.done = true; + return _session.write_one_track (*this, start, end, false, srcs, itt); } void @@ -798,7 +795,9 @@ AudioTrack::freeze (InterThreadInfo& itt) return; } - if (_session.write_one_audio_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) { + boost::shared_ptr<Region> res; + + if ((res = _session.write_one_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) == 0) { return; } diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index b941bc10bb..4862ddcd12 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -24,7 +24,10 @@ #include <pbd/whitespace.h> #include <glibmm/thread.h> +#include <glibmm/fileutils.h> +#include <glibmm/miscutils.h> +#include <ardour/ardour.h> #include <ardour/audioengine.h> #include <ardour/io.h> #include <ardour/audio_unit.h> @@ -43,6 +46,8 @@ using namespace std; using namespace PBD; using namespace ARDOUR; +AUPluginInfo::CachedInfoMap AUPluginInfo::cached_info; + static OSStatus _render_callback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, @@ -120,28 +125,12 @@ AUPlugin::init () unit->GetElementCount (kAudioUnitScope_Input, input_elements); unit->GetElementCount (kAudioUnitScope_Output, output_elements); - // set up the basic stream format. these fields do not change - - streamFormat.mSampleRate = _session.frame_rate(); - streamFormat.mFormatID = kAudioFormatLinearPCM; - streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved; - -#ifdef __LITTLE_ENDIAN__ - /* relax */ -#else - streamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian; -#endif - - streamFormat.mBitsPerChannel = 32; - streamFormat.mFramesPerPacket = 1; - - // subject to later modification as we discover channel counts - - streamFormat.mBytesPerPacket = 4; - streamFormat.mBytesPerFrame = 4; - streamFormat.mChannelsPerFrame = 1; + /* these keep track of *configured* channel set up, + not potential set ups. + */ - format_set = 0; + input_channels = -1; + output_channels = -1; if (_set_block_size (_session.get_block_size())) { error << _("AUPlugin: cannot set processing block size") << endmsg; @@ -396,42 +385,233 @@ AUPlugin::_set_block_size (nframes_t nframes) return 0; } -int32_t -AUPlugin::can_support_input_configuration (int32_t in) -{ - streamFormat.mChannelsPerFrame = in; +int32_t +AUPlugin::configure_io (ChanCount in, ChanCount out) +{ + AudioStreamBasicDescription streamFormat; + + streamFormat.mSampleRate = _session.frame_rate(); + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved; + +#ifdef __LITTLE_ENDIAN__ + /* relax */ +#else + streamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian; +#endif + + streamFormat.mBitsPerChannel = 32; + streamFormat.mFramesPerPacket = 1; + /* apple says that for non-interleaved data, these values always refer to a single channel. */ streamFormat.mBytesPerPacket = 4; streamFormat.mBytesPerFrame = 4; - if (set_input_format () == 0) { - return 1; - } else { + streamFormat.mChannelsPerFrame = in.n_audio(); + + if (set_input_format (streamFormat) != 0) { + return -1; + } + + streamFormat.mChannelsPerFrame = out.n_audio(); + + if (set_output_format (streamFormat) != 0) { return -1; } + + return Plugin::configure_io (in, out); +} + +bool +AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out) +{ + int32_t ret = count_for_configuration (in, out); + return ret >= 0; +} + +int32_t +AUPlugin::count_for_configuration(ChanCount cin, ChanCount& out) const +{ + // XXX as of May 13th 2008, AU plugin support returns a count of either 1 or -1. We never + // attempt to multiply-instantiate plugins to meet io configurations. + + int32_t plugcnt = -1; + AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info()); + int32_t in = cin.n_audio(); /* XXX handle MIDI one day ??? */ + + vector<pair<int,int> >& io_configs = pinfo->cache.io_configs; + + for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) { + + int32_t possible_in = i->first; + int32_t possible_out = i->second; + + if (possible_out == 0) { + warning << string_compose (_("AU %1 has zero outputs - configuration ignored"), name()) << endmsg; + continue; + } + + if (possible_in == 0) { + + /* instrument plugin, always legal but throws away inputs ... + */ + + if (possible_out == -1) { + /* out much match in (UNLIKELY!!) */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + /* any configuration possible, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in == -1) { + + /* wildcard for input */ + + if (possible_out == -1) { + /* out much match in */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + /* any configuration possible, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in == -2) { + + if (possible_out == -1) { + /* any configuration possible, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + error << string_compose (_("AU plugin %1 has illegal IO configuration (-2,-2)"), name()) + << endmsg; + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in < -2) { + + /* explicit variable number of inputs */ + + if (in > -possible_in) { + /* request is too large */ + plugcnt = -1; + } + + if (possible_out == -1) { + /* out must match in */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + error << string_compose (_("AU plugin %1 has illegal IO configuration (-2,-2)"), name()) + << endmsg; + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + if (possible_in == in) { + + /* exact number of inputs ... must match obviously */ + + if (possible_out == -1) { + /* out must match in */ + out.set (DataType::AUDIO, in); + plugcnt = 1; + } else if (possible_out == -2) { + /* any output configuration, pick matching */ + out.set (DataType::AUDIO, in); + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out.set (DataType::AUDIO, -possible_out); + plugcnt = 1; + } else { + /* exact number of outputs */ + out.set (DataType::AUDIO, possible_out); + plugcnt = 1; + } + } + + } + + /* no fit */ + return plugcnt; } int -AUPlugin::set_input_format () +AUPlugin::set_input_format (AudioStreamBasicDescription& fmt) { - return set_stream_format (kAudioUnitScope_Input, input_elements); + return set_stream_format (kAudioUnitScope_Input, input_elements, fmt); } int -AUPlugin::set_output_format () +AUPlugin::set_output_format (AudioStreamBasicDescription& fmt) { - return set_stream_format (kAudioUnitScope_Output, output_elements); + if (set_stream_format (kAudioUnitScope_Output, output_elements, fmt) != 0) { + return -1; + } + + if (buffers) { + free (buffers); + buffers = 0; + } + + buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) + + fmt.mChannelsPerFrame * sizeof(AudioBuffer)); + + Glib::Mutex::Lock em (_session.engine().process_lock()); + IO::PortCountChanged (ChanCount (DataType::AUDIO, fmt.mChannelsPerFrame)); + + return 0; } int -AUPlugin::set_stream_format (int scope, uint32_t cnt) +AUPlugin::set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription& fmt) { OSErr result; for (uint32_t i = 0; i < cnt; ++i) { - if ((result = unit->SetFormat (scope, i, streamFormat)) != 0) { + if ((result = unit->SetFormat (scope, i, fmt)) != 0) { error << string_compose (_("AUPlugin: could not set stream format for %1/%2 (err = %3)"), (scope == kAudioUnitScope_Input ? "input" : "output"), i, result) << endmsg; return -1; @@ -439,60 +619,44 @@ AUPlugin::set_stream_format (int scope, uint32_t cnt) } if (scope == kAudioUnitScope_Input) { - format_set |= 0x1; + input_channels = fmt.mChannelsPerFrame; } else { - format_set |= 0x2; + output_channels = fmt.mChannelsPerFrame; } return 0; } -int32_t -AUPlugin::compute_output_streams (int32_t nplugins) -{ - /* we will never replicate AU plugins - either they can do the I/O we need - or not. thus, we can ignore nplugins entirely. - */ - - if (set_output_format() == 0) { - if (buffers) { - free (buffers); - buffers = 0; - } - - buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) + - streamFormat.mChannelsPerFrame * sizeof(AudioBuffer)); - - Glib::Mutex::Lock em (_session.engine().process_lock()); - IO::MoreOutputs (streamFormat.mChannelsPerFrame); +ChanCount +AUPlugin::input_streams() const +{ + ChanCount in; - return streamFormat.mChannelsPerFrame; + if (input_channels < 0) { + warning << string_compose (_("AUPlugin: %1 input_streams() called without any format set!"), name()) << endmsg; + in.set_audio (1); } else { - return -1; + in.set_audio (input_channels); } + + return in; } -uint32_t + +ChanCount AUPlugin::output_streams() const { - if (!(format_set & 0x2)) { + ChanCount out; + + if (output_channels < 0) { warning << string_compose (_("AUPlugin: %1 output_streams() called without any format set!"), name()) << endmsg; - return 1; + out.set_audio (1); + } else { + out.set_audio (output_channels); } - return streamFormat.mChannelsPerFrame; -} - - -uint32_t -AUPlugin::input_streams() const -{ - if (!(format_set & 0x1)) { - warning << _("AUPlugin: input_streams() called without any format set!") << endmsg; - return 1; - } - return streamFormat.mChannelsPerFrame; + return out; } OSStatus @@ -679,13 +843,25 @@ AUPluginInfo::load (Session& session) } catch (failed_constructor &err) { - return PluginPtr ((Plugin*) 0); + return PluginPtr (); } } +Glib::ustring +AUPluginInfo::au_cache_path () +{ + return Glib::build_filename (ARDOUR::get_user_ardour_path(), "au_cache"); +} + PluginInfoList AUPluginInfo::discover () { + XMLTree tree; + + if (!Glib::file_test (au_cache_path(), Glib::FILE_TEST_EXISTS)) { + ARDOUR::BootMessage (_("Discovering AudioUnit plugins (could take some time ...)")); + } + PluginInfoList plugs; discover_fx (plugs); @@ -839,17 +1015,211 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip info->type = ARDOUR::AudioUnit; info->unique_id = stringify_descriptor (*info->descriptor); - /* mark the plugin as having flexible i/o */ + /* XXX not sure of the best way to handle plugin versioning yet + */ + + CAComponent cacomp (*info->descriptor); + + if (cacomp.GetResourceVersion (info->version) != noErr) { + info->version = 0; + } - info->n_inputs = -1; - info->n_outputs = -1; + if (cached_io_configuration (info->unique_id, info->version, cacomp, info->cache, info->name)) { + + /* here we have to map apple's wildcard system to a simple pair + of values. + */ + + info->n_inputs = ChanCount (DataType::AUDIO, info->cache.io_configs.front().first); + info->n_outputs = ChanCount (DataType::AUDIO, info->cache.io_configs.front().second); + + if (info->cache.io_configs.size() > 1) { + cerr << "ODD: variable IO config for " << info->unique_id << endl; + } + + plugs.push_back (info); - plugs.push_back (info); + } else { + error << string_compose (_("Cannot get I/O configuration info for AU %1"), info->name) << endmsg; + } comp = FindNextComponent (comp, &desc); } } +bool +AUPluginInfo::cached_io_configuration (const std::string& unique_id, + UInt32 version, + CAComponent& comp, + AUPluginCachedInfo& cinfo, + const std::string& name) +{ + std::string id; + char buf[32]; + + /* concatenate unique ID with version to provide a key for cached info lookup. + this ensures we don't get stale information, or should if plugin developers + follow Apple "guidelines". + */ + + snprintf (buf, sizeof (buf), "%u", version); + id = unique_id; + id += '/'; + id += buf; + + CachedInfoMap::iterator cim = cached_info.find (id); + + if (cim != cached_info.end()) { + cinfo = cim->second; + return true; + } + + CAAudioUnit unit; + AUChannelInfo* channel_info; + UInt32 cnt; + int ret; + + ARDOUR::BootMessage (string_compose (_("Checking AudioUnit: %1"), name)); + + if (CAAudioUnit::Open (comp, unit) != noErr) { + return false; + } + + if ((ret = unit.GetChannelInfo (&channel_info, cnt)) < 0) { + return false; + } + + if (ret > 0) { + /* no explicit info available */ + + cinfo.io_configs.push_back (pair<int,int> (-1, -1)); + + } else { + + /* store each configuration */ + + for (uint32_t n = 0; n < cnt; ++n) { + cinfo.io_configs.push_back (pair<int,int> (channel_info[n].inChannels, + channel_info[n].outChannels)); + } + + free (channel_info); + } + + add_cached_info (id, cinfo); + save_cached_info (); + + return true; +} + +void +AUPluginInfo::add_cached_info (const std::string& id, AUPluginCachedInfo& cinfo) +{ + cached_info[id] = cinfo; +} + +void +AUPluginInfo::save_cached_info () +{ + XMLNode* node; + + node = new XMLNode (X_("AudioUnitPluginCache")); + + for (map<string,AUPluginCachedInfo>::iterator i = cached_info.begin(); i != cached_info.end(); ++i) { + XMLNode* parent = new XMLNode (X_("plugin")); + parent->add_property ("id", i->first); + node->add_child_nocopy (*parent); + + for (vector<pair<int, int> >::iterator j = i->second.io_configs.begin(); j != i->second.io_configs.end(); ++j) { + + XMLNode* child = new XMLNode (X_("io")); + char buf[32]; + + snprintf (buf, sizeof (buf), "%d", j->first); + child->add_property (X_("in"), buf); + snprintf (buf, sizeof (buf), "%d", j->second); + child->add_property (X_("out"), buf); + parent->add_child_nocopy (*child); + } + + } + + Glib::ustring path = au_cache_path (); + XMLTree tree; + + tree.set_root (node); + + if (!tree.write (path)) { + error << string_compose (_("could not save AU cache to %1"), path) << endmsg; + unlink (path.c_str()); + } +} + +int +AUPluginInfo::load_cached_info () +{ + Glib::ustring path = au_cache_path (); + XMLTree tree; + + if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) { + return 0; + } + + tree.read (path); + const XMLNode* root (tree.root()); + + if (root->name() != X_("AudioUnitPluginCache")) { + return -1; + } + + cached_info.clear (); + + const XMLNodeList children = root->children(); + + for (XMLNodeConstIterator iter = children.begin(); iter != children.end(); ++iter) { + + const XMLNode* child = *iter; + + if (child->name() == X_("plugin")) { + + const XMLNode* gchild; + const XMLNodeList gchildren = child->children(); + const XMLProperty* prop = child->property (X_("id")); + + if (!prop) { + continue; + } + + std::string id = prop->value(); + + for (XMLNodeConstIterator giter = gchildren.begin(); giter != gchildren.end(); giter++) { + + gchild = *giter; + + if (gchild->name() == X_("io")) { + + int in; + int out; + const XMLProperty* iprop; + const XMLProperty* oprop; + + if (((iprop = gchild->property (X_("in"))) != 0) && + ((oprop = gchild->property (X_("out"))) != 0)) { + in = atoi (iprop->value()); + out = atoi (iprop->value()); + + AUPluginCachedInfo cinfo; + cinfo.io_configs.push_back (pair<int,int> (in, out)); + add_cached_info (id, cinfo); + } + } + } + } + } + + return 0; +} + void AUPluginInfo::get_names (CAComponentDescription& comp_desc, std::string& name, Glib::ustring& maker) { diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index a3f5eb9fd1..76c0de9b24 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -70,13 +70,12 @@ AudioEngine::AudioEngine (string client_name) last_monitor_check = 0; monitor_check_interval = max_frames; _processed_frames = 0; - _freewheeling = false; _usecs_per_cycle = 0; _jack = 0; _frame_rate = 0; _buffer_size = 0; - _freewheeling = false; _freewheel_thread_registered = false; + _freewheeling = false; m_meter_thread = 0; g_atomic_int_set (&m_meter_exit, 0); @@ -84,6 +83,7 @@ AudioEngine::AudioEngine (string client_name) if (connect_to_jack (client_name)) { throw NoBackendAvailable (); } + Port::set_engine (this); } @@ -331,8 +331,6 @@ AudioEngine::process_callback (nframes_t nframes) if (_freewheeling) { /* emit the Freewheel signal and stop freewheeling in the event of trouble */ if (Freewheel (nframes)) { - cerr << "Freewheeling returned non-zero!\n"; - _freewheeling = false; jack_set_freewheel (_jack, false); } @@ -847,7 +845,7 @@ AudioEngine::frames_per_cycle () * Note this can return NULL, it will NOT create a port if it is not found (any more). */ Port * -AudioEngine::get_port_by_name (const string& portname, bool keep) const +AudioEngine::get_port_by_name (const string& portname, bool keep) { Glib::Mutex::Lock lm (_process_lock); @@ -923,7 +921,7 @@ AudioEngine::can_request_hardware_monitoring () uint32_t -AudioEngine::n_physical_outputs () const +AudioEngine::n_physical_outputs (DataType type) const { const char ** ports; uint32_t i = 0; @@ -932,7 +930,7 @@ AudioEngine::n_physical_outputs () const return 0; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsInput)) == 0) { return 0; } @@ -943,7 +941,7 @@ AudioEngine::n_physical_outputs () const } uint32_t -AudioEngine::n_physical_inputs () const +AudioEngine::n_physical_inputs (DataType type) const { const char ** ports; uint32_t i = 0; @@ -952,7 +950,7 @@ AudioEngine::n_physical_inputs () const return 0; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsOutput)) == 0) { return 0; } @@ -964,7 +962,7 @@ AudioEngine::n_physical_inputs () const } void -AudioEngine::get_physical_inputs (vector<string>& ins) +AudioEngine::get_physical_inputs (DataType type, vector<string>& ins) { const char ** ports; uint32_t i = 0; @@ -973,7 +971,7 @@ AudioEngine::get_physical_inputs (vector<string>& ins) return; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsOutput)) == 0) { return; } @@ -986,7 +984,7 @@ AudioEngine::get_physical_inputs (vector<string>& ins) } void -AudioEngine::get_physical_outputs (vector<string>& outs) +AudioEngine::get_physical_outputs (DataType type, vector<string>& outs) { const char ** ports; uint32_t i = 0; @@ -995,7 +993,7 @@ AudioEngine::get_physical_outputs (vector<string>& outs) return; } - if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) { + if ((ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|JackPortIsInput)) == 0) { return; } @@ -1123,11 +1121,18 @@ AudioEngine::freewheel (bool onoff) { if (_jack) { - if (onoff) { - _freewheel_thread_registered = false; - } + if (onoff != _freewheeling) { - return jack_set_freewheel (_jack, onoff); + if (onoff) { + _freewheel_thread_registered = false; + } + + return jack_set_freewheel (_jack, onoff); + + } else { + /* already doing what has been asked for */ + return 0; + } } else { return -1; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index f5f04eac6d..cbf2e44c5f 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -1243,6 +1243,15 @@ AudioRegion::speed_mismatch (float sr) const void AudioRegion::source_offset_changed () { + /* XXX this fixes a crash that should not occur. It does occur + becauses regions are not being deleted when a session + is unloaded. That bug must be fixed. + */ + + if (_sources.empty()) { + return; + } + boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(_sources.front()); if (afs && afs->destructive()) { diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index 01dea08d3e..8e68b31587 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -214,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 || (statbuf.st_size < ((length() / _FPP) * sizeof (PeakData)))) { + if (statbuf.st_size == 0 || ((nframes_t) statbuf.st_size < ((length() / _FPP) * sizeof (PeakData)))) { // empty _peaks_built = false; } else { diff --git a/libs/ardour/auto_bundle.cc b/libs/ardour/auto_bundle.cc index 9da32bbb7a..fc70768601 100644 --- a/libs/ardour/auto_bundle.cc +++ b/libs/ardour/auto_bundle.cc @@ -13,17 +13,17 @@ ARDOUR::AutoBundle::AutoBundle (std::string const & n, bool i) } -uint32_t +ARDOUR::ChanCount ARDOUR::AutoBundle::nchannels () const { Glib::Mutex::Lock lm (_ports_mutex); - return _ports.size (); + return ChanCount (type(), _ports.size ()); } const ARDOUR::PortList& ARDOUR::AutoBundle::channel_ports (uint32_t c) const { - assert (c < nchannels()); + assert (c < nchannels().get (type())); Glib::Mutex::Lock lm (_ports_mutex); return _ports[c]; @@ -39,7 +39,7 @@ ARDOUR::AutoBundle::set_channels (uint32_t n) void ARDOUR::AutoBundle::set_port (uint32_t c, std::string const & p) { - assert (c < nchannels ()); + assert (c < nchannels ().get (type())); Glib::Mutex::Lock lm (_ports_mutex); _ports[c].resize (1); diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc index b164d418ab..56dfd99f02 100644 --- a/libs/ardour/configuration.cc +++ b/libs/ardour/configuration.cc @@ -22,6 +22,7 @@ #include <glib.h> #include <glib/gstdio.h> /* for g_stat() */ +#include <glibmm/miscutils.h> #include <pbd/failed_constructor.h> #include <pbd/xml++.h> diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc index f3dfa28165..213e7504b0 100644 --- a/libs/ardour/crossfade.cc +++ b/libs/ardour/crossfade.cc @@ -84,7 +84,6 @@ Crossfade::Crossfade (boost::shared_ptr<AudioRegion> in, boost::shared_ptr<Audio { _in = in; _out = out; - _anchor_point = ap; _follow_overlap = false; diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 1397a7d959..3401d8c48a 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -30,6 +30,10 @@ #include <fst.h> #endif +#ifdef HAVE_AUDIOUNITS +#include <ardour/audio_unit.h> +#endif + #ifdef __SSE__ #include <xmmintrin.h> #endif @@ -347,6 +351,10 @@ ARDOUR::init (bool use_vst, bool try_optimization) } #endif +#ifdef HAVE_AUDIOUNITS + AUPluginInfo::load_cached_info (); +#endif + /* Make VAMP look in our library ahead of anything else */ char *p = getenv ("VAMP_PATH"); @@ -393,11 +401,7 @@ ARDOUR::cleanup () microseconds_t ARDOUR::get_microseconds () { - /* XXX need JACK to export its functionality */ - - struct timeval now; - gettimeofday (&now, 0); - return now.tv_sec * 1000000ULL + now.tv_usec; + return (microseconds_t) jack_get_time (); } ARDOUR::Change @@ -431,7 +435,6 @@ 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")) { diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index d79c930e6d..d4afda8b5a 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -459,15 +459,16 @@ Session::import_audiofiles (import_status& status) if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) { afs->update_header(0, *now, xnow); afs->done_with_peakfile_writes (); - } - - /* now that there is data there, requeue the file for analysis */ - if (Config->get_auto_analyse_audio()) { - Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false); + /* now that there is data there, requeue the file for analysis */ + + if (Config->get_auto_analyse_audio()) { + Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false); + } } - + /* don't create tracks for empty MIDI sources (channels) */ + if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) { x = all_new_sources.erase(x); } else { diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 5d4b41cf32..1b3c2e2378 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -24,6 +24,7 @@ #include <sigc++/bind.h> +#include <glibmm.h> #include <glibmm/thread.h> #include <pbd/xml++.h> @@ -358,14 +359,16 @@ IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports) for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) { - uint32_t const N = i->bundle->nchannels (); + ChanCount const N = i->bundle->nchannels (); - if (ports.num_ports() < N) { + if (ports.num_ports (default_type()) < N.get (default_type())) { continue; } bool ok = true; - for (uint32_t j = 0; j < N; ++j) { + uint32_t n = N.get (default_type()); + + for (uint32_t j = 0; j < n; ++j) { /* Every port on bundle channel j must be connected to our input j */ PortList const pl = i->bundle->channel_ports (j); for (uint32_t k = 0; k < pl.size(); ++k) { @@ -730,7 +733,7 @@ IO::add_input_port (string source, void* src, DataType type) { Glib::Mutex::Lock lm (io_lock); - if (n_inputs() >= _input_maximum) { + if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) { return -1; } @@ -1460,16 +1463,12 @@ IO::load_automation (string path) float version; LocaleGuard lg (X_("POSIX")); - fullpath = _session.automation_dir(); - fullpath += path; + fullpath = Glib::build_filename(_session.automation_dir(), path); in.open (fullpath.c_str()); if (!in) { - fullpath = _session.automation_dir(); - fullpath += _session.snap_name(); - fullpath += '-'; - fullpath += path; + fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path); in.open (fullpath.c_str()); @@ -1573,23 +1572,138 @@ IO::ports_became_legal () return ret; } +boost::shared_ptr<Bundle> +IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name) +{ + static const string digits = "0123456789"; + + boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name); + + if (!c) { + int bundle_number, mask; + string possible_name; + bool stereo = false; + string::size_type last_non_digit_pos; + + error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name) + << endmsg; + + // find numeric suffix of desired name + bundle_number = 0; + + last_non_digit_pos = desired_name.find_last_not_of(digits); + + if (last_non_digit_pos != string::npos) { + stringstream s; + s << desired_name.substr(last_non_digit_pos); + s >> bundle_number; + } + + // see if it's a stereo connection e.g. "in 3+4" + + if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') { + int left_bundle_number = 0; + string::size_type left_last_non_digit_pos; + + left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1); + + if (left_last_non_digit_pos != string::npos) { + stringstream s; + s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1); + s >> left_bundle_number; + + if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) { + bundle_number--; + stereo = true; + } + } + } + + // make 0-based + if (bundle_number) + bundle_number--; + + // find highest set bit + mask = 1; + while ((mask <= bundle_number) && (mask <<= 1)); + + // "wrap" bundle number into largest possible power of 2 + // that works... + + while (mask) { + + if (bundle_number & mask) { + bundle_number &= ~mask; + + stringstream s; + s << default_name << " " << bundle_number + 1; + + if (stereo) { + s << "+" << bundle_number + 2; + } + + possible_name = s.str(); + + if ((c = _session.bundle_by_name (possible_name)) != 0) { + break; + } + } + mask >>= 1; + } + if (c) { + info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name) + << endmsg; + } else { + error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name) + << endmsg; + } + + } + + return c; + +} + int IO::create_ports (const XMLNode& node) { XMLProperty const * prop; - int num_inputs = 0; - int num_outputs = 0; + ChanCount num_inputs; + ChanCount num_outputs; + + if ((prop = node.property ("input-connection")) != 0) { - if ((prop = node.property ("inputs")) != 0) { - num_inputs = count (prop->value().begin(), prop->value().end(), '{'); + boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input")); + + if (!c) { + return -1; + } + + num_inputs = c->nchannels(); + + } else if ((prop = node.property ("inputs")) != 0) { + + num_inputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{')); + } + + if ((prop = node.property ("output-connection")) != 0) { + + boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output")); + + if (!c) { + return -1; + } + + num_outputs = c->nchannels (); + } else if ((prop = node.property ("outputs")) != 0) { - num_outputs = count (prop->value().begin(), prop->value().end(), '{'); + + num_outputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{')); } no_panner_reset = true; - // FIXME: audio-only - if (ensure_io (ChanCount(DataType::AUDIO, num_inputs), ChanCount(DataType::AUDIO, num_outputs), true, this)) { + if (ensure_io (num_inputs, num_outputs, true, this)) { error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg; return -1; } @@ -1606,17 +1720,35 @@ IO::create_ports (const XMLNode& node) int IO::make_connections (const XMLNode& node) { - XMLProperty const * prop; - - if ((prop = node.property ("inputs")) != 0) { + + const XMLProperty* prop; + + if ((prop = node.property ("input-connection")) != 0) { + boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input")); + + if (!c) { + return -1; + } + + connect_input_ports_to_bundle (c, this); + + } else if ((prop = node.property ("inputs")) != 0) { if (set_inputs (prop->value())) { error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg; return -1; } } - - if ((prop = node.property ("outputs")) != 0) { + if ((prop = node.property ("output-connection")) != 0) { + boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output")); + + if (!c) { + return -1; + } + + connect_output_ports_to_bundle (c, this); + + } else if ((prop = node.property ("outputs")) != 0) { if (set_outputs (prop->value())) { error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg; return -1; @@ -1628,23 +1760,19 @@ IO::make_connections (const XMLNode& node) if ((*i)->name() == "InputBundle") { XMLProperty const * prop = (*i)->property ("name"); if (prop) { - boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value()); + boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input")); if (b) { connect_input_ports_to_bundle (b, this); - } else { - error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg; } } } else if ((*i)->name() == "OutputBundle") { XMLProperty const * prop = (*i)->property ("name"); if (prop) { - boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value()); + boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output")); if (b) { connect_output_ports_to_bundle (b, this); - } else { - error << string_compose(_("Unknown bundle \"%1\" listed for output of %2"), prop->value(), _name) << endmsg; - } + } } } } @@ -1924,9 +2052,10 @@ IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src) /* Connect to the bundle, not worrying about any connections that are already made. */ - uint32_t const channels = c->nchannels (); - - for (uint32_t n = 0; n < channels; ++n) { + ChanCount const channels = c->nchannels (); + uint32_t cnt = channels.get (default_type()); + + for (uint32_t n = 0; n < cnt; ++n) { const PortList& pl = c->channel_ports (n); for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) { @@ -1973,9 +2102,10 @@ IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src) /* Connect to the bundle, not worrying about any connections that are already made. */ - uint32_t const channels = c->nchannels (); + ChanCount const channels = c->nchannels (); + uint32_t cnt = channels.get (default_type()); - for (uint32_t n = 0; n < channels; ++n) { + for (uint32_t n = 0; n < cnt; ++n) { const PortList& pl = c->channel_ports (n); @@ -2105,8 +2235,8 @@ IO::GainControl::get_value (void) const void IO::setup_peak_meters() { - ChanCount max_streams = std::max(_inputs.count(), _outputs.count()); - _meter->configure_io(max_streams, max_streams); + ChanCount max_streams = std::max (_inputs.count(), _outputs.count()); + _meter->configure_io (max_streams, max_streams); } /** @@ -2496,11 +2626,12 @@ void IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles) { boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b); + if (ab == 0 || ab->ports_are_outputs() == false) { return; } - - if (ab->nchannels () != n_inputs().n_total ()) { + + if (ab->nchannels().get (default_type()) != n_inputs().n_total ()) { return; } @@ -2552,7 +2683,7 @@ IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<bo return; } - if (ab->nchannels () != n_outputs().n_total ()) { + if (ab->nchannels ().get (default_type()) != n_outputs().n_total ()) { return; } diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 0da75810ca..3654e03a9d 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -100,6 +100,7 @@ Location::set_start (nframes_t s) _end = s; start_changed(this); /* EMIT SIGNAL */ + end_changed(this); /* EMIT SIGNAL */ if ( is_start() ) { @@ -137,7 +138,17 @@ Location::set_end (nframes_t e) if (_start != e) { _start = e; _end = e; + start_changed(this); /* EMIT SIGNAL */ end_changed(this); /* EMIT SIGNAL */ + + if ( is_start() ) { + Session::StartTimeChanged (); /* EMIT SIGNAL */ + } + + if ( is_end() ) { + Session::EndTimeChanged (); /* EMIT SIGNAL */ + } + } return 0; } diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 4553458831..a38c851c21 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -23,6 +23,7 @@ #include <cstdlib> #include <cmath> +#include <cstring> #include <pbd/compose.h> #include <pbd/error.h> diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc index e75c1d89ca..aedfd17be8 100644 --- a/libs/ardour/meter.cc +++ b/libs/ardour/meter.cc @@ -95,8 +95,9 @@ bool PeakMeter::configure_io (ChanCount in, ChanCount out) { /* we're transparent no matter what. fight the power. */ - if (out != in) + if (out != in) { return false; + } uint32_t limit = in.n_total(); @@ -116,9 +117,7 @@ PeakMeter::configure_io (ChanCount in, ChanCount out) assert(_visible_peak_power.size() == limit); assert(_max_peak_power.size() == limit); - Processor::configure_io(in, out); - - return true; + return Processor::configure_io (in, out); } /** To be driven by the Meter signal from IO. diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 1000e68ba6..efb6e5b8d9 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -661,21 +661,23 @@ MidiTrack::set_latency_delay (nframes_t longest_session_latency) _diskstream->set_roll_delay (_roll_delay); } -void +boost::shared_ptr<Region> MidiTrack::bounce (InterThreadInfo& itt) { throw; - //vector<MidiSource*> srcs; - //_session.write_one_midi_track (*this, 0, _session.current_end_frame(), false, srcs, itt); + // vector<MidiSource*> srcs; + // return _session.write_one_track (*this, 0, _session.current_end_frame(), false, srcs, itt); + return boost::shared_ptr<Region> (); } -void +boost::shared_ptr<Region> MidiTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt) { throw; //vector<MidiSource*> srcs; - //_session.write_one_midi_track (*this, start, end, false, srcs, itt); + //return _session.write_one_track (*this, start, end, false, srcs, itt); + return boost::shared_ptr<Region> (); } void @@ -732,7 +734,7 @@ MidiTrack::MidiControl::set_value(float val) size_t size = 3; if ( ! _list->automation_playback()) { - uint8_t ev[3] = { _list->parameter().channel(), int(val), 0.0 }; + uint8_t ev[3] = { _list->parameter().channel(), int(val), 0 }; switch(_list->parameter().type()) { case MidiCCAutomation: ev[0] += MIDI_CMD_CONTROL; diff --git a/libs/ardour/onset_detector.cc b/libs/ardour/onset_detector.cc new file mode 100644 index 0000000000..f58e64ad4a --- /dev/null +++ b/libs/ardour/onset_detector.cc @@ -0,0 +1,126 @@ +#include <ardour/onset_detector.h> + +#include "i18n.h" + +using namespace Vamp; +using namespace ARDOUR; +using namespace std; + +/* need a static initializer function for this */ + +string OnsetDetector::_op_id = X_("libardourvampplugins:aubioonset:2"); + +OnsetDetector::OnsetDetector (float sr) + : AudioAnalyser (sr, X_("libardourvampplugins:aubioonset")) +{ + /* update the op_id */ + + _op_id = X_("libardourvampplugins:aubioonset"); + + // XXX this should load the above-named plugin and get the current version + + _op_id += ":2"; +} + +OnsetDetector::~OnsetDetector() +{ +} + +string +OnsetDetector::operational_identifier() +{ + return _op_id; +} + +int +OnsetDetector::run (const std::string& path, Readable* src, uint32_t channel, AnalysisFeatureList& results) +{ + current_results = &results; + int ret = analyse (path, src, channel); + + current_results = 0; + return ret; +} + +int +OnsetDetector::use_features (Plugin::FeatureSet& features, ostream* out) +{ + const Plugin::FeatureList& fl (features[0]); + + for (Plugin::FeatureList::const_iterator f = fl.begin(); f != fl.end(); ++f) { + + if ((*f).hasTimestamp) { + + if (out) { + (*out) << (*f).timestamp.toString() << endl; + } + + current_results->push_back (RealTime::realTime2Frame ((*f).timestamp, (nframes_t) floor(sample_rate))); + } + } + + return 0; +} + +void +OnsetDetector::set_silence_threshold (float val) +{ + if (plugin) { + plugin->setParameter ("silencethreshold", val); + } +} + +void +OnsetDetector::set_peak_threshold (float val) +{ + if (plugin) { + plugin->setParameter ("peakpickthreshold", val); + } +} + +void +OnsetDetector::set_function (int val) +{ + if (plugin) { + plugin->setParameter ("onsettype", (float) val); + } +} + +void +OnsetDetector::cleanup_onsets (AnalysisFeatureList& t, float sr, float gap_msecs) +{ + if (t.empty()) { + return; + } + + t.sort (); + + /* remove duplicates or other things that are too close */ + + AnalysisFeatureList::iterator i = t.begin(); + AnalysisFeatureList::iterator f, b; + const nframes64_t gap_frames = (nframes64_t) floor (gap_msecs * (sr / 1000.0)); + + while (i != t.end()) { + + // move front iterator to just past i, and back iterator the same place + + f = i; + ++f; + b = f; + + // move f until we find a new value that is far enough away + + while ((f != t.end()) && (((*f) - (*i)) < gap_frames)) { + ++f; + } + + i = f; + + // if f moved forward from b, we had duplicates/too-close points: get rid of them + + if (b != f) { + t.erase (b, f); + } + } +} diff --git a/libs/ardour/osc.cc b/libs/ardour/osc.cc index b0bd35b8c6..0c58040ad6 100644 --- a/libs/ardour/osc.cc +++ b/libs/ardour/osc.cc @@ -28,6 +28,8 @@ #include <unistd.h> #include <fcntl.h> +#include <glibmm/miscutils.h> + #include <pbd/pthread_utils.h> #include <pbd/file_utils.h> @@ -183,6 +185,7 @@ OSC::register_callbacks() #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this) REGISTER_CALLBACK (serv, "/ardour/add_marker", "", add_marker); + REGISTER_CALLBACK (serv, "/ardour/access_action", "s", access_action); REGISTER_CALLBACK (serv, "/ardour/loop_toggle", "", loop_toggle); REGISTER_CALLBACK (serv, "/ardour/goto_start", "", goto_start); REGISTER_CALLBACK (serv, "/ardour/goto_end", "", goto_end); @@ -409,6 +412,10 @@ OSC::set_session (Session& s) { session = &s; session->GoingAway.connect (mem_fun (*this, &OSC::session_going_away)); + + // "Application Hooks" + session_loaded( s ); + session->Exported.connect( mem_fun( *this, &OSC::session_exported ) ); } void @@ -417,6 +424,21 @@ OSC::session_going_away () session = 0; } +// "Application Hook" Handlers // +void +OSC::session_loaded( Session& s ) { + lo_address listener = lo_address_new( NULL, "7770" ); + lo_send( listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str() ); +} + +void +OSC::session_exported( std::string path, std::string name ) { + lo_address listener = lo_address_new( NULL, "7770" ); + lo_send( listener, "/session/exported", "ss", path.c_str(), name.c_str() ); +} + +// end "Application Hook" Handlers // + /* path callbacks */ int diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index ca4c51fa97..2163ba5cc0 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -1115,8 +1115,7 @@ Panner::set_state (const XMLNode& node) /* automation path is relative */ - automation_path = _session.automation_dir(); - automation_path += prop->value (); + automation_path = Glib::build_filename(_session.automation_dir(), prop->value ()); } return 0; @@ -1416,11 +1415,8 @@ Panner::distribute (BufferSet& inbufs, BufferSet& outbufs, nframes_t start_frame void Panner::set_name (string str) { - automation_path = _session.automation_dir(); - automation_path += _session.snap_name(); - automation_path += "-pan-"; - automation_path += legalize_for_path (str); - automation_path += ".automation"; + automation_path = Glib::build_filename(_session.automation_dir(), + _session.snap_name() + "-pan-" + legalize_for_path (str) + ".automation"); } int diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index 3d218448dd..c52a027915 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -241,3 +241,22 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type) return PluginPtr ((Plugin*) 0); } +ChanCount +Plugin::output_streams () const +{ + /* LADSPA & VST should not get here because they do not + return "infinite" i/o counts. + */ + return ChanCount::ZERO; +} + +ChanCount +Plugin::input_streams () const +{ + /* LADSPA & VST should not get here because they do not + return "infinite" i/o counts. + */ + return ChanCount::ZERO; +} + + diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 26d344dee4..f44a5df003 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -162,19 +162,34 @@ PluginInsert::auto_state_changed (Parameter which) ChanCount PluginInsert::output_streams() const { - if (_configured) - return output_for_input_configuration(_configured_input); - else - return natural_output_streams(); + ChanCount out = _plugins.front()->get_info()->n_outputs; + + if (out == ChanCount::INFINITE) { + + return _plugins.front()->output_streams (); + + } else { + + out.set_audio (out.n_audio() * _plugins.size()); + out.set_midi (out.n_midi() * _plugins.size()); + + return out; + } } ChanCount PluginInsert::input_streams() const { - if (_configured) - return _configured_input; - else - return natural_input_streams(); + ChanCount in = _plugins[0]->get_info()->n_inputs; + + if (in == ChanCount::INFINITE) { + return _plugins[0]->input_streams (); + } else { + in.set_audio (in.n_audio() * _plugins.size()); + in.set_midi (in.n_midi() * _plugins.size()); + + return in; + } } ChanCount @@ -473,31 +488,42 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other) bool PluginInsert::configure_io (ChanCount in, ChanCount out) { - ChanCount matching_out = output_for_input_configuration(out); - if (matching_out != out) { - _configured = false; + if (set_count (count_for_configuration (in, out)) < 0) { + return false; + } + + /* if we're running replicated plugins, each plugin has + the same i/o configuration and we may need to announce how many + output streams there are. + + if we running a single plugin, we need to configure it. + */ + + if (_plugins.front()->configure_io (in, out) < 0) { return false; - } else { - bool success = set_count (count_for_configuration(in, out)); - if (success) - Processor::configure_io(in, out); - return success; } + + return Processor::configure_io (in, out); } bool -PluginInsert::can_support_input_configuration (ChanCount in) const +PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const { + if (_plugins.front()->reconfigurable_io()) { + /* plugin has flexible I/O, so delegate to it */ + return _plugins.front()->can_support_io_configuration (in, out); + } + ChanCount outputs = _plugins[0]->get_info()->n_outputs; ChanCount inputs = _plugins[0]->get_info()->n_inputs; - /* see output_for_input_configuration below */ if ((inputs.n_total() == 0) || (inputs.n_total() == 1 && outputs == inputs) || (inputs.n_total() == 1 && outputs == inputs && ((inputs.n_audio() == 0 && in.n_audio() == 0) || (inputs.n_midi() == 0 && in.n_midi() == 0))) || (inputs == in)) { + out = outputs; return true; } @@ -513,60 +539,31 @@ PluginInsert::can_support_input_configuration (ChanCount in) const } } - if (can_replicate && (in.n_total() % inputs.n_total() == 0)) { - return true; - } else { + if (!can_replicate || (in.n_total() % inputs.n_total() != 0)) { return false; } -} - -ChanCount -PluginInsert::output_for_input_configuration (ChanCount in) const -{ - ChanCount outputs = _plugins[0]->get_info()->n_outputs; - ChanCount inputs = _plugins[0]->get_info()->n_inputs; if (inputs.n_total() == 0) { /* instrument plugin, always legal, but throws away any existing streams */ - return outputs; - } - - if (inputs.n_total() == 1 && outputs == inputs + out = outputs; + } else if (inputs.n_total() == 1 && outputs == inputs && ((inputs.n_audio() == 0 && in.n_audio() == 0) - || (inputs.n_midi() == 0 && in.n_midi() == 0))) { - /* mono plugin, replicate as needed to match in */ - return in; - } - - if (inputs == in) { + || (inputs.n_midi() == 0 && in.n_midi() == 0))) { + /* mono, single-typed plugin, replicate as needed to match in */ + out = in; + } else if (inputs == in) { /* exact match */ - return outputs; - } - - bool can_replicate = true; - - /* if number of inputs is a factor of the requested input - configuration for every type, we can replicate. - */ - for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - if (inputs.get(*t) >= in.get(*t) || (in.get(*t) % inputs.get(*t) != 0)) { - can_replicate = false; - break; - } - } - - if (can_replicate && (inputs.n_total() % in.n_total() == 0)) { - ChanCount output; - + out = outputs; + } else { + /* replicate - note that we've already verified that + the replication count is constant across all data types. + */ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - output.set(*t, outputs.get(*t) * (in.get(*t) / inputs.get(*t))); + out.set (*t, outputs.get(*t) * (in.get(*t) / inputs.get(*t))); } - - return output; } - - /* sorry */ - return ChanCount(); + + return true; } /* Number of plugin instances required to support a given channel configuration. @@ -575,6 +572,12 @@ PluginInsert::output_for_input_configuration (ChanCount in) const int32_t PluginInsert::count_for_configuration (ChanCount in, ChanCount out) const { + if (_plugins.front()->reconfigurable_io()) { + /* plugin has flexible I/O, so the answer is always 1 */ + /* this could change if we ever decide to replicate AU's */ + return 1; + } + // FIXME: take 'out' into consideration ChanCount outputs = _plugins[0]->get_info()->n_outputs; diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 6ff780a25f..e7c2aecd2d 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -24,13 +24,17 @@ #include <cstdio> #include <lrdf.h> #include <dlfcn.h> +#include <cstdlib> +#include <fstream> #ifdef VST_SUPPORT #include <fst.h> #include <pbd/basename.h> -#include <string.h> +#include <cstring> #endif // VST_SUPPORT +#include <glibmm/miscutils.h> + #include <pbd/pathscanner.h> #include <ardour/ladspa.h> @@ -38,6 +42,7 @@ #include <ardour/plugin_manager.h> #include <ardour/plugin.h> #include <ardour/ladspa_plugin.h> +#include <ardour/filesystem_paths.h> #ifdef HAVE_SLV2 #include <slv2/slv2.h> @@ -50,6 +55,7 @@ #ifdef HAVE_AUDIOUNITS #include <ardour/audio_unit.h> +#include <Carbon/Carbon.h> #endif #include <pbd/error.h> @@ -59,6 +65,7 @@ using namespace ARDOUR; using namespace PBD; +using namespace std; PluginManager* PluginManager::_manager = 0; @@ -67,6 +74,16 @@ PluginManager::PluginManager () char* s; string lrdf_path; + load_favorites (); + +#ifdef GTKOSX + ProcessSerialNumber psn = { 0, kCurrentProcess }; + OSStatus returnCode = TransformProcessType(& psn, kProcessTransformToForegroundApplication); + if( returnCode != 0) { + error << _("Cannot become GUI app") << endmsg; + } +#endif + if ((s = getenv ("LADSPA_RDF_PATH"))){ lrdf_path = s; } @@ -487,3 +504,107 @@ PluginManager::vst_discover (string path) } #endif // VST_SUPPORT + +bool +PluginManager::is_a_favorite_plugin (const PluginInfoPtr& pi) +{ + FavoritePlugin fp (pi->type, pi->unique_id); + return find (favorites.begin(), favorites.end(), fp) != favorites.end(); +} + +void +PluginManager::save_favorites () +{ + ofstream ofs; + sys::path path = user_config_directory(); + path /= "favorite_plugins"; + + ofs.open (path.to_string().c_str(), ios_base::openmode (ios::out|ios::trunc)); + + if (!ofs) { + return; + } + + for (FavoritePluginList::iterator i = favorites.begin(); i != favorites.end(); ++i) { + switch ((*i).type) { + case LADSPA: + ofs << "LADSPA"; + break; + case AudioUnit: + ofs << "AudioUnit"; + break; + case LV2: + ofs << "LV2"; + break; + case VST: + ofs << "VST"; + break; + } + + ofs << ' ' << (*i).unique_id << endl; + } + + ofs.close (); +} + +void +PluginManager::load_favorites () +{ + sys::path path = user_config_directory(); + path /= "favorite_plugins"; + ifstream ifs (path.to_string().c_str()); + + if (!ifs) { + return; + } + + std::string stype; + std::string id; + PluginType type; + + while (ifs) { + + ifs >> stype; + if (!ifs) { + break; + + } + ifs >> id; + if (!ifs) { + break; + } + + if (stype == "LADSPA") { + type = LADSPA; + } else if (stype == "AudioUnit") { + type = AudioUnit; + } else if (stype == "LV2") { + type = LV2; + } else if (stype == "VST") { + type = VST; + } else { + error << string_compose (_("unknown favorite plugin type \"%1\" - ignored"), stype) + << endmsg; + continue; + } + + add_favorite (type, id); + } + + ifs.close (); +} + +void +PluginManager::add_favorite (PluginType t, string id) +{ + FavoritePlugin fp (t, id); + pair<FavoritePluginList::iterator,bool> res = favorites.insert (fp); + cerr << "Added " << t << " " << id << " success ? " << res.second << endl; +} + +void +PluginManager::remove_favorite (PluginType t, string id) +{ + FavoritePlugin fp (t, id); + favorites.erase (fp); +} diff --git a/libs/ardour/po/sv_SE.po b/libs/ardour/po/sv_SE.po index ddc7f108bb..58be548f8e 100644 --- a/libs/ardour/po/sv_SE.po +++ b/libs/ardour/po/sv_SE.po @@ -1972,6 +1972,10 @@ msgstr "Fogredigering" msgid "Slide Edit" msgstr "Glidredigering" +#: libs/ardour/utils.cc:372 libs/ardour/utils.cc:388 +msgid "Lock Edit" +msgstr "LÃ¥st redigering" + #: libs/ardour/utils.cc:309 msgid "programming error: unknown edit mode string \"%1\"" msgstr "" diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc index e14835b083..8c33d989dd 100644 --- a/libs/ardour/port_insert.cc +++ b/libs/ardour/port_insert.cc @@ -173,43 +173,12 @@ PortInsert::signal_latency() const } bool -PortInsert::can_support_input_configuration (ChanCount in) const -{ - if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) { - - /* not configured yet */ - - return true; /* we can support anything the first time we're asked */ - - } else { - - /* the "input" config for a port insert corresponds to how - many output ports it will have. - */ - - if (_io->output_maximum() == in) { - - return true; - } - } - - return false; -} - -ChanCount -PortInsert::output_for_input_configuration (ChanCount in) const -{ - return in; -} - -bool PortInsert::configure_io (ChanCount in, ChanCount out) { /* do not allow configuration to be changed outside the range of the last request config. or something like that. */ - /* this is a bit odd: the number of inputs we are required to handle corresponds @@ -224,12 +193,11 @@ PortInsert::configure_io (ChanCount in, ChanCount out) _io->set_input_maximum (out); _io->set_input_minimum (out); - bool success = (_io->ensure_io (out, in, false, this) == 0); - - if (success) - return Processor::configure_io(in, out); - else + if (_io->ensure_io (out, in, false, this) != 0) { return false; + } + + return Processor::configure_io (in, out); } ChanCount diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc index cea33fbe32..486a75703b 100644 --- a/libs/ardour/processor.cc +++ b/libs/ardour/processor.cc @@ -272,3 +272,16 @@ Processor::set_state (const XMLNode& node) return 0; } +bool +Processor::configure_io (ChanCount in, ChanCount out) +{ + /* this class assumes static output stream count. + Derived classes must override, and must set "out" + to reflect "in" before calling this. + */ + + _configured_input = in; + _configured = true; + + return true; +} diff --git a/libs/ardour/rb_effect.cc b/libs/ardour/rb_effect.cc index 4daf5cb33a..9d8ac311b7 100644 --- a/libs/ardour/rb_effect.cc +++ b/libs/ardour/rb_effect.cc @@ -74,21 +74,89 @@ RBEffect::run (boost::shared_ptr<AudioRegion> region) nframes_t pos = 0; int avail = 0; - // note: this_time_fraction is a ratio of original length. 1.0 = no change, - // 0.5 is half as long, 2.0 is twice as long, etc. + cerr << "RBEffect: source region: position = " << region->position() + << ", start = " << region->start() + << ", length = " << region->length() + << ", ancestral_start = " << region->ancestral_start() + << ", ancestral_length = " << region->ancestral_length() + << ", stretch " << region->stretch() + << ", shift " << region->shift() << endl; + + /* + We have two cases to consider: + + 1. The region has not been stretched before. + + In this case, we just want to read region->length() frames + from region->start(). + + We will create a new region of region->length() * + tsr.time_fraction frames. The new region will have its + start set to 0 (because it has a new audio file that begins + at the start of the stretched area) and its ancestral_start + set to region->start() (so that we know where to begin + reading if we want to stretch it again). + + 2. The region has been stretched before. + + The region starts at region->start() frames into its + (possibly previously stretched) source file. But we don't + want to read from its source file; we want to read from the + file it was originally stretched from. + + The region's source begins at region->ancestral_start() + frames into its master source file. Thus, we need to start + reading at region->ancestral_start() + (region->start() / + region->stretch()) frames into the master source. This + value will also become the ancestral_start for the new + region. + + We cannot use region->ancestral_length() to establish how + many frames to read, because it won't be up to date if the + region has been trimmed since it was last stretched. We + must read region->length() / region->stretch() frames and + stretch them by tsr.time_fraction * region->stretch(), for + a new region of region->length() * tsr.time_fraction + frames. + + Case 1 is of course a special case of 2, where + region->ancestral_start() == 0 and region->stretch() == 1. + + When we ask to read from a region, we supply a position on + the global timeline. The read function calculates the + offset into the source as (position - region->position()) + + region->start(). This calculation is used regardless of + whether we are reading from a master or + previously-stretched region. In order to read from a point + n frames into the master source, we need to provide n - + region->start() + region->position() as our position + argument to master_read_at(). + + Note that region->ancestral_length() is not used. + + I hope this is clear. + */ + + double stretch = region->stretch() * tsr.time_fraction; + double shift = region->shift() * tsr.pitch_fraction; - double this_time_fraction = tsr.time_fraction * region->stretch (); - double this_pitch_fraction = tsr.pitch_fraction * region->shift (); + nframes_t read_start = region->ancestral_start() + + nframes_t(region->start() / (double)region->stretch()); - RubberBandStretcher stretcher (session.frame_rate(), region->n_channels(), - (RubberBandStretcher::Options) tsr.opts, - this_time_fraction, this_pitch_fraction); + nframes_t read_duration = + nframes_t(region->length() / (double)region->stretch()); + + uint32_t channels = region->n_channels(); + + RubberBandStretcher stretcher + (session.frame_rate(), channels, + (RubberBandStretcher::Options) tsr.opts, stretch, shift); tsr.progress = 0.0f; tsr.done = false; - uint32_t channels = region->n_channels(); - nframes_t duration = region->ancestral_length(); + stretcher.setExpectedInputDuration(read_duration); + stretcher.setDebugLevel(1); stretcher.setExpectedInputDuration(duration); stretcher.setDebugLevel(1); @@ -97,14 +165,14 @@ RBEffect::run (boost::shared_ptr<AudioRegion> region) digits just to disambiguate close but not identical FX */ - if (this_time_fraction == 1.0) { - snprintf (suffix, sizeof (suffix), "@%d", (int) floor (this_pitch_fraction * 100.0f)); - } else if (this_pitch_fraction == 1.0) { - snprintf (suffix, sizeof (suffix), "@%d", (int) floor (this_time_fraction * 100.0f)); + if (stretch == 1.0) { + snprintf (suffix, sizeof (suffix), "@%d", (int) floor (shift * 100.0f)); + } else if (shift == 1.0) { + snprintf (suffix, sizeof (suffix), "@%d", (int) floor (stretch * 100.0f)); } else { snprintf (suffix, sizeof (suffix), "@%d-%d", - (int) floor (this_time_fraction * 100.0f), - (int) floor (this_pitch_fraction * 100.0f)); + (int) floor (stretch * 100.0f), + (int) floor (shift * 100.0f)); } /* create new sources */ @@ -131,22 +199,26 @@ RBEffect::run (boost::shared_ptr<AudioRegion> region) done = 0; try { - while (pos < duration && !tsr.cancel) { + while (pos < read_duration && !tsr.cancel) { nframes_t this_read = 0; for (uint32_t i = 0; i < channels; ++i) { this_read = 0; + nframes_t this_time; + this_time = min(bufsize, read_duration - pos); - this_time = min(bufsize, duration - pos); - + nframes_t this_position; + this_position = read_start + pos - + region->start() + region->position(); + this_read = region->master_read_at (buffers[i], buffers[i], gain_buffer, - pos + region->position(), + this_position, this_time, i); @@ -161,15 +233,15 @@ RBEffect::run (boost::shared_ptr<AudioRegion> region) pos += this_read; done += this_read; - tsr.progress = ((float) done / duration) * 0.25; + tsr.progress = ((float) done / read_duration) * 0.25; - stretcher.study(buffers, this_read, pos == duration); + stretcher.study(buffers, this_read, pos == read_duration); } done = 0; pos = 0; - while (pos < duration && !tsr.cancel) { + while (pos < read_duration && !tsr.cancel) { nframes_t this_read = 0; @@ -177,14 +249,17 @@ RBEffect::run (boost::shared_ptr<AudioRegion> region) this_read = 0; nframes_t this_time; - - this_time = min(bufsize, duration - pos); + this_time = min(bufsize, read_duration - pos); + + nframes_t this_position; + this_position = read_start + pos - + region->start() + region->position(); this_read = region->master_read_at (buffers[i], buffers[i], gain_buffer, - pos + region->position(), + this_position, this_time, i); @@ -199,9 +274,9 @@ RBEffect::run (boost::shared_ptr<AudioRegion> region) pos += this_read; done += this_read; - tsr.progress = 0.25 + ((float) done / duration) * 0.75; + tsr.progress = 0.25 + ((float) done / read_duration) * 0.75; - stretcher.process(buffers, this_read, pos == duration); + stretcher.process(buffers, this_read, pos == read_duration); int avail = 0; @@ -261,10 +336,11 @@ RBEffect::run (boost::shared_ptr<AudioRegion> region) for (vector<boost::shared_ptr<AudioRegion> >::iterator x = results.begin(); x != results.end(); ++x) { - (*x)->set_ancestral_data (region->ancestral_start(), - region->ancestral_length(), - this_time_fraction, - this_pitch_fraction ); + + (*x)->set_ancestral_data (read_start, + read_duration, + stretch, + shift); (*x)->set_master_sources (region->get_master_sources()); } diff --git a/libs/ardour/recent_sessions.cc b/libs/ardour/recent_sessions.cc index 9b8668dd88..d7f5ad132f 100644 --- a/libs/ardour/recent_sessions.cc +++ b/libs/ardour/recent_sessions.cc @@ -22,7 +22,11 @@ #include <unistd.h> #include <fstream> #include <algorithm> + +#include <glibmm/miscutils.h> + #include <pbd/error.h> + #include <ardour/configuration.h> #include <ardour/filesystem_paths.h> #include <ardour/recent_sessions.h> diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index a6d153f359..6676222b54 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -185,6 +185,7 @@ Region::Region (boost::shared_ptr<const Region> other, nframes_t offset, nframes _sync_position = other->_sync_position; } + for (SourceList::const_iterator i = other->_master_sources.begin(); i != other->_master_sources.end(); ++i) { if (unique_srcs.find (*i) == unique_srcs.end()) { (*i)->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), (*i))); @@ -388,6 +389,7 @@ Region::set_name (const std::string& str) void Region::set_length (nframes_t len, void *src) { + //cerr << "Region::set_length() len = " << len << endl; if (_flags & Locked) { return; } diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc index 84d8167240..88925a7f16 100644 --- a/libs/ardour/region_factory.cc +++ b/libs/ardour/region_factory.cc @@ -72,7 +72,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region) { boost::shared_ptr<const AudioRegion> ar; boost::shared_ptr<const MidiRegion> mr; - + if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) { boost::shared_ptr<Region> ret (new AudioRegion (ar)); /* pure copy constructor - no CheckNewRegion emitted */ @@ -101,7 +101,11 @@ boost::shared_ptr<Region> RegionFactory::create (Session& session, XMLNode& node, bool yn) { boost::shared_ptr<Region> r = session.XMLRegionFactory (node, yn); - CheckNewRegion (r); + + if (r) { + CheckNewRegion (r); + } + return r; } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index e655efedb2..638c026056 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -813,7 +813,7 @@ Route::set_mute (bool yn, void *src) int Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err) { - ChanCount old_rmo = processor_max_outs; + ChanCount old_pmo = processor_max_outs; if (!_session.engine().connected()) { return 1; @@ -827,8 +827,15 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* //processor->set_default_type(_default_type); + _processors.push_back (processor); + + if (_reset_processor_counts (err)) { + _processors.pop_back (); + _reset_processor_counts (0); // it worked before we tried to add it ... + return -1; + } + if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) { - pi->set_count (1); if (pi->natural_input_streams() == ChanCount::ZERO) { /* generator plugin */ @@ -841,15 +848,22 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* // Set up processor list channels. This will set processor->[input|output]_streams(), // configure redirect ports properly, etc. - if (_reset_plugin_counts (err)) { + if (_reset_processor_counts (err)) { _processors.pop_back (); - _reset_plugin_counts (0); // it worked before we tried to add it ... + _reset_processor_counts (0); // it worked before we tried to add it ... return -1; } // Ensure peak vector sizes before the plugin is activated - ChanCount potential_max_streams = max(processor->input_streams(), processor->output_streams()); - _meter->configure_io(potential_max_streams, potential_max_streams); + + ChanCount potential_max_streams; + + potential_max_streams.set (DataType::AUDIO, max (processor->input_streams().n_audio(), + processor->output_streams().n_audio())); + potential_max_streams.set (DataType::MIDI, max (processor->input_streams().n_midi(), + processor->output_streams().n_midi())); + + _meter->configure_io (potential_max_streams, potential_max_streams); processor->activate (); processor->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false)); @@ -857,7 +871,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* _user_latency = 0; } - if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) { + if (processor_max_outs != old_pmo || old_pmo == ChanCount::ZERO) { reset_panner (); } @@ -869,7 +883,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* int Route::add_processors (const ProcessorList& others, ProcessorStreams* err) { - ChanCount old_rmo = processor_max_outs; + ChanCount old_pmo = processor_max_outs; if (!_session.engine().connected()) { return 1; @@ -896,14 +910,14 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err) } // Ensure peak vector sizes before the plugin is activated - _meter->configure_io(potential_max_streams, potential_max_streams); + _meter->configure_io (potential_max_streams, potential_max_streams); _processors.push_back (*i); - if (_reset_plugin_counts (err)) { + if (_reset_processor_counts (err)) { ++existing_end; _processors.erase (existing_end, _processors.end()); - _reset_plugin_counts (0); // it worked before we tried to add it ... + _reset_processor_counts (0); // it worked before we tried to add it ... return -1; } @@ -914,7 +928,7 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err) _user_latency = 0; } - if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) { + if (processor_max_outs != old_pmo || old_pmo == ChanCount::ZERO) { reset_panner (); } @@ -1064,7 +1078,7 @@ Route::pre_fader_streams() const void Route::clear_processors (Placement p) { - const ChanCount old_rmo = processor_max_outs; + const ChanCount old_pmo = processor_max_outs; if (!_session.engine().connected()) { return; @@ -1088,7 +1102,7 @@ Route::clear_processors (Placement p) } /* FIXME: can't see how this test can ever fire */ - if (processor_max_outs != old_rmo) { + if (processor_max_outs != old_pmo) { reset_panner (); } @@ -1100,7 +1114,7 @@ Route::clear_processors (Placement p) int Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err) { - ChanCount old_rmo = processor_max_outs; + ChanCount old_pmo = processor_max_outs; if (!_session.engine().connected()) { return 1; @@ -1118,7 +1132,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream ProcessorList::iterator tmp; - /* move along, see failure case for reset_plugin_counts() + /* move along, see failure case for reset_processor_counts() where we may need to reprocessor the processor. */ @@ -1152,30 +1166,29 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream return 1; } - if (_reset_plugin_counts (err)) { + if (_reset_processor_counts (err)) { /* get back to where we where */ _processors.insert (i, processor); /* we know this will work, because it worked before :) */ - _reset_plugin_counts (0); + _reset_processor_counts (0); return -1; } - bool foo = false; + _have_internal_generator = false; for (i = _processors.begin(); i != _processors.end(); ++i) { boost::shared_ptr<PluginInsert> pi; if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) { if (pi->is_generator()) { - foo = true; + _have_internal_generator = true; + break; } } } - - _have_internal_generator = foo; } - if (old_rmo != processor_max_outs) { + if (old_pmo != processor_max_outs) { reset_panner (); } @@ -1186,27 +1199,32 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream } int -Route::reset_plugin_counts (ProcessorStreams* err) +Route::reset_processor_counts (ProcessorStreams* err) { Glib::RWLock::WriterLock lm (_processor_lock); - return _reset_plugin_counts (err); + return _reset_processor_counts (err); } int -Route::_reset_plugin_counts (ProcessorStreams* err) +Route::_reset_processor_counts (ProcessorStreams* err) { ProcessorList::iterator r; - map<Placement,list<ProcessorCount> > processor_map; - ChanCount initial_streams; - ChanCount post_fader_input; + uint32_t insert_cnt = 0; + uint32_t send_cnt = 0; + map<Placement,list<ProcessorCount> > proc_map; + ProcessorList::iterator prev; + ChanCount initial_streams = n_inputs (); + ChanCount previous_initial_streams = n_inputs (); int ret = -1; + uint32_t max_audio = 0; + uint32_t max_midi = 0; - /* Process each placement in order, checking to see if we - can really do what has been requested. - */ + processor_max_outs.reset (); - /* divide processors up by placement so we get the signal flow + /* Step 1: build a map that links each insert to an in/out channel count + + Divide inserts up by placement so we get the signal flow properly modelled. we need to do this because the _processors list is not sorted by placement, and because other reasons may exist now or in the future for this separate treatment. @@ -1216,60 +1234,146 @@ Route::_reset_plugin_counts (ProcessorStreams* err) for (r = _processors.begin(); r != _processors.end(); ++r) { - boost::shared_ptr<Processor> processor; + boost::shared_ptr<PluginInsert> plugin_insert; + boost::shared_ptr<PortInsert> port_insert; + + if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert>(*r)) != 0) { + + ++insert_cnt; + proc_map[(*r)->placement()].push_back (ProcessorCount (*r)); + + /* reset plugin counts back to one for now so + that we have a predictable, controlled + state to try to configure. + */ - if ((processor = boost::dynamic_pointer_cast<Processor>(*r)) != 0) { - processor_map[processor->placement()].push_back (ProcessorCount (processor)); + plugin_insert->set_count (1); + + } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert>(*r)) != 0) { + + ++insert_cnt; + proc_map[(*r)->placement()].push_back (ProcessorCount (*r)); + + } else if (boost::dynamic_pointer_cast<Send> (*r) != 0) { + ++send_cnt; } } + if (insert_cnt == 0) { + if (send_cnt) { + goto recompute; + } else { + ret = 0; + goto streamcount; + } + } + + /* Now process each placement in order, checking to see if we + can really do what has been requested. + */ + /* A: PreFader */ - if ( ! check_some_plugin_counts (processor_map[PreFader], n_inputs (), err)) { + if (check_some_processor_counts (proc_map[PreFader], n_inputs (), err)) { goto streamcount; } - post_fader_input = (err ? err->count : n_inputs()); + if (!proc_map[PreFader].empty()) { + previous_initial_streams = n_inputs (); + for (list<ProcessorCount>::iterator i = proc_map[PreFader].begin(); i != proc_map[PreFader].end(); i++) { + if (i->processor->can_support_io_configuration (previous_initial_streams, initial_streams) < 0) { + goto streamcount; + } + previous_initial_streams = initial_streams; + } + } /* B: PostFader */ - if ( ! check_some_plugin_counts (processor_map[PostFader], post_fader_input, err)) { + if (check_some_processor_counts (proc_map[PostFader], initial_streams, err)) { goto streamcount; } + if (!proc_map[PostFader].empty()) { + for (list<ProcessorCount>::iterator i = proc_map[PostFader].begin(); i != proc_map[PostFader].end(); i++) { + if (i->processor->can_support_io_configuration (previous_initial_streams, initial_streams) < 0) { + goto streamcount; + } + previous_initial_streams = initial_streams; + } + } + /* OK, everything can be set up correctly, so lets do it */ - apply_some_plugin_counts (processor_map[PreFader]); - apply_some_plugin_counts (processor_map[PostFader]); + apply_some_processor_counts (proc_map[PreFader]); + apply_some_processor_counts (proc_map[PostFader]); /* recompute max outs of any processor */ ret = 0; - streamcount: - processor_max_outs.reset(); + recompute: - for (r = _processors.begin(); r != _processors.end(); ++r) { - processor_max_outs = max ((*r)->output_streams (), processor_max_outs); + processor_max_outs.reset (); + prev = _processors.end(); + + for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) { + boost::shared_ptr<Send> s; + + if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) { + if (r == _processors.begin()) { + s->expect_inputs (n_inputs()); + } else { + s->expect_inputs ((*prev)->output_streams()); + } + + } else { + + /* don't pay any attention to send output configuration, since it doesn't + affect the route. + */ + + max_audio = max ((*r)->output_streams ().n_audio(), max_audio); + max_midi = max ((*r)->output_streams ().n_midi(), max_midi); + } } + processor_max_outs.set (DataType::AUDIO, max_audio); + processor_max_outs.set (DataType::MIDI, max_midi); + + /* we're done */ return 0; + + streamcount: + for (r = _processors.begin(); r != _processors.end(); ++r) { + max_audio = max ((*r)->output_streams ().n_audio(), max_audio); + max_midi = max ((*r)->output_streams ().n_midi(), max_midi); + } + + processor_max_outs.set (DataType::AUDIO, max_audio); + processor_max_outs.set (DataType::MIDI, max_midi); + + return ret; } int32_t -Route::apply_some_plugin_counts (list<ProcessorCount>& iclist) +Route::apply_some_processor_counts (list<ProcessorCount>& iclist) { list<ProcessorCount>::iterator i; - + for (i = iclist.begin(); i != iclist.end(); ++i) { - - cerr << "now applying for " << (*i).processor->name() << " in = " << (*i).in.n_audio() << " out = " << (*i).out.n_audio() << endl; - if ((*i).processor->configure_io ((*i).in, (*i).out)) { + ProcessorCount& pc (*i); + + cerr << "now applying for " << (*i).processor->name() << " in = " << pc.in.n_audio() << " out = " << pc.out.n_audio() << endl; + + if (pc.processor->configure_io (pc.in, pc.out)) { return -1; } + /* make sure that however many we have, they are all active */ - (*i).processor->activate (); + + pc.processor->activate (); } return 0; @@ -1281,7 +1385,7 @@ Route::apply_some_plugin_counts (list<ProcessorCount>& iclist) * Otherwise, \a err is set to the output of the list. */ bool -Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err) +Route::check_some_processor_counts (list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err) { list<ProcessorCount>::iterator i; size_t index = 0; @@ -1291,12 +1395,11 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require err->count = required_inputs; } - for (i = iclist.begin(); i != iclist.end(); ++i) { - + for (i = iclist.begin(); i != iclist.end(); ++i, ++index) { cerr << "Checking whether " << (*i).processor->name() << " can support " << required_inputs.n_audio() << " inputs\n"; - if ((*i).processor->can_support_input_configuration (required_inputs) < 0) { + if (!(*i).processor->can_support_io_configuration (required_inputs, (*i).out)) { if (err) { err->index = index; err->count = required_inputs; @@ -1305,20 +1408,7 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require } (*i).in = required_inputs; - (*i).out = (*i).processor->output_for_input_configuration (required_inputs); - - cerr << "config looks like " << (*i).processor->name() << " in = " << (*i).in.n_audio() << " out = " << (*i).out.n_audio() << endl; - required_inputs = (*i).out; - - ++index; - } - - if (err) { - if (!iclist.empty()) { - err->index = index; - err->count = iclist.back().processor->output_for_input_configuration(required_inputs); - } } return true; @@ -1327,7 +1417,7 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require int Route::copy_processors (const Route& other, Placement placement, ProcessorStreams* err) { - ChanCount old_rmo = processor_max_outs; + ChanCount old_pmo = processor_max_outs; ProcessorList to_be_deleted; @@ -1362,7 +1452,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream /* reset plugin stream handling */ - if (_reset_plugin_counts (err)) { + if (_reset_processor_counts (err)) { /* FAILED COPY ATTEMPT: we have to restore order */ @@ -1383,7 +1473,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream /* restore the natural order */ _processors = the_copy; - processor_max_outs = old_rmo; + processor_max_outs = old_pmo; /* we failed, even though things are OK again */ @@ -1397,7 +1487,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream } } - if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) { + if (processor_max_outs != old_pmo || old_pmo == ChanCount::ZERO) { reset_panner (); } @@ -1457,7 +1547,7 @@ Route::sort_processors (ProcessorStreams* err) { ProcessorSorter comparator; Glib::RWLock::WriterLock lm (_processor_lock); - ChanCount old_rmo = processor_max_outs; + ChanCount old_pmo = processor_max_outs; /* the sweet power of C++ ... */ @@ -1465,9 +1555,9 @@ Route::sort_processors (ProcessorStreams* err) _processors.sort (comparator); - if (_reset_plugin_counts (err)) { + if (_reset_processor_counts (err)) { _processors = as_it_was_before; - processor_max_outs = old_rmo; + processor_max_outs = old_pmo; return -1; } } @@ -2334,7 +2424,7 @@ void Route::input_change_handler (IOChange change, void *ignored) { if (change & ConfigurationChanged) { - reset_plugin_counts (0); + reset_processor_counts (0); } } @@ -2346,7 +2436,7 @@ Route::output_change_handler (IOChange change, void *ignored) _control_outs->ensure_io (ChanCount::ZERO, ChanCount(DataType::AUDIO, n_outputs().n_audio()), true, this); } - reset_plugin_counts (0); + reset_processor_counts (0); } } @@ -2540,6 +2630,11 @@ Route::update_total_latency () } } +#undef DEBUG_LATENCY +#ifdef DEBUG_LATENCY + cerr << _name << ": internal redirect latency = " << _own_latency << endl; +#endif + set_port_latency (_own_latency); if (!_user_latency) { @@ -2558,6 +2653,11 @@ Route::update_total_latency () signal_latency_changed (); /* EMIT SIGNAL */ } +#ifdef DEBUG_LATENCY + cerr << _name << ": input latency = " << input_latency() << " total = " + << _own_latency << endl; +#endif + return _own_latency; } diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc index 736a443c72..a80e99a1ee 100644 --- a/libs/ardour/send.cc +++ b/libs/ardour/send.cc @@ -156,13 +156,13 @@ Send::set_metering (bool yn) } bool -Send::can_support_input_configuration (ChanCount in) const +Send::can_support_io_configuration (const ChanCount& in, ChanCount& out_is_ignored) const { if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) { /* not configured yet */ - return true; /* we can support anything the first time we're asked */ + return 1; /* we can support anything the first time we're asked */ } else { @@ -171,42 +171,35 @@ Send::can_support_input_configuration (ChanCount in) const */ if (_io->output_maximum() == in) { - - return true; + return 1; } } - return false; -} - -ChanCount -Send::output_for_input_configuration (ChanCount in) const -{ - // from the internal (Insert) perspective a Send does not modify its input whatsoever - return in; + return -1; } bool Send::configure_io (ChanCount in, ChanCount out) { /* we're transparent no matter what. fight the power. */ - if (out != in) + + if (out != in) { return false; + } _io->set_output_maximum (in); _io->set_output_minimum (in); _io->set_input_maximum (ChanCount::ZERO); _io->set_input_minimum (ChanCount::ZERO); - bool success = _io->ensure_io (ChanCount::ZERO, in, false, this) == 0; - - if (success) { - Processor::configure_io(in, out); - _io->reset_panner(); - return true; - } else { + if (_io->ensure_io (ChanCount::ZERO, in, false, this) != 0) { return false; } + + Processor::configure_io(in, out); + _io->reset_panner(); + + return true; } ChanCount @@ -226,3 +219,11 @@ Send::input_streams() const } +void +Send::expect_inputs (const ChanCount& expected) +{ + if (expected != expected_inputs) { + expected_inputs = expected; + _io->reset_panner (); + } +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 1124b8960f..311e272903 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -115,9 +115,9 @@ sigc::signal<void> Session::SendFeedback; sigc::signal<void> Session::SMPTEOffsetChanged; sigc::signal<void> Session::StartTimeChanged; sigc::signal<void> Session::EndTimeChanged; - sigc::signal<void> Session::AutoBindingOn; sigc::signal<void> Session::AutoBindingOff; +sigc::signal<void, std::string, std::string> Session::Exported; Session::Session (AudioEngine &eng, const string& fullpath, @@ -140,6 +140,7 @@ Session::Session (AudioEngine &eng, diskstreams (new DiskstreamList), routes (new RouteList), auditioner ((Auditioner*) 0), + _total_free_4k_blocks (0), _bundle_xml_node (0), _click_io ((IO*) 0), main_outs (0) @@ -152,8 +153,8 @@ Session::Session (AudioEngine &eng, cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl; - n_physical_outputs = _engine.n_physical_outputs(); - n_physical_inputs = _engine.n_physical_inputs(); + n_physical_outputs = _engine.n_physical_outputs(DataType::AUDIO); + n_physical_inputs = _engine.n_physical_inputs(DataType::AUDIO); first_stage_init (fullpath, snapshot_name); @@ -210,6 +211,7 @@ Session::Session (AudioEngine &eng, midi_requests (16), diskstreams (new DiskstreamList), routes (new RouteList), + _total_free_4k_blocks (0), _bundle_xml_node (0), main_outs (0) @@ -222,8 +224,8 @@ Session::Session (AudioEngine &eng, cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl; - n_physical_outputs = _engine.n_physical_outputs(); - n_physical_inputs = _engine.n_physical_inputs(); + n_physical_outputs = _engine.n_physical_outputs (DataType::AUDIO); + n_physical_inputs = _engine.n_physical_inputs (DataType::AUDIO); if (n_physical_inputs) { n_physical_inputs = max (requested_physical_in, n_physical_inputs); @@ -1086,6 +1088,12 @@ Session::handle_locations_changed (Locations::LocationList& locations) set_loop = true; } + if (location->is_start()) { + start_location = location; + } + if (location->is_end()) { + end_location = location; + } } if (!set_loop) { @@ -1523,16 +1531,16 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many) } } - /* +#if 0 vector<string> physinputs; vector<string> physoutputs; + + _engine.get_physical_outputs (DataType::MIDI, physoutputs); + _engine.get_physical_inputs (DataType::MIDI, physinputs); uint32_t nphysical_in; uint32_t nphysical_out; - - _engine.get_physical_outputs (physoutputs); - _engine.get_physical_inputs (physinputs); - control_id = ntracks() + nbusses() + 1; - */ + control_id = ntracks() + nbusses(); +#endif while (how_many) { @@ -1555,7 +1563,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many) } while (track_id < (UINT_MAX-1)); /* - if (Config->get_input_auto_connect() & AutoConnectPhysical) { + if (Config->get_input_auto_connect() & AutoConnectPhysical) { nphysical_in = min (n_physical_inputs, (uint32_t) physinputs.size()); } else { nphysical_in = 0; @@ -1703,8 +1711,8 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod uint32_t nphysical_in; uint32_t nphysical_out; - _engine.get_physical_outputs (physoutputs); - _engine.get_physical_inputs (physinputs); + _engine.get_physical_outputs (DataType::AUDIO, physoutputs); + _engine.get_physical_inputs (DataType::AUDIO, physinputs); control_id = ntracks() + nbusses() + 1; while (how_many) { @@ -1889,8 +1897,8 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ vector<string> physinputs; vector<string> physoutputs; - _engine.get_physical_outputs (physoutputs); - _engine.get_physical_inputs (physinputs); + _engine.get_physical_outputs (DataType::AUDIO, physoutputs); + _engine.get_physical_inputs (DataType::AUDIO, physinputs); control_id = ntracks() + nbusses() + 1; while (how_many) { @@ -2418,6 +2426,8 @@ Session::get_maximum_extent () const boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) { + if ((*i)->destructive()) //ignore tape tracks when getting max extents + continue; boost::shared_ptr<Playlist> pl = (*i)->playlist(); if ((me = pl->get_maximum_extent()) > max) { max = me; @@ -2509,7 +2519,7 @@ Session::new_region_name (string old) } int -Session::region_name (string& result, string base, bool newlevel) const +Session::region_name (string& result, string base, bool newlevel) { char buf[16]; string subbase; @@ -2521,15 +2531,11 @@ Session::region_name (string& result, string base, bool newlevel) const Glib::Mutex::Lock lm (region_lock); snprintf (buf, sizeof (buf), "%d", (int)regions.size() + 1); - - result = "region."; result += buf; } else { - /* XXX this is going to be slow. optimize me later */ - if (newlevel) { subbase = base; } else { @@ -2543,37 +2549,25 @@ Session::region_name (string& result, string base, bool newlevel) const } - bool name_taken = true; - { Glib::Mutex::Lock lm (region_lock); - for (int n = 1; n < 5000; ++n) { - - result = subbase; - snprintf (buf, sizeof (buf), ".%d", n); - result += buf; + map<string,uint32_t>::iterator x; - name_taken = false; + result = subbase; - for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) { - if (i->second->name() == result) { - name_taken = true; - break; - } - } + if ((x = region_name_map.find (subbase)) == region_name_map.end()) { + result += ".1"; + region_name_map[subbase] = 1; + } else { + x->second++; + snprintf (buf, sizeof (buf), ".%d", x->second); - if (!name_taken) { - break; - } + result += buf; } } - - if (name_taken) { - fatal << string_compose(_("too many regions with names like %1"), base) << endmsg; - /*NOTREACHED*/ - } } + return 0; } @@ -2635,7 +2629,7 @@ Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions) add the region to the region list. */ - set_dirty(); + set_dirty (); if (added) { @@ -2660,6 +2654,8 @@ Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions) 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))); + + update_region_name_map (region); } if (!v.empty()) { @@ -2669,6 +2665,25 @@ Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions) } void +Session::update_region_name_map (boost::shared_ptr<Region> region) +{ + string::size_type last_period = region->name().find_last_of ('.'); + + if (last_period != string::npos && last_period < region->name().length() - 1) { + + string base = region->name().substr (0, last_period); + string number = region->name().substr (last_period+1); + map<string,uint32_t>::iterator x; + + /* note that if there is no number, we get zero from atoi, + which is just fine + */ + + region_name_map[base] = atoi (number); + } +} + +void Session::region_changed (Change what_changed, boost::weak_ptr<Region> weak_region) { boost::shared_ptr<Region> region (weak_region.lock ()); @@ -2681,6 +2696,10 @@ Session::region_changed (Change what_changed, boost::weak_ptr<Region> weak_regio /* relay hidden changes */ RegionHiddenChange (region); } + + if (what_changed & NameChanged) { + update_region_name_map (region); + } } void @@ -4022,11 +4041,11 @@ Session::freeze (InterThreadInfo& itt) return 0; } -int -Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t len, - bool overwrite, vector<boost::shared_ptr<Source> >& srcs, InterThreadInfo& itt) +boost::shared_ptr<Region> +Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end, + bool overwrite, vector<boost::shared_ptr<Source> >& srcs, InterThreadInfo& itt) { - int ret = -1; + boost::shared_ptr<Region> result; boost::shared_ptr<Playlist> playlist; boost::shared_ptr<AudioFileSource> fsource; uint32_t x; @@ -4038,6 +4057,13 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le BufferSet buffers; SessionDirectory sdir(get_best_session_directory_for_new_source ()); const string sound_dir = sdir.sound_path().to_string(); + nframes_t len = end - start; + + if (end <= start) { + error << string_compose (_("Cannot write a range where end <= start (e.g. %1 <= %2)"), + end, start) << endmsg; + return result; + } // any bigger than this seems to cause stack overflows in called functions const nframes_t chunk_size = (128 * 1024)/4; @@ -4142,21 +4168,19 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le /* construct a region to represent the bounced material */ - boost::shared_ptr<Region> aregion = RegionFactory::create (srcs, 0, srcs.front()->length(), - region_name_from_path (srcs.front()->name(), true)); - - ret = 0; + result = RegionFactory::create (srcs, 0, srcs.front()->length(), + region_name_from_path (srcs.front()->name(), true)); } out: - if (ret) { + if (!result) { for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) { boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); if (afs) { afs->mark_for_remove (); } - + (*src)->drop_references (); } @@ -4171,7 +4195,7 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le g_atomic_int_set (&processing_prohibited, 0); - return ret; + return result; } BufferSet& diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index ec5de23caf..eac71fb5d1 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -171,7 +171,8 @@ Session::butler_thread_work () uint32_t err = 0; int32_t bytes; bool compute_io; - struct timeval begin, end; + microseconds_t begin, end; + struct pollfd pfd[1]; bool disk_work_outstanding = false; DiskstreamList::iterator i; @@ -248,7 +249,7 @@ Session::butler_thread_work () bytes = 0; compute_io = true; - gettimeofday (&begin, 0); + begin = get_microseconds(); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader (); @@ -295,17 +296,16 @@ Session::butler_thread_work () } if (compute_io) { - gettimeofday (&end, 0); - - double b = begin.tv_sec + (begin.tv_usec/1000000.0); - double e = end.tv_sec + (end.tv_usec / 1000000.0); - - _read_data_rate = bytes / (e - b); + end = get_microseconds(); + if(end-begin > 0) { + _read_data_rate = (float) bytes / (float) (end - begin); + } else { _read_data_rate = 0; // infinity better + } } bytes = 0; compute_io = true; - gettimeofday (&begin, 0); + begin = get_microseconds(); for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) { // cerr << "write behind for " << (*i)->name () << endl; @@ -349,12 +349,13 @@ Session::butler_thread_work () } if (compute_io) { - gettimeofday (&end, 0); - - double b = begin.tv_sec + (begin.tv_usec/1000000.0); - double e = end.tv_sec + (end.tv_usec / 1000000.0); - - _write_data_rate = bytes / (e - b); + // there are no apparent users for this calculation? + end = get_microseconds(); + if(end-begin > 0) { + _write_data_rate = (float) bytes / (float) (end - begin); + } else { + _write_data_rate = 0; // Well, infinity would be better + } } if (!disk_work_outstanding) { @@ -421,7 +422,7 @@ Session::read_data_rate () const /* disk i/o in excess of 10000MB/sec indicate the buffer cache in action. ignore it. */ - return _read_data_rate > 10485760000.0f ? 0.0f : _read_data_rate; + return _read_data_rate > 10485.7600000f ? 0.0f : _read_data_rate; } float @@ -430,7 +431,7 @@ Session::write_data_rate () const /* disk i/o in excess of 10000MB/sec indicate the buffer cache in action. ignore it. */ - return _write_data_rate > 10485760000.0f ? 0.0f : _write_data_rate; + return _write_data_rate > 10485.7600000f ? 0.0f : _write_data_rate; } uint32_t diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc index e8670e7199..72bc3f23d7 100644 --- a/libs/ardour/session_command.cc +++ b/libs/ardour/session_command.cc @@ -72,7 +72,7 @@ Session::memento_command_factory(XMLNode *n) before = new XMLNode(*n->children().front()); after = new XMLNode(*n->children().back()); child = before; - } + } if (!child) { diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc index 49b6d9b150..0111e4ed0b 100644 --- a/libs/ardour/session_export.cc +++ b/libs/ardour/session_export.cc @@ -254,6 +254,12 @@ ExportSpecification::prepare (nframes_t blocksize, nframes_t frate) output_data = (void*) malloc (sample_bytes * out_samples_max); } + pos = start_frame; + end_frame = end_frame; + total_frames = end_frame - start_frame; + running = true; + do_freewheel = false; /* force a call to ::prepare_to_export() before proceeding to normal operation */ + return 0; } @@ -436,14 +442,10 @@ Session::start_export (ExportSpecification& spec) return -1; } - spec.pos = spec.start_frame; - spec.end_frame = spec.end_frame; - spec.total_frames = spec.end_frame - spec.start_frame; - spec.running = true; - spec.do_freewheel = false; /* force a call to ::prepare_to_export() before proceeding to normal operation */ - spec.freewheel_connection = _engine.Freewheel.connect (sigc::bind (mem_fun (*this, &Session::process_export), &spec)); + cerr << "Start export at pos = " << spec.pos << endl; + return _engine.freewheel (true); } @@ -455,14 +457,14 @@ Session::stop_export (ExportSpecification& spec) spec.freewheel_connection.disconnect (); spec.clear (); /* resets running/stop etc */ + Exported (spec.path, name()); + return 0; } -int -Session::prepare_to_export (ExportSpecification& spec) +int +Session::pre_export () { - int ret = -1; - wait_till_butler_finished (); /* take everyone out of awrite to avoid disasters */ @@ -475,6 +477,27 @@ Session::prepare_to_export (ExportSpecification& spec) } } + /* make sure we are actually rolling */ + + if (get_record_enabled()) { + disable_record (false); + } + + /* no slaving */ + + post_export_slave = Config->get_slave_source (); + post_export_position = _transport_frame; + + Config->set_slave_source (None); + + return 0; +} + +int +Session::prepare_to_export (ExportSpecification& spec) +{ + int ret = -1; + /* get everyone to the right position */ { @@ -490,22 +513,21 @@ Session::prepare_to_export (ExportSpecification& spec) } } - /* make sure we are actually rolling */ + cerr << "Everybdy is at " << spec.start_frame << endl; - if (get_record_enabled()) { - disable_record (false); - } + /* we just did the core part of a locate() call above, but + for the sake of any GUI, put the _transport_frame in + the right place too. + */ + _transport_frame = spec.start_frame; _exporting = true; - - /* no slaving */ - - post_export_slave = Config->get_slave_source (); - post_export_position = _transport_frame; - - Config->set_slave_source (None); - /* get transport ready */ + /* get transport ready. note how this is calling butler functions + from a non-butler thread. we waited for the butler to stop + what it was doing earlier in Session::pre_export() and nothing + since then has re-awakened it. + */ set_transport_speed (1.0, false); butler_transport_work (); @@ -528,6 +550,10 @@ Session::process_export (nframes_t nframes, ExportSpecification* spec) int ret = -1; nframes_t this_nframes; + cerr << "Export process at pos = " << spec->pos << " _exporting = " + << _exporting << " running = " << spec->running << " stop = " + << spec->stop << endl; + /* This is not required to be RT-safe because we are running while freewheeling */ if (spec->do_freewheel == false) { @@ -545,12 +571,14 @@ Session::process_export (nframes_t nframes, ExportSpecification* spec) if (!_exporting) { /* finished, but still freewheeling */ - process_without_events (nframes); + cerr << "\tExport ... not exporting yet, no_roll() for " << nframes <<endl; + no_roll (nframes, 0); return 0; } - + if (!spec->running || spec->stop || (this_nframes = min ((spec->end_frame - spec->pos), nframes)) == 0) { - process_without_events (nframes); + cerr << "\tExport ... not running or at end, no_roll() for " << nframes <<endl; + no_roll (nframes, 0); return stop_export (*spec); } @@ -604,6 +632,8 @@ Session::process_export (nframes_t nframes, ExportSpecification* spec) } } + cerr << "\tprocess " << nframes << endl; + if (spec->process (nframes)) { goto out; } @@ -611,6 +641,8 @@ Session::process_export (nframes_t nframes, ExportSpecification* spec) spec->pos += nframes; spec->progress = 1.0 - (((float) spec->end_frame - spec->pos) / spec->total_frames); + cerr << "\t@ " << spec->pos << " prog = " << spec->progress << endl; + /* and we're good to go */ ret = 0; @@ -629,7 +661,7 @@ Session::process_export (nframes_t nframes, ExportSpecification* spec) } void -Session::finalize_audio_export () +Session::finalize_export () { _engine.freewheel (false); _exporting = false; diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index d6890b31ae..abe802548a 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -867,18 +867,38 @@ Session::maybe_sync_start (nframes_t& nframes, nframes_t& offset) if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) { + /* generate silence up to the sync point, then + adjust nframes + offset to reflect whatever + is left to do. + */ + no_roll (sync_offset, 0); nframes -= sync_offset; offset += sync_offset; waiting_for_sync_offset = false; if (nframes == 0) { - return true; // done + return true; // done, nothing left to process } } else { + + /* sync offset point is not within this process() + cycle, so just generate silence. and don't bother + with any fancy stuff here, just the minimal silence. + */ + + g_atomic_int_inc (&processing_prohibited); no_roll (nframes, 0); - return true; // done + g_atomic_int_dec_and_test (&processing_prohibited); + + if (Config->get_locate_while_waiting_for_sync()) { + if (micro_locate (nframes)) { + /* XXX ERROR !!! XXX */ + } + } + + return true; // done, nothing left to process } return false; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index c228f3c47b..8ebf3ab07b 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -432,8 +432,9 @@ Session::setup_raid_path (string path) AudioFileSource::set_search_path (sound_search_path.to_string ()); SMFSource::set_search_path (midi_search_path.to_string ()); + // reset the round-robin soundfile path thingie - + last_rr_session_dir = session_dirs.begin(); } @@ -1794,6 +1795,43 @@ Session::save_template (string template_name) return 0; } +int +Session::rename_template (string old_name, string new_name) +{ + sys::path old_path (user_template_directory()); + old_path /= old_name + template_suffix; + + sys::path new_path(user_template_directory()); + new_path /= new_name + template_suffix; + + if (sys::exists (new_path)) { + warning << string_compose(_("Template \"%1\" already exists - template not renamed"), + new_path.to_string()) << endmsg; + return -1; + } + + try { + sys::rename (old_path, new_path); + return 0; + } catch (...) { + return -1; + } +} + +int +Session::delete_template (string name) +{ + sys::path path = user_template_directory(); + path /= name + template_suffix; + + try { + sys::remove (path); + return 0; + } catch (...) { + return -1; + } +} + void Session::refresh_disk_space () { @@ -2009,17 +2047,13 @@ Session::XMLNamedSelectionFactory (const XMLNode& node) string Session::automation_dir () const { - string res = _path; - res += "automation/"; - return res; + return Glib::build_filename (_path, "automation"); } string Session::analysis_dir () const { - string res = _path; - res += "analysis/"; - return res; + return Glib::build_filename (_path, "analysis"); } int diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 61a741d0fb..cc94595f8c 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -138,7 +138,7 @@ Session::realtime_stop (bool abort) // FIXME: where should this really be? [DR] //send_full_time_code(); - deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame); + deliver_mmc (MIDI::MachineControl::cmdStop, 0); deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame); if (_transport_speed < 0.0f) { @@ -658,6 +658,25 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, } } +int +Session::micro_locate (nframes_t distance) +{ + boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + if (!(*i)->can_internal_playback_seek (distance)) { + return -1; + } + } + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + (*i)->internal_playback_seek (distance); + } + + _transport_frame += distance; + return 0; +} + void Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop) { @@ -1314,6 +1333,11 @@ Session::update_latency_compensation (bool with_stop, bool abort) _worst_track_latency = 0; +#undef DEBUG_LATENCY +#ifdef DEBUG_LATENCY + cerr << "\n---------------------------------\nUPDATE LATENCY\n"; +#endif + boost::shared_ptr<RouteList> r = routes.reader (); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { @@ -1340,6 +1364,10 @@ Session::update_latency_compensation (bool with_stop, bool abort) _engine.update_total_latencies (); } +#ifdef DEBUG_LATENCY + cerr << "\tworst was " << _worst_track_latency << endl; +#endif + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { (*i)->set_latency_delay (_worst_track_latency); } diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index ab090381b4..b6efe27d36 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -20,15 +20,18 @@ #include <cstring> #include <cerrno> #include <climits> +#include <cstdarg> #include <pwd.h> #include <sys/utsname.h> #include <sys/stat.h> #include <glibmm/miscutils.h> + #include <ardour/sndfilesource.h> #include <ardour/sndfile_helpers.h> #include <ardour/utils.h> +#include <ardour/version.h> #include "i18n.h" @@ -44,6 +47,22 @@ const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSou AudioFileSource::Removable| AudioFileSource::RemovableIfEmpty| AudioFileSource::CanRename); + +static void +snprintf_bounded_null_filled (char* target, size_t target_size, char* fmt, ...) +{ + char buf[target_size+1]; + va_list ap; + + va_start (ap, fmt); + vsnprintf (buf, target_size+1, fmt, ap); + va_end (ap); + + memset (target, 0, target_size); + memcpy (target, buf, target_size); + +} + SndFileSource::SndFileSource (Session& s, const XMLNode& node) : AudioFileSource (s, node) { @@ -140,21 +159,8 @@ SndFileSource::SndFileSource (Session& s, ustring path, SampleFormat sfmt, Heade _broadcast_info = new SF_BROADCAST_INFO; memset (_broadcast_info, 0, sizeof (*_broadcast_info)); - snprintf (_broadcast_info->description, sizeof (_broadcast_info->description), "BWF %s", _name.c_str()); - - struct utsname utsinfo; - - if (uname (&utsinfo)) { - error << string_compose(_("FileSource: cannot get host information for BWF header (%1)"), strerror(errno)) << endmsg; - return; - } - - snprintf (_broadcast_info->originator, sizeof (_broadcast_info->originator), "ardour:%s:%s:%s:%s:%s)", - Glib::get_real_name().c_str(), - utsinfo.nodename, - utsinfo.sysname, - utsinfo.release, - utsinfo.version); + snprintf_bounded_null_filled (_broadcast_info->description, sizeof (_broadcast_info->description), "BWF %s", _name.c_str()); + snprintf_bounded_null_filled (_broadcast_info->originator, sizeof (_broadcast_info->originator), "ardour %s)", Glib::get_real_name().c_str()); _broadcast_info->version = 1; _broadcast_info->time_reference_low = 0; @@ -162,7 +168,7 @@ SndFileSource::SndFileSource (Session& s, ustring path, SampleFormat sfmt, Heade /* XXX do something about this field */ - snprintf (_broadcast_info->umid, sizeof (_broadcast_info->umid), "%s", "fnord"); + snprintf_bounded_null_filled (_broadcast_info->umid, sizeof (_broadcast_info->umid), "%s", "fnord"); /* coding history is added by libsndfile */ @@ -533,25 +539,25 @@ SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow /* random code is 9 digits */ int random_code = random() % 999999999; + + snprintf_bounded_null_filled (_broadcast_info->originator_reference, sizeof (_broadcast_info->originator_reference), "%2s%3s%12s%02d%02d%02d%9d", + Config->get_bwf_country_code().c_str(), + Config->get_bwf_organization_code().c_str(), + bwf_serial_number, + now.tm_hour, + now.tm_min, + now.tm_sec, + random_code); - snprintf (_broadcast_info->originator_reference, sizeof (_broadcast_info->originator_reference), "%2s%3s%12s%02d%02d%02d%9d", - Config->get_bwf_country_code().c_str(), - Config->get_bwf_organization_code().c_str(), - bwf_serial_number, - now.tm_hour, - now.tm_min, - now.tm_sec, - random_code); - - snprintf (_broadcast_info->origination_date, sizeof (_broadcast_info->origination_date), "%4d-%02d-%02d", - 1900 + now.tm_year, - now.tm_mon, - now.tm_mday); + snprintf_bounded_null_filled (_broadcast_info->origination_date, sizeof (_broadcast_info->origination_date), "%4d-%02d-%02d", + 1900 + now.tm_year, + now.tm_mon + 1, // move from 0..11 to 1..12 + now.tm_mday); - snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d:%02d:%02d", - now.tm_hour, - now.tm_min, - now.tm_sec); + snprintf_bounded_null_filled (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d:%02d:%02d", + now.tm_hour, + now.tm_min, + now.tm_sec); /* now update header position taking header offset into account */ diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index 5338997659..0b7c0f3d9e 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -129,10 +129,12 @@ SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks) DataType type = DataType::AUDIO; const XMLProperty* prop = node.property("type"); - if (prop) { - type = DataType(prop->value()); + if (!prop) { + return boost::shared_ptr<Source>(); } + type = DataType (prop->value()); + if (type == DataType::AUDIO) { try { diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 052105cc85..ed52fd70a9 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -104,6 +104,11 @@ Track::update_total_latency () } } +#undef DEBUG_LATENCY +#ifdef DEBUG_LATENCY + cerr << _name << ": internal redirect (final) latency = " << _own_latency << endl; +#endif + set_port_latency (_own_latency); if (old != _own_latency) { diff --git a/libs/ardour/user_bundle.cc b/libs/ardour/user_bundle.cc index 471d823496..b9d115bc40 100644 --- a/libs/ardour/user_bundle.cc +++ b/libs/ardour/user_bundle.cc @@ -23,17 +23,17 @@ ARDOUR::UserBundle::UserBundle (XMLNode const & x, bool i) } } -uint32_t +ARDOUR::ChanCount ARDOUR::UserBundle::nchannels () const { Glib::Mutex::Lock lm (_ports_mutex); - return _ports.size (); + return ChanCount (type(), _ports.size ()); } const ARDOUR::PortList& ARDOUR::UserBundle::channel_ports (uint32_t n) const { - assert (n < nchannels ()); + assert (n < nchannels ().get (type())); Glib::Mutex::Lock lm (_ports_mutex); return _ports[n]; @@ -42,7 +42,7 @@ ARDOUR::UserBundle::channel_ports (uint32_t n) const void ARDOUR::UserBundle::add_port_to_channel (uint32_t c, std::string const & p) { - assert (c < nchannels ()); + assert (c < nchannels ().get (type())); PortsWillChange (c); @@ -57,7 +57,7 @@ ARDOUR::UserBundle::add_port_to_channel (uint32_t c, std::string const & p) void ARDOUR::UserBundle::remove_port_from_channel (uint32_t c, std::string const & p) { - assert (c < nchannels ()); + assert (c < nchannels ().get (type())); PortsWillChange (c); @@ -75,7 +75,7 @@ ARDOUR::UserBundle::remove_port_from_channel (uint32_t c, std::string const & p) bool ARDOUR::UserBundle::port_attached_to_channel (uint32_t c, std::string const & p) const { - assert (c < nchannels ()); + assert (c < nchannels ().get (type())); Glib::Mutex::Lock lm (_ports_mutex); return std::find (_ports[c].begin(), _ports[c].end(), p) != _ports[c].end(); @@ -110,7 +110,7 @@ ARDOUR::UserBundle::set_channels (uint32_t n) void ARDOUR::UserBundle::remove_channel (uint32_t r) { - assert (r < nchannels ()); + assert (r < nchannels ().get (type())); ConfigurationWillChange (); diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index 58443bd005..1906d92b88 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -25,6 +25,7 @@ #include <cmath> #include <cctype> #include <string> +#include <cstring> #include <cerrno> #include <iostream> #include <sys/types.h> diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index 47b5cb4fba..11169a74de 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -20,16 +20,19 @@ #include <algorithm> #include <vector> #include <string> -#include <ctype.h> +#include <cctype> #include <cstdlib> #include <cstdio> // so libraptor doesn't complain #include <cmath> #include <dirent.h> -#include <string.h> // for memmove +#include <cstring> // for memmove #include <sys/stat.h> #include <cerrno> +#include <glibmm/ustring.h> +#include <glibmm/miscutils.h> + #include <lrdf.h> #include <fst.h> @@ -156,13 +159,12 @@ VSTPlugin::get_state() /* save it to a file */ - string path; + Glib::ustring path = Glib::build_filename (get_user_ardour_path (), "vst"); struct stat sbuf; sys::path user_vst_directory(user_config_directory()); user_vst_directory /= "vst"; - path = user_vst_directory.to_string(); if (stat (path.c_str(), &sbuf)) { @@ -187,7 +189,7 @@ VSTPlugin::get_state() return *root; } - path += "something"; + path = Glib::build_filename (path, "something"); /* store information */ diff --git a/libs/cairomm/SConscript b/libs/cairomm/SConscript index 3af7019e52..cb3dfa9c1a 100644 --- a/libs/cairomm/SConscript +++ b/libs/cairomm/SConscript @@ -8,7 +8,7 @@ cairomm_files = glob.glob('cairomm/*.cc') Import('env libraries install_prefix') -cairomm = env.Copy() +cairomm = env.Clone() cairomm.Merge([libraries['cairo']]) cairomm.Append(CXXFLAGS='-DHAVE_CONFIG_H') diff --git a/libs/clearlooks/SConscript b/libs/clearlooks/SConscript index 3b496fb3f1..bd460f971e 100644 --- a/libs/clearlooks/SConscript +++ b/libs/clearlooks/SConscript @@ -19,7 +19,7 @@ libclearlooks_files = [ Import ('env install_prefix') -clearlooks = env.Copy() +clearlooks = env.Clone() clearlooks.Replace(CCFLAGS = ' `pkg-config --cflags gtk+-2.0 cairo` ', LINKFLAGS = ' `pkg-config --libs gtk+-2.0 cairo` ') diff --git a/libs/fst/SConscript b/libs/fst/SConscript index bdffd959b5..576283d73c 100644 --- a/libs/fst/SConscript +++ b/libs/fst/SConscript @@ -8,7 +8,7 @@ import glob fst_src = glob.glob('*.c') Import('env install_prefix') -fst = env.Copy(CC="winegcc") +fst = env.Clone(CC="winegcc") fst.Append (CPPPATH=".") if fst['VST']: diff --git a/libs/glibmm2/SConscript b/libs/glibmm2/SConscript index 66434396a3..bbf65ad228 100644 --- a/libs/glibmm2/SConscript +++ b/libs/glibmm2/SConscript @@ -9,7 +9,7 @@ glibmm2_files = glob.glob('glib/glibmm/*.cc') Import('env libraries install_prefix') -glibmm2 = env.Copy() +glibmm2 = env.Clone() glibmm2.Merge([libraries['sigc2'], libraries['glib2']]) glibmm2.Append(LIBPATH='#libs/glibmm2', CPPPATH='#libs/glibmm2/glib') diff --git a/libs/glibmm2/glib/glibmmconfig.h b/libs/glibmm2/glib/glibmmconfig.h index 4e4bfa308f..140cc376af 100644 --- a/libs/glibmm2/glib/glibmmconfig.h +++ b/libs/glibmm2/glib/glibmmconfig.h @@ -1,4 +1,4 @@ -/* glib/glibmmconfig.h. Generated from glibmmconfig.h.in by configure. */ +/* glib/glibmmconfig.h. Generated by configure. */ #ifndef _GLIBMM_CONFIG_H #define _GLIBMM_CONFIG_H 1 @@ -78,7 +78,7 @@ #ifdef GLIBMM_DLL #if defined(GLIBMM_BUILD) && defined(_WINDLL) /* Do not dllexport as it is handled by gendef on MSVC */ - #define GLIBMM_API + #define GLIBMM_API #elif !defined(GLIBMM_BUILD) #define GLIBMM_API __declspec(dllimport) #else diff --git a/libs/gtkmm2/atk/SConscript b/libs/gtkmm2/atk/SConscript index c1e5fb849e..b1f479c386 100644 --- a/libs/gtkmm2/atk/SConscript +++ b/libs/gtkmm2/atk/SConscript @@ -7,7 +7,7 @@ import glob atkmm_files = glob.glob('atkmm/*.cc') Import('env libraries install_prefix') -atkmm = env.Copy() +atkmm = env.Clone() atkmm.Merge([libraries['glibmm2'], libraries['gtk2'], libraries['sigc2'] ]) libatkmm = atkmm.SharedLibrary('atkmm', atkmm_files) diff --git a/libs/gtkmm2/gdk/SConscript b/libs/gtkmm2/gdk/SConscript index dca82665dc..4155cc74ba 100644 --- a/libs/gtkmm2/gdk/SConscript +++ b/libs/gtkmm2/gdk/SConscript @@ -7,7 +7,7 @@ import glob gdkmm2_files = glob.glob('gdkmm/*.cc') Import('env libraries install_prefix') -gdkmm2 = env.Copy() +gdkmm2 = env.Clone() gdkmm2.Merge([libraries['glibmm2'], libraries['gtk2'], libraries['sigc2'], libraries['pangomm'], libraries['cairomm']]) gdkmm2.Append(CXXFLAGS=["-Ilibs/gtkmm2/gtk", "-DGLIBMM_EXCEPTIONS_ENABLED"]) diff --git a/libs/gtkmm2/gtk/SConscript b/libs/gtkmm2/gtk/SConscript index 32e45a131e..217ce5d48c 100644 --- a/libs/gtkmm2/gtk/SConscript +++ b/libs/gtkmm2/gtk/SConscript @@ -7,7 +7,7 @@ import glob gtkmm2_files = glob.glob('gtkmm/*.cc') Import('env libraries install_prefix') -gtkmm2 = env.Copy() +gtkmm2 = env.Clone() gtkmm2.Merge([libraries['glibmm2'], libraries['gtk2'], libraries['sigc2'], libraries['pangomm'], libraries['atkmm'], libraries['gdkmm2'], libraries['cairomm'], libraries['gtk2-unix-print'] ]) gtkmm2.Append(CXXFLAGS = ['-DGLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED', '-DGLIBMM_PROPERTIES_ENABLED', '-DGLIBMM_EXCEPTIONS_ENABLED']) diff --git a/libs/gtkmm2/pango/SConscript b/libs/gtkmm2/pango/SConscript index 02d75193a0..4b7bae8d1d 100644 --- a/libs/gtkmm2/pango/SConscript +++ b/libs/gtkmm2/pango/SConscript @@ -7,7 +7,7 @@ import glob pangomm_files = glob.glob('pangomm/*.cc') Import('env libraries install_prefix') -pangomm = env.Copy() +pangomm = env.Clone() pangomm.Merge([libraries['glibmm2'], libraries['pango'], libraries['sigc2'], libraries['cairomm'], libraries['cairo'], libraries['pangocairo'] ]) if pangomm['IS_OSX']: diff --git a/libs/gtkmm2ext/SConscript b/libs/gtkmm2ext/SConscript index a0ef88e6d1..3a3bd351d7 100644 --- a/libs/gtkmm2ext/SConscript +++ b/libs/gtkmm2ext/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix libraries i18n') -gtkmm2ext = env.Copy() +gtkmm2ext = env.Clone() gtkmm2ext.Merge ([ libraries['sigc2'], libraries['pbd'], @@ -48,9 +48,7 @@ fastmeter.cc focus_entry.cc grouped_buttons.cc gtk_ui.cc -hexentry.cc idle_adjustment.cc -pathlist.cc pixfader.cc pixscroller.cc popup.cc diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc index a3b2a13bf5..90954e57b3 100644 --- a/libs/gtkmm2ext/barcontroller.cc +++ b/libs/gtkmm2ext/barcontroller.cc @@ -36,7 +36,7 @@ using namespace Gtk; using namespace Gtkmm2ext; BarController::BarController (Gtk::Adjustment& adj, - PBD::Controllable& mc, + boost::shared_ptr<PBD::Controllable> mc, sigc::slot<void,char*,unsigned int> lc) : adjustment (adj), diff --git a/libs/gtkmm2ext/binding_proxy.cc b/libs/gtkmm2ext/binding_proxy.cc index 90f95f82ef..6c60deaa8f 100644 --- a/libs/gtkmm2ext/binding_proxy.cc +++ b/libs/gtkmm2ext/binding_proxy.cc @@ -31,7 +31,7 @@ using namespace Gtkmm2ext; using namespace std; using namespace PBD; -BindingProxy::BindingProxy (Controllable& c) +BindingProxy::BindingProxy (boost::shared_ptr<Controllable> c) : prompter (0), controllable (c), bind_button (2), @@ -65,7 +65,7 @@ bool BindingProxy::button_press_handler (GdkEventButton *ev) { if ((ev->state & bind_statemask) && ev->button == bind_button) { - if (Controllable::StartLearning (&controllable)) { + if (Controllable::StartLearning (controllable.get())) { string prompt = _("operate controller now"); if (prompter == 0) { prompter = new PopUp (Gtk::WIN_POS_MOUSE, 30000, false); @@ -73,7 +73,7 @@ BindingProxy::button_press_handler (GdkEventButton *ev) } prompter->set_text (prompt); prompter->touch (); // shows popup - learning_connection = controllable.LearningFinished.connect (mem_fun (*this, &BindingProxy::learning_finished)); + learning_connection = controllable->LearningFinished.connect (mem_fun (*this, &BindingProxy::learning_finished)); } return true; } @@ -95,7 +95,7 @@ bool BindingProxy::prompter_hiding (GdkEventAny *ev) { learning_connection.disconnect (); - Controllable::StopLearning (&controllable); + Controllable::StopLearning (controllable.get()); return false; } diff --git a/libs/gtkmm2ext/fastmeter.cc b/libs/gtkmm2ext/fastmeter.cc index 63c36558f1..bdd8919d36 100644 --- a/libs/gtkmm2ext/fastmeter.cc +++ b/libs/gtkmm2ext/fastmeter.cc @@ -25,7 +25,7 @@ #include <gtkmm2ext/fastmeter.h> #include <gtkmm2ext/utils.h> #include <gtkmm/style.h> -#include <string.h> +#include <cstring> #define UINT_TO_RGB(u,r,g,b) { (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; } #define UINT_TO_RGBA(u,r,g,b,a) { UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; } diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc index f00c6cd1e1..4ca23b0240 100644 --- a/libs/gtkmm2ext/gtk_ui.cc +++ b/libs/gtkmm2ext/gtk_ui.cc @@ -65,7 +65,6 @@ UI::UI (string namestr, int *argc, char ***argv) : AbstractUI<UIRequest> (namestr, true) { theMain = new Main (argc, argv); - tips = new Tooltips; _active = false; diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h index fe67e9ecec..5e9a6fed90 100644 --- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h +++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h @@ -34,7 +34,7 @@ class BarController : public Gtk::Frame public: typedef sigc::slot<void,char*,unsigned int> LabelCallback; - BarController (Gtk::Adjustment& adj, PBD::Controllable&, LabelCallback lc = LabelCallback()); + BarController (Gtk::Adjustment& adj, boost::shared_ptr<PBD::Controllable>, LabelCallback lc = LabelCallback()); virtual ~BarController () {} @@ -63,7 +63,7 @@ class BarController : public Gtk::Frame /* export this to allow direct connection to button events */ Gtk::Widget& event_widget() { return darea; } - PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); } + boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); } protected: Gtk::Adjustment& adjustment; diff --git a/libs/gtkmm2ext/gtkmm2ext/bindable_button.h b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h index 1cde32c5ba..844dc27d08 100644 --- a/libs/gtkmm2ext/gtkmm2ext/bindable_button.h +++ b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h @@ -32,9 +32,9 @@ namespace PBD { class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton { public: - BindableToggleButton (PBD::Controllable& c) : binding_proxy (c) {} + BindableToggleButton (boost::shared_ptr<PBD::Controllable> c) : binding_proxy (c) {} - explicit BindableToggleButton (PBD::Controllable& c, const std::string &label) + explicit BindableToggleButton (boost::shared_ptr<PBD::Controllable> c, const std::string &label) : Gtkmm2ext::StatefulToggleButton (label), binding_proxy (c) {} virtual ~BindableToggleButton() {} @@ -48,7 +48,8 @@ class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton } } - PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); } + boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); } + private: BindingProxy binding_proxy; }; @@ -56,9 +57,9 @@ class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton class BindableButton : public Gtkmm2ext::StatefulButton { public: - BindableButton (PBD::Controllable& c) : binding_proxy (c) {} + BindableButton (boost::shared_ptr<PBD::Controllable> c) : binding_proxy (c) {} - explicit BindableButton (PBD::Controllable& c, const std::string &label) + explicit BindableButton (boost::shared_ptr<PBD::Controllable> c, const std::string &label) : Gtkmm2ext::StatefulButton (label), binding_proxy (c) {} ~BindableButton() {} @@ -72,7 +73,7 @@ class BindableButton : public Gtkmm2ext::StatefulButton } } - PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); } + boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); } private: BindingProxy binding_proxy; diff --git a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h index dd9b94319d..ecb95bf815 100644 --- a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h +++ b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h @@ -24,6 +24,7 @@ #include <string> #include <gtkmm2ext/popup.h> +#include <boost/shared_ptr.hpp> namespace PBD { class Controllable; @@ -32,7 +33,7 @@ namespace PBD { class BindingProxy : public sigc::trackable { public: - BindingProxy (PBD::Controllable&); + BindingProxy (boost::shared_ptr<PBD::Controllable>); virtual ~BindingProxy(); void set_bind_button_state (guint button, guint statemask); @@ -40,11 +41,11 @@ class BindingProxy : public sigc::trackable bool button_press_handler (GdkEventButton *); - PBD::Controllable* get_controllable() { return &controllable; } - protected: + boost::shared_ptr<PBD::Controllable> get_controllable() { return controllable; } + protected: Gtkmm2ext::PopUp* prompter; - PBD::Controllable& controllable; + boost::shared_ptr<PBD::Controllable> controllable; guint bind_button; guint bind_statemask; sigc::connection learning_connection; diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h index 0c2ff0d798..22ac517672 100644 --- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h +++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h @@ -31,7 +31,6 @@ #include <gtkmm/style.h> #include <gtkmm/textbuffer.h> #include <gtkmm/main.h> -#include <gtkmm/tooltips.h> #include <gdkmm/color.h> #include <pbd/abstract_ui.h> #include <pbd/ringbufferNPT.h> @@ -150,7 +149,6 @@ class UI : public Receiver, public AbstractUI<UIRequest> static pthread_t gui_thread; bool _active; Gtk::Main *theMain; - Gtk::Tooltips *tips; TextViewer *errors; Glib::RefPtr<Gtk::TextBuffer::Tag> error_ptag; Glib::RefPtr<Gtk::TextBuffer::Tag> error_mtag; diff --git a/libs/gtkmm2ext/gtkmm2ext/hexentry.h b/libs/gtkmm2ext/gtkmm2ext/hexentry.h deleted file mode 100644 index 410f54274e..0000000000 --- a/libs/gtkmm2ext/gtkmm2ext/hexentry.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 1999 Paul Barton-Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __gtkmm2ext_hexentry_h__ -#define __gtkmm2ext_hexentry_h__ - -#include <gtkmm.h> - -namespace Gtkmm2ext { - -class HexEntry : public Gtk::Entry - -{ - public: - /* Take a byte-level representation of a series of hexadecimal - values and use them to set the displayed text of the entry. - Eg. if hexbuf[0] = 0xff and hexbuf[1] = 0xa1 and buflen = 2, - then the text will be set to "ff a1". - */ - - void set_hex (unsigned char *hexbuf, unsigned int buflen); - - /* puts byte-level representation of current entry text - into hexbuf, and returns number of bytes written there. - - NOTE: this will release the existing memory pointed to - by hexbuf if buflen indicates that it is not long enough - to hold the new representation, and hexbuf is not zero. - - If the returned length is zero, the contents of hexbuf - are undefined. - */ - - unsigned int get_hex (unsigned char *hexbuf, size_t buflen); - - private: - bool on_key_press_event (GdkEventKey *); -}; - -} /* namespace */ - -#endif /* __gtkmm2ext_hexentry_h__ */ diff --git a/libs/gtkmm2ext/gtkmm2ext/pathlist.h b/libs/gtkmm2ext/gtkmm2ext/pathlist.h deleted file mode 100644 index f4a5973d5a..0000000000 --- a/libs/gtkmm2ext/gtkmm2ext/pathlist.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (C) 2006 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __gtkmm2ext_pathlist_h__ -#define __gtkmm2ext_pathlist_h__ - -#include <vector> -#include <string> - -#include <gtkmm.h> - -namespace Gtkmm2ext { - -class PathList : public Gtk::VBox -{ - public: - PathList (); - ~PathList () {}; - - std::vector<std::string> get_paths (); - void set_paths (std::vector<std::string> paths); - - sigc::signal<void> PathsUpdated; - - protected: - Gtk::Button add_btn; - Gtk::Button subtract_btn; - - void add_btn_clicked (); - void subtract_btn_clicked (); - - private: - struct PathColumns : public Gtk::TreeModel::ColumnRecord { - PathColumns() { add (paths); } - Gtk::TreeModelColumn<std::string> paths; - }; - PathColumns path_columns; - - Glib::RefPtr<Gtk::ListStore> _store; - Gtk::TreeView _view; - - void selection_changed (); -}; - -} // namespace Gtkmm2ext - -#endif // __gtkmm2ext_pathlist_h__ diff --git a/libs/gtkmm2ext/gtkmm2ext/slider_controller.h b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h index 60c8eef660..46f70dacd8 100644 --- a/libs/gtkmm2ext/gtkmm2ext/slider_controller.h +++ b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h @@ -24,6 +24,8 @@ #include <gtkmm2ext/pixfader.h> #include <gtkmm2ext/binding_proxy.h> +#include <boost/shared_ptr.hpp> + namespace Gtkmm2ext { class Pix; } @@ -39,9 +41,9 @@ class SliderController : public Gtkmm2ext::PixFader public: SliderController (Glib::RefPtr<Gdk::Pixbuf> image, Gtk::Adjustment* adj, int orientation, - PBD::Controllable&, + boost::shared_ptr<PBD::Controllable>, bool with_numeric = true); - + virtual ~SliderController () {} void set_value (float); @@ -64,7 +66,7 @@ class VSliderController : public SliderController public: VSliderController (Glib::RefPtr<Gdk::Pixbuf> image, Gtk::Adjustment *adj, - PBD::Controllable&, + boost::shared_ptr<PBD::Controllable>, bool with_numeric = true); }; @@ -73,7 +75,7 @@ class HSliderController : public SliderController public: HSliderController (Glib::RefPtr<Gdk::Pixbuf> image, Gtk::Adjustment *adj, - PBD::Controllable&, + boost::shared_ptr<PBD::Controllable>, bool with_numeric = true); }; diff --git a/libs/gtkmm2ext/hexentry.cc b/libs/gtkmm2ext/hexentry.cc deleted file mode 100644 index 9862cac435..0000000000 --- a/libs/gtkmm2ext/hexentry.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - Copyright (C) 2000 Paul Barton-Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ -*/ - -#include <stdio.h> /* for sprintf, sigh ... */ -#include <string> -#include <ctype.h> - -#include <gdk/gdkkeysyms.h> -#include <gtkmm2ext/hexentry.h> - -using namespace std; -using namespace Gtkmm2ext; - -bool -HexEntry::on_key_press_event (GdkEventKey *ev) - -{ - if ((ev->keyval >= GDK_a && ev->keyval <= GDK_f) || - (ev->keyval >= GDK_A && ev->keyval <= GDK_A) || - (ev->keyval >= GDK_0 && ev->keyval <= GDK_9) || - ev->keyval == GDK_space || - ev->keyval == GDK_Tab || - ev->keyval == GDK_Return || - ev->keyval == GDK_BackSpace || - ev->keyval == GDK_Delete) { - return Gtk::Entry::on_key_press_event (ev); - } else { - gdk_beep (); - return FALSE; - } -} - - -void -HexEntry::set_hex (unsigned char *msg, unsigned int len) - -{ - /* create a textual representation of the MIDI message */ - - if (msg && len) { - char *rep; - - rep = new char[(len * 3) + 1]; - for (size_t i = 0; i < len; i++) { - sprintf (&rep[i*3], "%02x ", msg[i]); - } - rep[len * 3] = '\0'; - set_text (rep); - delete [] rep; - } else { - set_text (""); - } -} - -unsigned int -HexEntry::get_hex (unsigned char *hexbuf, size_t buflen) - -{ - int fetched_len; - char buf[3]; - string text = get_text(); - string::size_type length = text.length (); - string::size_type offset; - - fetched_len = 0; - buf[2] = '\0'; - offset = 0; - - while (1) { - offset = text.find_first_of ("abcdef0123456789", offset); - - if (offset == string::npos) { - break; - } - - /* grab two characters, but no more */ - - buf[0] = text[offset]; - - if (offset < length - 1) { - buf[1] = text[offset+1]; - offset += 2; - } else { - buf[1] = '\0'; - offset += 1; - } - - hexbuf[fetched_len++] = (char) strtol (buf, 0, 16); - } - - return fetched_len; -} - - diff --git a/libs/gtkmm2ext/pathlist.cc b/libs/gtkmm2ext/pathlist.cc deleted file mode 100644 index 7b3448ed5f..0000000000 --- a/libs/gtkmm2ext/pathlist.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright (C) 2006 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include <gtkmm2ext/pathlist.h> - -#include "i18n.h" - -using namespace std; -using namespace Gtkmm2ext; - -PathList::PathList () - : - add_btn(_("+")), - subtract_btn(_("-")), - path_columns(), - _store(Gtk::ListStore::create(path_columns)), - _view(_store) -{ - _view.append_column(_("Paths"), path_columns.paths); - _view.set_size_request(-1, 100); - _view.set_headers_visible (false); - - Gtk::ScrolledWindow* scroll = manage(new Gtk::ScrolledWindow); - scroll->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - scroll->add(_view); - - add (*scroll); - - Gtk::HBox* btn_box = manage(new Gtk::HBox); - btn_box->add(add_btn); - btn_box->add(subtract_btn); - - add (*btn_box); - - add_btn.signal_clicked().connect (mem_fun(*this, &PathList::add_btn_clicked)); - subtract_btn.signal_clicked().connect (mem_fun(*this, &PathList::subtract_btn_clicked)); - _view.get_selection()->signal_changed().connect (mem_fun(*this, &PathList::selection_changed)); -} - -vector<string> -PathList::get_paths () -{ - vector<string> paths; - - Gtk::TreeModel::Children children(_store->children()); - - for (Gtk::TreeIter iter = children.begin(); iter != children.end(); ++iter) { - Gtk::ListStore::Row row = *iter; - - paths.push_back(row[path_columns.paths]); - } - - return paths; -} - -void -PathList::set_paths (vector<string> paths) -{ - _store->clear(); - - for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i) { - Gtk::ListStore::iterator iter = _store->append(); - Gtk::ListStore::Row row = *iter; - row[path_columns.paths] = *i; - } -} - -void -PathList::add_btn_clicked () -{ - Gtk::FileChooserDialog path_chooser (_("Path Chooser"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); - - path_chooser.add_button (Gtk::Stock::ADD, Gtk::RESPONSE_OK); - path_chooser.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - - int result = path_chooser.run (); - - if (result == Gtk::RESPONSE_OK) { - string pathname = path_chooser.get_filename(); - - if (pathname.length ()) { - Gtk::ListStore::iterator iter = _store->append (); - Gtk::ListStore::Row row = *iter; - row[path_columns.paths] = pathname; - - PathsUpdated (); // EMIT_SIGNAL - } - } -} - -void -PathList::subtract_btn_clicked () -{ - Gtk::ListStore::iterator iter = _view.get_selection()->get_selected(); - _store->erase (iter); - - PathsUpdated (); // EMIT_SIGNAL -} - -void -PathList::selection_changed () -{ - if (_view.get_selection()->count_selected_rows ()) { - subtract_btn.set_sensitive (true); - } else { - subtract_btn.set_sensitive (false); - } -} diff --git a/libs/gtkmm2ext/slider_controller.cc b/libs/gtkmm2ext/slider_controller.cc index 93dfb27ae2..92fd9d078b 100644 --- a/libs/gtkmm2ext/slider_controller.cc +++ b/libs/gtkmm2ext/slider_controller.cc @@ -30,7 +30,7 @@ using namespace PBD; SliderController::SliderController (Glib::RefPtr<Gdk::Pixbuf> image, Gtk::Adjustment *adj, int orientation, - Controllable& c, + boost::shared_ptr<Controllable> c, bool with_numeric) : PixFader (image, *adj, orientation), @@ -60,7 +60,7 @@ SliderController::on_button_press_event (GdkEventButton *ev) VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> image, Gtk::Adjustment *adj, - Controllable& control, + boost::shared_ptr<Controllable> control, bool with_numeric) : SliderController (image, adj, VERT, control, with_numeric) @@ -76,7 +76,7 @@ VSliderController::VSliderController (Glib::RefPtr<Gdk::Pixbuf> image, HSliderController::HSliderController (Glib::RefPtr<Gdk::Pixbuf> image, Gtk::Adjustment *adj, - Controllable& control, + boost::shared_ptr<Controllable> control, bool with_numeric) : SliderController (image, adj, HORIZ, control, with_numeric) diff --git a/libs/libgnomecanvasmm/SConscript b/libs/libgnomecanvasmm/SConscript index 7907622287..273fbe84df 100644 --- a/libs/libgnomecanvasmm/SConscript +++ b/libs/libgnomecanvasmm/SConscript @@ -7,7 +7,7 @@ import glob gnomecanvasmm_files = glob.glob('libgnomecanvasmm/*.cc') Import('env libraries install_prefix') -gnomecanvasmm = env.Copy() +gnomecanvasmm = env.Clone() gnomecanvasmm.Merge([libraries['glibmm2'], libraries['gtk2'], libraries['sigc2'], diff --git a/libs/libsndfile/SConscript b/libs/libsndfile/SConscript index 63c5285346..70cdb637b1 100644 --- a/libs/libsndfile/SConscript +++ b/libs/libsndfile/SConscript @@ -7,7 +7,7 @@ import glob sndfile_files = glob.glob('src/*.c') + glob.glob('src/GSM610/*.c') + glob.glob('src/G72x/*.c') Import('env install_prefix libraries use_flac') -sndfile = env.Copy() +sndfile = env.Clone() if use_flac: sndfile.Merge([libraries['flac'] ]) diff --git a/libs/midi++2/SConscript b/libs/midi++2/SConscript index 0915db9f3f..222e9e249a 100644 --- a/libs/midi++2/SConscript +++ b/libs/midi++2/SConscript @@ -6,7 +6,7 @@ import glob Import('env libraries install_prefix') -midi2 = env.Copy() +midi2 = env.Clone() midi2.Merge([ libraries['sigc2'], libraries['xml'], libraries['glibmm2'], diff --git a/libs/midi++2/midi.cc b/libs/midi++2/midi.cc index 1d45dc57f5..f612b4707a 100644 --- a/libs/midi++2/midi.cc +++ b/libs/midi++2/midi.cc @@ -20,6 +20,7 @@ #include <cstring> #include <string> +#include <cstring> #include <cstdlib> #include <midi++/types.h> diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript index 87173f0874..4b65e3ee38 100644 --- a/libs/pbd/SConscript +++ b/libs/pbd/SConscript @@ -6,7 +6,7 @@ import glob Import('env libraries i18n install_prefix') -pbd = env.Copy() +pbd = env.Clone() domain = 'libpbd' diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc index 94d039ba86..0dbe6baf52 100644 --- a/libs/pbd/base_ui.cc +++ b/libs/pbd/base_ui.cc @@ -21,7 +21,8 @@ #include <stdint.h> #include <unistd.h> #include <fcntl.h> -#include <errno.h> +#include <cerrno> +#include <cstring> #include <pbd/base_ui.h> #include <pbd/error.h> @@ -85,20 +86,20 @@ BaseUI::setup_signal_pipe () */ if (pipe (signal_pipe)) { - error << string_compose (_("%1-UI: cannot create error signal pipe (%2)"), _name, std::strerror (errno)) + error << string_compose (_("%1-UI: cannot create error signal pipe (%2)"), _name, ::strerror (errno)) << endmsg; return -1; } if (fcntl (signal_pipe[0], F_SETFL, O_NONBLOCK)) { - error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal read pipe (%2)"), _name, std::strerror (errno)) + error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal read pipe (%2)"), _name, ::strerror (errno)) << endmsg; return -1; } if (fcntl (signal_pipe[1], F_SETFL, O_NONBLOCK)) { - error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal write pipe (%2)"), _name, std::strerror (errno)) + error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal write pipe (%2)"), _name, ::strerror (errno)) << endmsg; return -1; } diff --git a/libs/pbd/enumwriter.cc b/libs/pbd/enumwriter.cc index 7674410ec9..7033e5f3b1 100644 --- a/libs/pbd/enumwriter.cc +++ b/libs/pbd/enumwriter.cc @@ -18,10 +18,10 @@ $Id$ */ -#include <ctype.h> +#include <cctype> -#include <string.h> -#include <stdlib.h> +#include <cstring> +#include <cstdlib> #include <pbd/enumwriter.h> #include <pbd/error.h> diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc index f6850a57dc..76150824c7 100644 --- a/libs/pbd/fpu.cc +++ b/libs/pbd/fpu.cc @@ -1,5 +1,5 @@ #define _XOPEN_SOURCE 600 -#include <stdlib.h> +#include <cstdlib> #include <stdint.h> #include <pbd/fpu.h> diff --git a/libs/pbd/mountpoint.cc b/libs/pbd/mountpoint.cc index acc549890a..f273146343 100644 --- a/libs/pbd/mountpoint.cc +++ b/libs/pbd/mountpoint.cc @@ -21,6 +21,7 @@ #include <cstdio> #include <cstring> #include <string> +#include <cstring> #include <limits.h> #include <pbd/mountpoint.h> diff --git a/libs/pbd/pathscanner.cc b/libs/pbd/pathscanner.cc index eb913cc910..e12df5efac 100644 --- a/libs/pbd/pathscanner.cc +++ b/libs/pbd/pathscanner.cc @@ -21,6 +21,7 @@ #include <cstring> #include <cstdlib> #include <cstdio> +#include <cstring> #include <vector> #include <dirent.h> diff --git a/libs/pbd/pbd/functor_command.h b/libs/pbd/pbd/functor_command.h index e335f4418e..e6c07cfdbe 100644 --- a/libs/pbd/pbd/functor_command.h +++ b/libs/pbd/pbd/functor_command.h @@ -44,15 +44,11 @@ class FunctorCommand : public Command typedef typename FunctorMap::iterator FunctorMapIterator; public: - FunctorCommand( - std::string functor, - obj_type object, - arg_type b, - arg_type a - ) : functor_name(functor), - object(object), - before(b), - after(a) + FunctorCommand(std::string functor, obj_type& object, arg_type b, arg_type a) + : functor_name(functor) + , object(object) + , before(b) + , after(a) { method = find_functor(functor); @@ -76,6 +72,7 @@ class FunctorCommand : public Command std::stringstream ss; XMLNode *node = new XMLNode("FunctorCommand"); + node->add_property("type_name", typeid(obj_type).name()); node->add_property("functor", functor_name); ss << before; node->add_property("before", ss.str()); diff --git a/libs/pbd/pool.cc b/libs/pbd/pool.cc index 434429e69d..46de65153e 100644 --- a/libs/pbd/pool.cc +++ b/libs/pbd/pool.cc @@ -21,6 +21,7 @@ #include <cstdlib> #include <iostream> #include <vector> +#include <cstdlib> #include <pbd/pool.h> #include <pbd/error.h> diff --git a/libs/pbd/stacktrace.cc b/libs/pbd/stacktrace.cc index dc9a5e18ab..39dd46be3d 100644 --- a/libs/pbd/stacktrace.cc +++ b/libs/pbd/stacktrace.cc @@ -30,7 +30,7 @@ PBD::trace_twb () #ifdef HAVE_EXECINFO #include <execinfo.h> -#include <stdlib.h> +#include <cstdlib> void PBD::stacktrace (std::ostream& out, int levels) diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc index aeff37cce7..f04b4d9431 100644 --- a/libs/pbd/undo.cc +++ b/libs/pbd/undo.cc @@ -21,6 +21,7 @@ #include <iostream> #include <string> #include <sstream> +#include <time.h> #include <pbd/undo.h> #include <pbd/xml++.h> @@ -34,6 +35,7 @@ using namespace sigc; UndoTransaction::UndoTransaction () : _clearing(false) { + gettimeofday (&_timestamp, 0); } UndoTransaction::UndoTransaction (const UndoTransaction& rhs) diff --git a/libs/sigc++2/SConscript b/libs/sigc++2/SConscript index 9ac1ef48ee..8d6bc93c24 100644 --- a/libs/sigc++2/SConscript +++ b/libs/sigc++2/SConscript @@ -25,6 +25,7 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar env.Alias('tarball', env.Distribute (env['DISTTREE'], [ 'NEWS', 'README', 'AUTHORS', 'ChangeLog', 'configure', 'configure.ac', 'Makefile.am', 'SConscript', + 'config.sub', 'config.guess', 'sigc++/Makefile.in', 'sigc++config.h', 'sigc++config.h.in', diff --git a/libs/sigc++2/missing b/libs/sigc++2/missing index 1c8ff7049d..894e786e16 100755 --- a/libs/sigc++2/missing +++ b/libs/sigc++2/missing @@ -1,9 +1,9 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -scriptversion=2006-05-10.23 +scriptversion=2005-06-08.21 -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. @@ -33,8 +33,6 @@ if test $# -eq 0; then fi run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. @@ -46,7 +44,7 @@ fi msg="missing on your system" -case $1 in +case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= @@ -79,7 +77,6 @@ Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c @@ -109,7 +106,7 @@ esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). -case $1 in +case "$1" in lex|yacc) # Not GNU programs, they don't have --version. ;; @@ -138,7 +135,7 @@ esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. -case $1 in +case "$1" in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if @@ -167,7 +164,7 @@ WARNING: \`$1' is $msg. You should only need it if test -z "$files" && files="config.h" touch_files= for f in $files; do - case $f in + case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; @@ -195,8 +192,8 @@ WARNING: \`$1' is needed, but is $msg. You can get \`$1' as part of \`Autoconf' from any GNU archive site." - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else @@ -217,25 +214,25 @@ WARNING: \`$1' $msg. You should only need it if in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h - if test $# -ne 1; then + if [ $# -ne 1 ]; then eval LASTARG="\${$#}" - case $LASTARG in + case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then + if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then + if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi - if test ! -f y.tab.h; then + if [ ! -f y.tab.h ]; then echo >y.tab.h fi - if test ! -f y.tab.c; then + if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; @@ -247,18 +244,18 @@ WARNING: \`$1' is $msg. You should only need it if in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c - if test $# -ne 1; then + if [ $# -ne 1 ]; then eval LASTARG="\${$#}" - case $LASTARG in + case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then + if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi - if test ! -f lex.yy.c; then + if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; @@ -270,9 +267,11 @@ WARNING: \`$1' is $msg. You should only need it if \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file @@ -290,17 +289,11 @@ WARNING: \`$1' is $msg. You should only need it if DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi @@ -324,13 +317,13 @@ WARNING: \`$1' is $msg. You should only need it if fi firstarg="$1" if shift; then - case $firstarg in + case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac - case $firstarg in + case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 diff --git a/libs/soundtouch/AAFilter.cpp b/libs/soundtouch/AAFilter.cpp index d135218c54..d77c19d864 100644 --- a/libs/soundtouch/AAFilter.cpp +++ b/libs/soundtouch/AAFilter.cpp @@ -41,9 +41,9 @@ //////////////////////////////////////////////////////////////////////////////// #include <memory.h> -#include <assert.h> -#include <math.h> -#include <stdlib.h> +#include <cassert> +#include <cmath> +#include <cstdlib> #include "AAFilter.h" #include "FIRFilter.h" diff --git a/libs/soundtouch/FIFOSampleBuffer.cpp b/libs/soundtouch/FIFOSampleBuffer.cpp index f158ee7949..613d8f9c48 100644 --- a/libs/soundtouch/FIFOSampleBuffer.cpp +++ b/libs/soundtouch/FIFOSampleBuffer.cpp @@ -43,10 +43,10 @@ // //////////////////////////////////////////////////////////////////////////////// -#include <stdlib.h> +#include <cstdlib> #include <memory.h> -#include <string.h> -#include <assert.h> +#include <cstring> +#include <cassert> #include <stdexcept> #include "FIFOSampleBuffer.h" diff --git a/libs/soundtouch/FIFOSamplePipe.h b/libs/soundtouch/FIFOSamplePipe.h index d2d54d5274..bf42895c26 100644 --- a/libs/soundtouch/FIFOSamplePipe.h +++ b/libs/soundtouch/FIFOSamplePipe.h @@ -48,8 +48,8 @@ #ifndef FIFOSamplePipe_H #define FIFOSamplePipe_H -#include <assert.h> -#include <stdlib.h> +#include <cassert> +#include <cstdlib> #include "STTypes.h" namespace soundtouch diff --git a/libs/soundtouch/FIRFilter.cpp b/libs/soundtouch/FIRFilter.cpp index cc9c40d883..1723195733 100644 --- a/libs/soundtouch/FIRFilter.cpp +++ b/libs/soundtouch/FIRFilter.cpp @@ -40,9 +40,9 @@ //////////////////////////////////////////////////////////////////////////////// #include <memory.h> -#include <assert.h> -#include <math.h> -#include <stdlib.h> +#include <cassert> +#include <cmath> +#include <cstdlib> #include <stdexcept> #include "FIRFilter.h" #include "cpu_detect.h" diff --git a/libs/soundtouch/RateTransposer.cpp b/libs/soundtouch/RateTransposer.cpp index 493d5326f2..3000e37e4a 100644 --- a/libs/soundtouch/RateTransposer.cpp +++ b/libs/soundtouch/RateTransposer.cpp @@ -39,10 +39,10 @@ //////////////////////////////////////////////////////////////////////////////// #include <memory.h> -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <limits.h> +#include <cassert> +#include <cstdlib> +#include <cstdio> +#include <climits> #include "RateTransposer.h" #include "AAFilter.h" diff --git a/libs/soundtouch/SConscript b/libs/soundtouch/SConscript index 417d00b347..bfd1892212 100644 --- a/libs/soundtouch/SConscript +++ b/libs/soundtouch/SConscript @@ -16,7 +16,7 @@ cpu_detect_x86_gcc.cpp """) Import('env install_prefix') -st = env.Copy() +st = env.Clone() st.Append(CCFLAGS="-DHAVE_CONFIG_H -D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE") libst = st.SharedLibrary('soundtouch', soundtouch_files) diff --git a/libs/soundtouch/TDStretch.cpp b/libs/soundtouch/TDStretch.cpp index c71c65967f..d08dbc2028 100644 --- a/libs/soundtouch/TDStretch.cpp +++ b/libs/soundtouch/TDStretch.cpp @@ -41,12 +41,12 @@ // //////////////////////////////////////////////////////////////////////////////// -#include <string.h> -#include <stdlib.h> +#include <cstring> +#include <cstdlib> #include <memory.h> -#include <limits.h> -#include <math.h> -#include <assert.h> +#include <climits> +#include <cmath> +#include <cassert> #include "STTypes.h" #include "cpu_detect.h" diff --git a/libs/surfaces/control_protocol/SConscript b/libs/surfaces/control_protocol/SConscript index fcc11dbae3..22cb1f4961 100644 --- a/libs/surfaces/control_protocol/SConscript +++ b/libs/surfaces/control_protocol/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -cp = env.Copy() +cp = env.Clone() # # this defines the version number of libardour_cp @@ -38,7 +38,6 @@ cp.Merge ([ libraries['pbd'], libraries['midi++2'], libraries['xml'], - libraries['usb'], libraries['glib2'], libraries['glibmm2'] ]) diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc index 44445192be..71d5794805 100644 --- a/libs/surfaces/control_protocol/basic_ui.cc +++ b/libs/surfaces/control_protocol/basic_ui.cc @@ -30,6 +30,8 @@ using namespace ARDOUR; using ARDOUR::nframes_t; +sigc::signal<void,std::string,std::string> BasicUI::AccessAction; + BasicUI::BasicUI (Session& s) : session (&s) { @@ -51,6 +53,17 @@ BasicUI::register_thread (std::string name) PBD::ThreadCreated (pthread_self(), name); } + +void +BasicUI::access_action ( std::string action_path ) +{ + int split_at = action_path.find( "/" ); + std::string group = action_path.substr( 0, split_at ); + std::string item = action_path.substr( split_at + 1 ); + + AccessAction( group, item ); +} + void BasicUI::loop_toggle () { diff --git a/libs/surfaces/control_protocol/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/control_protocol/basic_ui.h index 7bc6b25c32..c8b5a2a0b6 100644 --- a/libs/surfaces/control_protocol/control_protocol/basic_ui.h +++ b/libs/surfaces/control_protocol/control_protocol/basic_ui.h @@ -42,6 +42,8 @@ class BasicUI { /* transport control */ void loop_toggle (); + void access_action ( std::string action_path ); + static sigc::signal<void,std::string,std::string> AccessAction; void goto_start (); void goto_end (); void rewind (); diff --git a/libs/surfaces/frontier/tranzport/SConscript b/libs/surfaces/frontier/tranzport/SConscript index 099e35de52..0f05e379cc 100644 --- a/libs/surfaces/frontier/tranzport/SConscript +++ b/libs/surfaces/frontier/tranzport/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -tranzport = env.Copy() +tranzport = env.Clone() # # this defines the version number of libardour_tranzport diff --git a/libs/surfaces/generic_midi/SConscript b/libs/surfaces/generic_midi/SConscript index 051a61f148..833f06923a 100644 --- a/libs/surfaces/generic_midi/SConscript +++ b/libs/surfaces/generic_midi/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -genericmidi = env.Copy() +genericmidi = env.Clone() # # this defines the version number of libardour_genericmidi diff --git a/libs/surfaces/mackie/SConscript b/libs/surfaces/mackie/SConscript index 4882658920..45ce63d3cd 100644 --- a/libs/surfaces/mackie/SConscript +++ b/libs/surfaces/mackie/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -mackie = env.Copy() +mackie = env.Clone() # # this defines the version number of libardour_mackie diff --git a/libs/surfaces/powermate/SConscript b/libs/surfaces/powermate/SConscript index 504edc6031..26ecc511eb 100644 --- a/libs/surfaces/powermate/SConscript +++ b/libs/surfaces/powermate/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -powermate = env.Copy() +powermate = env.Clone() # # this defines the version number of powermate diff --git a/libs/surfaces/powermate/powermate.cc b/libs/surfaces/powermate/powermate.cc index 8b3051af20..6f3cf15456 100644 --- a/libs/surfaces/powermate/powermate.cc +++ b/libs/surfaces/powermate/powermate.cc @@ -6,9 +6,9 @@ #include <linux/input.h> -#include <string.h> -#include <errno.h> -#include <stdio.h> +#include <cstring> +#include <cerrno> +#include <cstdio> #include <unistd.h> #include <fcntl.h> diff --git a/libs/surfaces/tranzport/SConscript b/libs/surfaces/tranzport/SConscript index 5e14be31d3..fddd66c95d 100644 --- a/libs/surfaces/tranzport/SConscript +++ b/libs/surfaces/tranzport/SConscript @@ -6,7 +6,7 @@ import glob Import('env final_prefix install_prefix final_config_prefix libraries i18n') -tranzport = env.Copy() +tranzport = env.Clone() # # this defines the version number of libardour_tranzport diff --git a/libs/surfaces/tranzport/screen.cc b/libs/surfaces/tranzport/screen.cc index ab19358868..74d6c7d528 100644 --- a/libs/surfaces/tranzport/screen.cc +++ b/libs/surfaces/tranzport/screen.cc @@ -18,6 +18,7 @@ * * */ +#include <cstring> #include <tranzport_control_protocol.h> #include <cstring> diff --git a/libs/vamp-plugins/Onset.cpp b/libs/vamp-plugins/Onset.cpp new file mode 100644 index 0000000000..d475b11be9 --- /dev/null +++ b/libs/vamp-plugins/Onset.cpp @@ -0,0 +1,280 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugins using Paul Brossier's Aubio library. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. + +*/ + +#include <math.h> +#include "Onset.h" + +using std::string; +using std::vector; +using std::cerr; +using std::endl; + +Onset::Onset(float inputSampleRate) : + Plugin(inputSampleRate), + m_ibuf(0), + m_fftgrain(0), + m_onset(0), + m_pv(0), + m_peakpick(0), + m_onsetdet(0), + m_onsettype(aubio_onset_complex), + m_threshold(0.3), + m_silence(-90), + m_channelCount(1) +{ +} + +Onset::~Onset() +{ + if (m_onsetdet) aubio_onsetdetection_free(m_onsetdet); + if (m_ibuf) del_fvec(m_ibuf); + if (m_onset) del_fvec(m_onset); + if (m_fftgrain) del_cvec(m_fftgrain); + if (m_pv) del_aubio_pvoc(m_pv); + if (m_peakpick) del_aubio_peakpicker(m_peakpick); +} + +string +Onset::getIdentifier() const +{ + return "aubioonset"; +} + +string +Onset::getName() const +{ + return "Aubio Onset Detector"; +} + +string +Onset::getDescription() const +{ + return "Estimate note onset times"; +} + +string +Onset::getMaker() const +{ + return "Paul Brossier (plugin by Chris Cannam)"; +} + +int +Onset::getPluginVersion() const +{ + return 1; +} + +string +Onset::getCopyright() const +{ + return "GPL"; +} + +bool +Onset::initialise(size_t channels, size_t stepSize, size_t blockSize) +{ + m_channelCount = channels; + m_stepSize = stepSize; + m_blockSize = blockSize; + + m_ibuf = new_fvec(stepSize, channels); + m_onset = new_fvec(1, channels); + m_fftgrain = new_cvec(blockSize, channels); + m_pv = new_aubio_pvoc(blockSize, stepSize, channels); + m_peakpick = new_aubio_peakpicker(m_threshold); + + m_onsetdet = new_aubio_onsetdetection(m_onsettype, blockSize, channels); + + m_delay = Vamp::RealTime::frame2RealTime(4 * stepSize, + lrintf(m_inputSampleRate)); + + m_lastOnset = Vamp::RealTime::zeroTime - m_delay - m_delay; + + return true; +} + +void +Onset::reset() +{ +} + +size_t +Onset::getPreferredStepSize() const +{ + return 512; +} + +size_t +Onset::getPreferredBlockSize() const +{ + return 2 * getPreferredStepSize(); +} + +Onset::ParameterList +Onset::getParameterDescriptors() const +{ + ParameterList list; + + ParameterDescriptor desc; + desc.identifier = "onsettype"; + desc.name = "Onset Detection Function Type"; + desc.minValue = 0; + desc.maxValue = 6; + desc.defaultValue = (int)aubio_onset_complex; + desc.isQuantized = true; + desc.quantizeStep = 1; + desc.valueNames.push_back("Energy Based"); + desc.valueNames.push_back("Spectral Difference"); + desc.valueNames.push_back("High-Frequency Content"); + desc.valueNames.push_back("Complex Domain"); + desc.valueNames.push_back("Phase Deviation"); + desc.valueNames.push_back("Kullback-Liebler"); + desc.valueNames.push_back("Modified Kullback-Liebler"); + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.identifier = "peakpickthreshold"; + desc.name = "Peak Picker Threshold"; + desc.minValue = 0; + desc.maxValue = 1; + desc.defaultValue = 0.3; + desc.isQuantized = false; + list.push_back(desc); + + desc = ParameterDescriptor(); + desc.identifier = "silencethreshold"; + desc.name = "Silence Threshold"; + desc.minValue = -120; + desc.maxValue = 0; + desc.defaultValue = -90; + desc.unit = "dB"; + desc.isQuantized = false; + list.push_back(desc); + + return list; +} + +float +Onset::getParameter(std::string param) const +{ + if (param == "onsettype") { + return m_onsettype; + } else if (param == "peakpickthreshold") { + return m_threshold; + } else if (param == "silencethreshold") { + return m_silence; + } else { + return 0.0; + } +} + +void +Onset::setParameter(std::string param, float value) +{ + if (param == "onsettype") { + switch (lrintf(value)) { + case 0: m_onsettype = aubio_onset_energy; break; + case 1: m_onsettype = aubio_onset_specdiff; break; + case 2: m_onsettype = aubio_onset_hfc; break; + case 3: m_onsettype = aubio_onset_complex; break; + case 4: m_onsettype = aubio_onset_phase; break; + case 5: m_onsettype = aubio_onset_kl; break; + case 6: m_onsettype = aubio_onset_mkl; break; + } + } else if (param == "peakpickthreshold") { + m_threshold = value; + } else if (param == "silencethreshold") { + m_silence = value; + } +} + +Onset::OutputList +Onset::getOutputDescriptors() const +{ + OutputList list; + + OutputDescriptor d; + d.identifier = "onsets"; + d.name = "Onsets"; + d.unit = ""; + d.hasFixedBinCount = true; + d.binCount = 0; + d.sampleType = OutputDescriptor::VariableSampleRate; + d.sampleRate = 0; + list.push_back(d); + + d = OutputDescriptor(); + d.identifier = "detectionfunction"; + d.name = "Onset Detection Function"; + d.unit = ""; + d.hasFixedBinCount = true; + d.binCount = m_channelCount; + d.hasKnownExtents = false; + d.isQuantized = false; + d.sampleType = OutputDescriptor::OneSamplePerStep; + list.push_back(d); + + return list; +} + +Onset::FeatureSet +Onset::process(const float *const *inputBuffers, + Vamp::RealTime timestamp) +{ + for (size_t i = 0; i < m_stepSize; ++i) { + for (size_t j = 0; j < m_channelCount; ++j) { + fvec_write_sample(m_ibuf, inputBuffers[j][i], j, i); + } + } + + aubio_pvoc_do(m_pv, m_ibuf, m_fftgrain); + aubio_onsetdetection(m_onsetdet, m_fftgrain, m_onset); + + bool isonset = aubio_peakpick_pimrt(m_onset, m_peakpick); + + if (isonset) { + if (aubio_silence_detection(m_ibuf, m_silence)) { + isonset = false; + } + } + + FeatureSet returnFeatures; + + if (isonset) { + if (timestamp - m_lastOnset >= m_delay) { + Feature onsettime; + onsettime.hasTimestamp = true; + if (timestamp < m_delay) timestamp = m_delay; + onsettime.timestamp = timestamp - m_delay; + returnFeatures[0].push_back(onsettime); + m_lastOnset = timestamp; + } + } + Feature feature; + for (size_t j = 0; j < m_channelCount; ++j) { + feature.values.push_back(m_onset->data[j][0]); + } + returnFeatures[1].push_back(feature); + + return returnFeatures; +} + +Onset::FeatureSet +Onset::getRemainingFeatures() +{ + return FeatureSet(); +} + diff --git a/libs/vamp-plugins/Onset.h b/libs/vamp-plugins/Onset.h new file mode 100644 index 0000000000..314e107308 --- /dev/null +++ b/libs/vamp-plugins/Onset.h @@ -0,0 +1,73 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugins using Paul Brossier's Aubio library. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. + +*/ + +#ifndef _ONSET_PLUGIN_H_ +#define _ONSET_PLUGIN_H_ + +#include <vamp-sdk/Plugin.h> +#include <aubio/aubio.h> + +class Onset : public Vamp::Plugin +{ +public: + Onset(float inputSampleRate); + virtual ~Onset(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + void reset(); + + InputDomain getInputDomain() const { return TimeDomain; } + + std::string getIdentifier() const; + std::string getName() const; + std::string getDescription() const; + std::string getMaker() const; + int getPluginVersion() const; + std::string getCopyright() const; + + ParameterList getParameterDescriptors() const; + float getParameter(std::string) const; + void setParameter(std::string, float); + + size_t getPreferredStepSize() const; + size_t getPreferredBlockSize() const; + + OutputList getOutputDescriptors() const; + + FeatureSet process(const float *const *inputBuffers, + Vamp::RealTime timestamp); + + FeatureSet getRemainingFeatures(); + +protected: + fvec_t *m_ibuf; + cvec_t *m_fftgrain; + fvec_t *m_onset; + aubio_pvoc_t *m_pv; + aubio_pickpeak_t *m_peakpick; + aubio_onsetdetection_t *m_onsetdet; + aubio_onsetdetection_type m_onsettype; + float m_threshold; + float m_silence; + size_t m_stepSize; + size_t m_blockSize; + size_t m_channelCount; + Vamp::RealTime m_delay; + Vamp::RealTime m_lastOnset; +}; + + +#endif diff --git a/libs/vamp-plugins/SConscript b/libs/vamp-plugins/SConscript index 6b8159bd8c..d0796af092 100644 --- a/libs/vamp-plugins/SConscript +++ b/libs/vamp-plugins/SConscript @@ -4,17 +4,33 @@ import os import os.path import glob -plugin_files = glob.glob ("*.cpp") +plugin_files = Split(""" +plugins.cpp +AmplitudeFollower.cpp +PercussionOnsetDetector.cpp +SpectralCentroid.cpp +ZeroCrossing.cpp +""") + +aubio_files = Split (""" +Onset.cpp +""") Import('env install_prefix libraries') -vampplugs = env.Copy() +vampplugs = env.Clone() vampplugs.Append (CPPATH='#libs/vamp-sdk/vamp', CXXFLAGS="-Ilibs/vamp-sdk") vampplugs.Merge ([libraries['vamp'], libraries['vamphost'] ]) -libvampplugins = vampplugs.SharedLibrary('ardourvampplugins', plugin_files) +sources = plugin_files + +if vampplugs['AUBIO']: + sources += aubio_files + vampplugs.Merge ([libraries['aubio']]) + +libvampplugins = vampplugs.SharedLibrary('ardourvampplugins', sources) Default(libvampplugins) @@ -22,5 +38,5 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar env.Alias('tarball', env.Distribute (env['DISTTREE'], [ 'SConscript' ] + - plugin_files + + plugin_files + aubio_files + glob.glob('*.h'))) diff --git a/libs/vamp-plugins/plugins.cpp b/libs/vamp-plugins/plugins.cpp index 25c6e6c0d4..c45912be9b 100644 --- a/libs/vamp-plugins/plugins.cpp +++ b/libs/vamp-plugins/plugins.cpp @@ -41,11 +41,13 @@ #include "SpectralCentroid.h" #include "PercussionOnsetDetector.h" #include "AmplitudeFollower.h" +#include "Onset.h" static Vamp::PluginAdapter<ZeroCrossing> zeroCrossingAdapter; static Vamp::PluginAdapter<SpectralCentroid> spectralCentroidAdapter; static Vamp::PluginAdapter<PercussionOnsetDetector> percussionOnsetAdapter; static Vamp::PluginAdapter<AmplitudeFollower> amplitudeAdapter; +static Vamp::PluginAdapter<Onset> onsetAdapter; const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version, unsigned int index) @@ -57,6 +59,7 @@ const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version, case 1: return spectralCentroidAdapter.getDescriptor(); case 2: return percussionOnsetAdapter.getDescriptor(); case 3: return amplitudeAdapter.getDescriptor(); + case 4: return onsetAdapter.getDescriptor(); default: return 0; } } diff --git a/libs/vamp-sdk/SConscript b/libs/vamp-sdk/SConscript index 79046e2fc0..be1834896b 100644 --- a/libs/vamp-sdk/SConscript +++ b/libs/vamp-sdk/SConscript @@ -20,7 +20,7 @@ vamp-sdk/RealTime.cpp """) Import('env install_prefix libraries') -vampsdk = env.Copy() +vampsdk = env.Clone() vampsdk.Merge ([libraries['fftw3'], libraries['fftw3f']]) diff --git a/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp index 24f91e5f50..334c11103c 100644 --- a/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp +++ b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp @@ -34,7 +34,7 @@ authorization. */ -#include <stdlib.h> +#include <cstdlib> #include "PluginHostAdapter.h" namespace Vamp diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp index 9d627a75cf..e9d75ee181 100644 --- a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp +++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp @@ -40,6 +40,8 @@ #include "PluginChannelAdapter.h" #include "PluginBufferingAdapter.h" +#include <string> +#include <cstring> #include <fstream> #include <cctype> // tolower #include <cstring> |