diff options
Diffstat (limited to 'libs/ardour')
122 files changed, 3031 insertions, 696 deletions
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 165ad6744f..ec31dd1ac2 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -37,7 +37,10 @@ #include "pbd/signals.h" #include "pbd/stacktrace.h" +#ifndef PLATFORM_WINDOWS #include <jack/weakjack.h> +#endif + #include <jack/jack.h> #include <jack/transport.h> #include <jack/thread.h> @@ -258,7 +261,8 @@ _ the regular process() call to session->process() is not made. static void destroy(); void died (); - int create_process_thread (boost::function<void()>, pthread_t*, size_t stacksize); + int create_process_thread (boost::function<void()>, jack_native_thread_t*, size_t stacksize); + bool stop_process_thread (jack_native_thread_t); private: static AudioEngine* _instance; diff --git a/libs/ardour/ardour/audiofile_tagger.h b/libs/ardour/ardour/audiofile_tagger.h index 0519e2233c..9a46e235d8 100644 --- a/libs/ardour/ardour/audiofile_tagger.h +++ b/libs/ardour/ardour/audiofile_tagger.h @@ -24,8 +24,8 @@ #include <string> #include "taglib/tag.h" -#include "taglib/taglib.h" -#include "taglib/xiphcomment.h" +#include "taglib/toolkit/taglib.h" +#include "taglib/ogg/xiphcomment.h" namespace ARDOUR { diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h index c5fd7b3af2..af5dabe388 100644 --- a/libs/ardour/ardour/audiofilesource.h +++ b/libs/ardour/ardour/audiofilesource.h @@ -64,6 +64,7 @@ public: virtual void clear_capture_marks() {} virtual bool one_of_several_channels () const { return false; } + virtual void flush () = 0; virtual int update_header (framepos_t when, struct tm&, time_t) = 0; virtual int flush_header () = 0; diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h index 478d4872cd..3c987c0aa0 100644 --- a/libs/ardour/ardour/audioplaylist.h +++ b/libs/ardour/ardour/audioplaylist.h @@ -29,7 +29,6 @@ namespace ARDOUR { class Session; -class Region; class AudioRegion; class Source; diff --git a/libs/ardour/ardour/butler.h b/libs/ardour/ardour/butler.h index cdd48c3e3a..226aacbbad 100644 --- a/libs/ardour/ardour/butler.h +++ b/libs/ardour/ardour/butler.h @@ -20,13 +20,21 @@ #ifndef __ardour_butler_h__ #define __ardour_butler_h__ +#include <pthread.h> + #include <glibmm/threads.h> +#ifdef PLATFORM_WINDOWS +#include "pbd/glib_semaphore.h" +#endif + #include "pbd/ringbuffer.h" #include "pbd/pool.h" #include "ardour/types.h" #include "ardour/session_handle.h" + + namespace ARDOUR { /** @@ -71,15 +79,43 @@ class Butler : public SessionHandleRef Glib::Threads::Cond paused; bool should_run; mutable gint should_do_transport_work; - int request_pipe[2]; framecnt_t audio_dstream_capture_buffer_size; framecnt_t audio_dstream_playback_buffer_size; uint32_t midi_dstream_buffer_size; RingBuffer<CrossThreadPool*> pool_trash; +#ifdef PLATFORM_WINDOWS + PBD::atomic_counter m_request_state; + PBD::GlibSemaphore m_request_sem; +#else + int request_pipe[2]; +#endif + private: void empty_pool_trash (); void config_changed (std::string); + +#ifndef PLATFORM_WINDOWS + int setup_request_pipe (); +#endif + + /** + * return true if there are requests to be processed + */ + bool wait_for_requests (); + + /** + * Remove request from butler request queue + * + * return true if there was another request and req is valid + */ + bool dequeue_request (Request::Type& req); + + /** + * Add request to butler thread request queue + */ + void queue_request (Request::Type r); + }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/chan_count.h b/libs/ardour/ardour/chan_count.h index c4f3caef6b..03e2fcd8ff 100644 --- a/libs/ardour/ardour/chan_count.h +++ b/libs/ardour/ardour/chan_count.h @@ -26,6 +26,10 @@ #include "pbd/xml++.h" #include "ardour/data_type.h" +#ifdef INFINITE +#undef INFINITE +#endif + namespace ARDOUR { diff --git a/libs/ardour/ardour/control_protocol_search_path.h b/libs/ardour/ardour/control_protocol_search_path.h index 8795f4501a..4fe790ef80 100644 --- a/libs/ardour/ardour/control_protocol_search_path.h +++ b/libs/ardour/ardour/control_protocol_search_path.h @@ -25,15 +25,15 @@ namespace ARDOUR { /** - * return a SearchPath containing directories in which to look for + * return a Searchpath containing directories in which to look for * control surface plugins. * - * If ARDOUR_SURFACES_PATH is defined then the SearchPath returned + * If ARDOUR_SURFACES_PATH is defined then the Searchpath returned * will contain only those directories specified in it, otherwise it will * contain the user and system directories which may contain control * surface plugins. */ - PBD::SearchPath control_protocol_search_path (); + PBD::Searchpath control_protocol_search_path (); } // namespace ARDOUR diff --git a/libs/ardour/ardour/coreaudiosource.h b/libs/ardour/ardour/coreaudiosource.h index 820fa0b9d8..30c66069f6 100644 --- a/libs/ardour/ardour/coreaudiosource.h +++ b/libs/ardour/ardour/coreaudiosource.h @@ -43,6 +43,8 @@ class CoreAudioSource : public AudioFileSource { void set_header_timeline_position () {}; bool clamped_at_unity () const { return false; } + void flush () {} + static int get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg); protected: diff --git a/libs/ardour/ardour/cycles.h b/libs/ardour/ardour/cycles.h index 01e1d55221..dc1095db7b 100644 --- a/libs/ardour/ardour/cycles.h +++ b/libs/ardour/ardour/cycles.h @@ -216,7 +216,10 @@ static inline cycles_t get_cycles (void) /* debian: sparc, arm, m68k */ +#ifndef COMPILER_MSVC +/* GRRR... Annoyingly, #warning aborts the compilation for MSVC !! */ #warning You are compiling libardour on a platform for which ardour/cycles.h needs work +#endif #include <sys/time.h> diff --git a/libs/ardour/ardour/debug.h b/libs/ardour/ardour/debug.h index 202d0cc424..ae18e59c04 100644 --- a/libs/ardour/ardour/debug.h +++ b/libs/ardour/ardour/debug.h @@ -34,6 +34,7 @@ namespace PBD { extern uint64_t SnapBBT; extern uint64_t Configuration; extern uint64_t Latency; + extern uint64_t Peaks; extern uint64_t Processors; extern uint64_t ProcessThreads; extern uint64_t Graph; diff --git a/libs/ardour/ardour/directory_names.h b/libs/ardour/ardour/directory_names.h index 9f7c778d33..cb4701d336 100644 --- a/libs/ardour/ardour/directory_names.h +++ b/libs/ardour/ardour/directory_names.h @@ -36,6 +36,7 @@ extern const char* const export_formats_dir_name; extern const char* const templates_dir_name; extern const char* const route_templates_dir_name; extern const char* const surfaces_dir_name; +extern const char* const ladspa_dir_name; extern const char* const user_config_dir_name; extern const char* const panner_dir_name; diff --git a/libs/ardour/ardour/export_formats_search_path.h b/libs/ardour/ardour/export_formats_search_path.h index 7b6fcea09b..771c6f9bd3 100644 --- a/libs/ardour/ardour/export_formats_search_path.h +++ b/libs/ardour/ardour/export_formats_search_path.h @@ -24,10 +24,10 @@ namespace ARDOUR { /** - * return a SearchPath containing directories in which to look for + * return a Searchpath containing directories in which to look for * export_formats. */ - PBD::SearchPath export_formats_search_path (); + PBD::Searchpath export_formats_search_path (); } // namespace ARDOUR diff --git a/libs/ardour/ardour/export_profile_manager.h b/libs/ardour/ardour/export_profile_manager.h index 424e0fe163..77ace497c2 100644 --- a/libs/ardour/ardour/export_profile_manager.h +++ b/libs/ardour/ardour/export_profile_manager.h @@ -102,7 +102,7 @@ class ExportProfileManager std::vector<std::string> find_file (std::string const & pattern); std::string export_config_dir; - PBD::SearchPath search_path; + PBD::Searchpath search_path; /* Timespans */ public: diff --git a/libs/ardour/ardour/file_source.h b/libs/ardour/ardour/file_source.h index 5898d04f0a..52dca18feb 100644 --- a/libs/ardour/ardour/file_source.h +++ b/libs/ardour/ardour/file_source.h @@ -79,7 +79,7 @@ public: virtual void set_path (const std::string&); - static PBD::Signal3<int,std::string,std::string,std::vector<std::string> > AmbiguousFileName; + static PBD::Signal2<int,std::string,std::vector<std::string> > AmbiguousFileName; protected: FileSource (Session& session, DataType type, diff --git a/libs/ardour/ardour/filesystem_paths.h b/libs/ardour/ardour/filesystem_paths.h index cfeb633597..e77de1c00f 100644 --- a/libs/ardour/ardour/filesystem_paths.h +++ b/libs/ardour/ardour/filesystem_paths.h @@ -41,14 +41,14 @@ namespace ARDOUR { * @return the search path to be used when looking for per-system * configuration files. This may include user configuration files. */ - PBD::SearchPath ardour_config_search_path (); + PBD::Searchpath ardour_config_search_path (); /** * @return the search path to be used when looking for data files * that could be shared by systems (h/w and configuration independent * files, such as icons, XML files, etc) */ - PBD::SearchPath ardour_data_search_path (); + PBD::Searchpath ardour_data_search_path (); } // namespace ARDOUR diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h index cac09d34af..0a288d68d3 100644 --- a/libs/ardour/ardour/graph.h +++ b/libs/ardour/ardour/graph.h @@ -92,7 +92,7 @@ protected: virtual void session_going_away (); private: - std::list<pthread_t> _thread_list; + std::list<jack_native_thread_t> _thread_list; volatile bool _quit_threads; void reset_thread_list (); diff --git a/libs/ardour/ardour/interthread_info.h b/libs/ardour/ardour/interthread_info.h index 01cacf437c..a06fc649ca 100644 --- a/libs/ardour/ardour/interthread_info.h +++ b/libs/ardour/ardour/interthread_info.h @@ -29,7 +29,7 @@ namespace ARDOUR { class InterThreadInfo { public: - InterThreadInfo () : done (false), cancel (false), progress (0), thread (0) {} + InterThreadInfo () : done (false), cancel (false), progress (0), thread () {} volatile bool done; volatile bool cancel; diff --git a/libs/ardour/ardour/jack_utils.h b/libs/ardour/ardour/jack_utils.h new file mode 100644 index 0000000000..40eb30f9ea --- /dev/null +++ b/libs/ardour/ardour/jack_utils.h @@ -0,0 +1,253 @@ +/* + Copyright (C) 2011 Tim Mayberry + + 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 <stdint.h> + +#include <vector> +#include <map> +#include <string> + +namespace ARDOUR { + + // Names for the drivers on all possible systems + extern const char * const portaudio_driver_name; + extern const char * const coreaudio_driver_name; + extern const char * const alsa_driver_name; + extern const char * const oss_driver_name; + extern const char * const freebob_driver_name; + extern const char * const ffado_driver_name; + extern const char * const netjack_driver_name; + extern const char * const dummy_driver_name; + + /** + * Get a list of possible JACK audio driver names based on platform + */ + void get_jack_audio_driver_names (std::vector<std::string>& driver_names); + + /** + * Get the default JACK audio driver based on platform + */ + void get_jack_default_audio_driver_name (std::string& driver_name); + + /** + * Get a list of possible JACK midi driver names based on platform + */ + void get_jack_midi_system_names (const std::string& driver, std::vector<std::string>& driver_names); + + /** + * Get the default JACK midi driver based on platform + */ + void get_jack_default_midi_system_name (const std::string& driver_name, std::string& midi_system); + + /** + * Get a list of possible samplerates supported be JACK + */ + void get_jack_sample_rate_strings (std::vector<std::string>& sample_rates); + + /** + * @return The default samplerate + */ + std::string get_jack_default_sample_rate (); + + /** + * @return true if sample rate string was able to be converted + */ + bool get_jack_sample_rate_value_from_string (const std::string& srs, uint32_t& srv); + + /** + * Get a list of possible period sizes supported be JACK + */ + void get_jack_period_size_strings (std::vector<std::string>& samplerates); + + /** + * @return The default period size + */ + std::string get_jack_default_period_size (); + + /** + * @return true if period size string was able to be converted + */ + bool get_jack_period_size_value_from_string (const std::string& pss, uint32_t& psv); + + /** + * These are driver specific I think, so it may require a driver arg + * in future + */ + void get_jack_dither_mode_strings (const std::string& driver, std::vector<std::string>& dither_modes); + + /** + * @return The default dither mode + */ + std::string get_jack_default_dither_mode (const std::string& driver); + + /** + * @return Estimate of latency + * + * API matches current use in GUI + */ + std::string get_jack_latency_string (std::string samplerate, float periods, std::string period_size); + + /** + * @return true if a JACK server is running + */ + bool jack_server_running (); + + /** + * Key being a readable name to display in a GUI + * Value being name used in a jack commandline + */ + typedef std::map<std::string, std::string> device_map_t; + + /** + * Use library specific code to find out what what devices exist for a given + * driver that might work in JACK. There is no easy way to find out what + * modules the JACK server supports so guess based on platform. For instance + * portaudio is cross-platform but we only return devices if built for + * windows etc + */ + void get_jack_alsa_device_names (device_map_t& devices); + void get_jack_portaudio_device_names (device_map_t& devices); + void get_jack_coreaudio_device_names (device_map_t& devices); + void get_jack_oss_device_names (device_map_t& devices); + void get_jack_freebob_device_names (device_map_t& devices); + void get_jack_ffado_device_names (device_map_t& devices); + void get_jack_netjack_device_names (device_map_t& devices); + void get_jack_dummy_device_names (device_map_t& devices); + + /* + * @return true if there were devices found for the driver + * + * @param driver The driver name returned by get_jack_audio_driver_names + * @param devices The map used to insert the drivers into, devices will be cleared before + * adding the available drivers + */ + bool get_jack_device_names_for_audio_driver (const std::string& driver, device_map_t& devices); + + /* + * @return a list of readable device names for a specific driver. + */ + std::vector<std::string> get_jack_device_names_for_audio_driver (const std::string& driver); + + /** + * @return true if the driver supports playback and recording + * on separate devices + */ + bool get_jack_audio_driver_supports_two_devices (const std::string& driver); + + bool get_jack_audio_driver_supports_latency_adjustment (const std::string& driver); + + bool get_jack_audio_driver_supports_setting_period_count (const std::string& driver); + + /** + * The possible names to use to try and find servers, this includes + * any file extensions like .exe on Windows + * + * @return true if the JACK application names for this platform could be guessed + */ + bool get_jack_server_application_names (std::vector<std::string>& server_names); + + /** + * Sets the PATH environment variable to contain directories likely to contain + * JACK servers so that if the JACK server is auto-started it can find the server + * executable. + * + * This is only modifies PATH on the mac at the moment. + */ + void set_path_env_for_jack_autostart (const std::vector<std::string>&); + + /** + * Get absolute paths to directories that might contain JACK servers on the system + * + * @return true if !server_paths.empty() + */ + bool get_jack_server_dir_paths (std::vector<std::string>& server_dir_paths); + + /** + * Get absolute paths to JACK servers on the system + * + * @return true if a server was found + */ + bool get_jack_server_paths (const std::vector<std::string>& server_dir_paths, + const std::vector<std::string>& server_names, + std::vector<std::string>& server_paths); + + + bool get_jack_server_paths (std::vector<std::string>& server_paths); + + /** + * Get absolute path to default JACK server + */ + bool get_jack_default_server_path (std::string& server_path); + + /** + * @return The name of the jack server config file + */ + std::string get_jack_server_config_file_name (); + + std::string get_jack_server_user_config_dir_path (); + + std::string get_jack_server_user_config_file_path (); + + bool write_jack_config_file (const std::string& config_file_path, const std::string& command_line); + + struct JackCommandLineOptions { + + // see implementation for defaults + JackCommandLineOptions (); + + //operator bool + //operator ostream + + std::string server_path; + uint32_t timeout; + bool no_mlock; + uint32_t ports_max; + bool realtime; + uint32_t priority; + bool unlock_gui_libs; + bool verbose; + bool temporary; + bool playback_only; + bool capture_only; + std::string driver; + std::string input_device; + std::string output_device; + uint32_t num_periods; + uint32_t period_size; + uint32_t samplerate; + uint32_t input_latency; + uint32_t output_latency; + bool hardware_metering; + bool hardware_monitoring; + std::string dither_mode; + bool force16_bit; + bool soft_mode; + std::string midi_driver; + }; + + /** + * @return true if able to build a valid command line based on options + */ + bool get_jack_command_line_string (const JackCommandLineOptions& options, std::string& command_line); + + /** + * We don't need this at the moment because the gui stores all its settings + */ + //std::string get_jack_command_line_from_config_file (const std::string& config_file_path); +} diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h index 6853a1dc36..62cad017fc 100644 --- a/libs/ardour/ardour/ladspa_plugin.h +++ b/libs/ardour/ardour/ladspa_plugin.h @@ -23,8 +23,8 @@ #include <set> #include <vector> #include <string> -#include <dlfcn.h> +#include <glibmm/module.h> #include "pbd/stateful.h" @@ -39,7 +39,7 @@ class Session; class LadspaPlugin : public ARDOUR::Plugin { public: - LadspaPlugin (void *module, ARDOUR::AudioEngine&, ARDOUR::Session&, uint32_t index, framecnt_t sample_rate); + LadspaPlugin (std::string module_path, ARDOUR::AudioEngine&, ARDOUR::Session&, uint32_t index, framecnt_t sample_rate); LadspaPlugin (const LadspaPlugin &); ~LadspaPlugin (); @@ -122,7 +122,8 @@ class LadspaPlugin : public ARDOUR::Plugin void connect_port (uint32_t port, float *ptr) { _descriptor->connect_port (_handle, port, ptr); } private: - void* _module; + std::string _module_path; + Glib::Module* _module; const LADSPA_Descriptor* _descriptor; LADSPA_Handle _handle; framecnt_t _sample_rate; @@ -134,7 +135,7 @@ class LadspaPlugin : public ARDOUR::Plugin void find_presets (); - void init (void *mod, uint32_t index, framecnt_t rate); + void init (std::string module_path, uint32_t index, framecnt_t rate); void run_in_place (pframes_t nsamples); void latency_compute_run (); int set_state_2X (const XMLNode&, int version); diff --git a/libs/ardour/ardour/ladspa_search_path.h b/libs/ardour/ardour/ladspa_search_path.h new file mode 100644 index 0000000000..bc184b5248 --- /dev/null +++ b/libs/ardour/ardour/ladspa_search_path.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2011 Tim Mayberry + + 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_LADSPA_SEARCH_PATH_INCLUDED +#define ARDOUR_LADSPA_SEARCH_PATH_INCLUDED + +#include "pbd/search_path.h" + +namespace ARDOUR { + + /** + * return a Searchpath containing directories in which to look for + * LADSPA plugins. + * + * If LADSPA_PATH is defined then the Searchpath returned + * will contain the directories specified in it as well as the + * user and system directories. + */ + PBD::Searchpath ladspa_search_path (); + +} // namespace ARDOUR + +#endif diff --git a/libs/ardour/ardour/lv2_bundled_search_path.h b/libs/ardour/ardour/lv2_bundled_search_path.h index f5780c5e0e..9314ee27d4 100644 --- a/libs/ardour/ardour/lv2_bundled_search_path.h +++ b/libs/ardour/ardour/lv2_bundled_search_path.h @@ -25,10 +25,10 @@ namespace ARDOUR { /** - * return a SearchPath containing directories in which to look for + * return a Searchpath containing directories in which to look for * lv2 plugins. */ - PBD::SearchPath lv2_bundled_search_path (); + PBD::Searchpath lv2_bundled_search_path (); } // namespace ARDOUR diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h index 56aa9dc7cf..6b4b1a1c67 100644 --- a/libs/ardour/ardour/lv2_plugin.h +++ b/libs/ardour/ardour/lv2_plugin.h @@ -29,6 +29,8 @@ #include "ardour/worker.h" #include "pbd/ringbuffer.h" +typedef struct LV2_Evbuf_Impl LV2_Evbuf; + namespace ARDOUR { // a callback function for lilv_state_new_from_instance(). friend of LV2Plugin diff --git a/libs/ardour/ardour/midi_patch_search_path.h b/libs/ardour/ardour/midi_patch_search_path.h index 5d27823461..168e75af4a 100644 --- a/libs/ardour/ardour/midi_patch_search_path.h +++ b/libs/ardour/ardour/midi_patch_search_path.h @@ -24,15 +24,15 @@ namespace ARDOUR { /** - * return a SearchPath containing directories in which to look for + * return a Searchpath containing directories in which to look for * MIDI patch files ("*.midnam") aka MIDNAM files * - * If ARDOUR_MIDI_PATCH_PATH is defined then the SearchPath returned + * If ARDOUR_MIDI_PATCH_PATH is defined then the Searchpath returned * will contain only those directories specified in it, otherwise it will * contain the user and system directories which may contain control * surface plugins. */ - PBD::SearchPath midi_patch_search_path (); + PBD::Searchpath midi_patch_search_path (); } // namespace ARDOUR diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index 543e1b353f..99d0b98321 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -32,7 +32,6 @@ namespace ARDOUR { class Session; -class Region; class MidiRegion; class Source; template<typename T> class MidiRingBuffer; diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 3b75c0a51b..9c1d21a3e4 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -20,6 +20,8 @@ #ifndef __ardour_midi_track_h__ #define __ardour_midi_track_h__ +#include "pbd/ffs.h" + #include "ardour/track.h" #include "ardour/midi_ring_buffer.h" @@ -183,7 +185,7 @@ private: /* if mode is ForceChannel, force mask to the lowest set channel or 1 if no * channels are set. */ -#define force_mask(mode,mask) (((mode) == ForceChannel) ? (((mask) ? (1<<(ffs((mask))-1)) : 1)) : mask) +#define force_mask(mode,mask) (((mode) == ForceChannel) ? (((mask) ? (1<<(PBD::ffs((mask))-1)) : 1)) : mask) void _set_playback_channel_mode(ChannelMode mode, uint16_t mask) { mask = force_mask (mode, mask); diff --git a/libs/ardour/ardour/msvc_libardour.h b/libs/ardour/ardour/msvc_libardour.h new file mode 100644 index 0000000000..75c932905e --- /dev/null +++ b/libs/ardour/ardour/msvc_libardour.h @@ -0,0 +1,99 @@ +/* + Copyright (C) 2009 John Emmas + + 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 __msvc_libardour_h__ +#define __msvc_libardour_h__ + +#include <limits.h> + +#ifdef LIBARDOUR_IS_IN_WIN_STATIC_LIB // #define if your project uses libardour (under Windows) as a static library +#define LIBARDOUR_IS_IN_WINDLL 0 +#endif + +#if !defined(LIBARDOUR_IS_IN_WINDLL) + #if defined(COMPILER_MSVC) || defined(COMPILER_MINGW) + // If you need '__declspec' compatibility, add extra compilers to the above as necessary + #define LIBARDOUR_IS_IN_WINDLL 1 + #else + #define LIBARDOUR_IS_IN_WINDLL 0 + #endif +#endif + +#if LIBARDOUR_IS_IN_WINDLL && !defined(LIBARDOUR_API) + #if defined(BUILDING_LIBARDOUR) + #define LIBARDOUR_API __declspec(dllexport) + #define LIBARDOUR_APICALLTYPE __stdcall + #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point + #define LIBARDOUR_API __declspec(dllimport) + #define LIBARDOUR_APICALLTYPE __stdcall + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#elif !defined(LIBARDOUR_API) + // Other compilers / platforms could be accommodated here + #define LIBARDOUR_API + #define LIBARDOUR_APICALLTYPE +#endif + +#ifndef _MAX_PATH +#define _MAX_PATH 260 +#endif +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif + +namespace ARDOUR { + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// LIBARDOUR_API char* LIBARDOUR_APICALLTYPE placeholder_for_non_msvc_specific_function(s); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +} // namespace ARDOUR + +#ifdef COMPILER_MSVC +#include <rpc.h> +//#include <io.h> + +#ifndef __THROW +#define __THROW throw() +#endif +#include <ardourext/sys/time.h> + +namespace ARDOUR { + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +LIBARDOUR_API int LIBARDOUR_APICALLTYPE symlink(const char *dest, const char *shortcut, const char *working_directory = 0); +LIBARDOUR_API int LIBARDOUR_APICALLTYPE readlink(const char *__restrict shortcut, char *__restrict buf, size_t bufsize); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +} // namespace ARDOUR + +#endif // COMPILER_MSVC +#endif // __mavc_libardour_h__ diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index b30b1859a3..024dcd150c 100644 --- a/libs/ardour/ardour/panner.h +++ b/libs/ardour/ardour/panner.h @@ -33,6 +33,14 @@ #include "ardour/types.h" #include "ardour/automation_control.h" #include "ardour/automatable.h" +#include "ardour/visibility.h" + +#ifdef ARDOURPANNER_DLL_EXPORTS // defined if we are building the ARDOUR Panners DLLs (instead of using them) + #define ARDOURPANNER_API LIBARDOUR_HELPER_DLL_EXPORT +#else + #define ARDOURPANNER_API LIBARDOUR_HELPER_DLL_IMPORT +#endif +#define ARDOURPANNER_LOCAL LIBARDOUR_HELPER_DLL_LOCAL namespace ARDOUR { diff --git a/libs/ardour/ardour/panner_manager.h b/libs/ardour/ardour/panner_manager.h index 016ba56ce3..c34d22285d 100644 --- a/libs/ardour/ardour/panner_manager.h +++ b/libs/ardour/ardour/panner_manager.h @@ -20,7 +20,8 @@ #ifndef __ardour_panner_manager_h__ #define __ardour_panner_manager_h__ -#include <dlfcn.h> +#include <glibmm/module.h> + #include "ardour/panner.h" #include "ardour/session_handle.h" @@ -28,15 +29,15 @@ namespace ARDOUR { struct PannerInfo { PanPluginDescriptor descriptor; - void* module; + Glib::Module* module; - PannerInfo (PanPluginDescriptor& d, void* handle) + PannerInfo (PanPluginDescriptor& d, Glib::Module* m) : descriptor (d) - , module (handle) + , module (m) {} ~PannerInfo () { - dlclose (module); + delete module; } }; diff --git a/libs/ardour/ardour/panner_search_path.h b/libs/ardour/ardour/panner_search_path.h index 889b9efb23..23004223b4 100644 --- a/libs/ardour/ardour/panner_search_path.h +++ b/libs/ardour/ardour/panner_search_path.h @@ -24,15 +24,15 @@ namespace ARDOUR { /** - * return a SearchPath containing directories in which to look for + * return a Searchpath containing directories in which to look for * panner plugins. * - * If ARDOUR_PANNER_PATH is defined then the SearchPath returned + * If ARDOUR_PANNER_PATH is defined then the Searchpath returned * will contain only those directories specified in it, otherwise it will * contain the user and system directories which may contain control * surface plugins. */ - PBD::SearchPath panner_search_path (); + PBD::Searchpath panner_search_path (); } // namespace ARDOUR diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 754e48cc25..fbe747b297 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -41,13 +41,13 @@ #include "evoral/types.hpp" #include "ardour/ardour.h" +#include "ardour/region.h" #include "ardour/session_object.h" #include "ardour/data_type.h" namespace ARDOUR { class Session; -class Region; class Playlist; class Crossfade; diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h index a7a5703690..2464368ae7 100644 --- a/libs/ardour/ardour/plugin_manager.h +++ b/libs/ardour/ardour/plugin_manager.h @@ -51,7 +51,6 @@ class PluginManager : public boost::noncopyable { void refresh (); - int add_ladspa_directory (std::string dirpath); int add_windows_vst_directory (std::string dirpath); int add_lxvst_directory (std::string dirpath); @@ -103,7 +102,6 @@ class PluginManager : public boost::noncopyable { std::map<uint32_t, std::string> rdf_type; - std::string ladspa_path; std::string windows_vst_path; std::string lxvst_path; @@ -127,7 +125,6 @@ class PluginManager : public boost::noncopyable { int lxvst_discover_from_path (std::string path); int lxvst_discover (std::string path); - int ladspa_discover_from_path (std::string path); int ladspa_discover (std::string path); std::string get_ladspa_category (uint32_t id); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index efe51e7b49..525dfbd849 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -822,7 +822,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void request_resume_timecode_transmission (); bool timecode_transmission_suspended () const; - std::string source_search_path(DataType) const; + std::vector<std::string> source_search_path(DataType) const; void ensure_search_path_includes (const std::string& path, DataType type); std::list<std::string> unknown_processors () const; diff --git a/libs/ardour/ardour/silentfilesource.h b/libs/ardour/ardour/silentfilesource.h index 5cdade3751..b8ac40e178 100644 --- a/libs/ardour/ardour/silentfilesource.h +++ b/libs/ardour/ardour/silentfilesource.h @@ -32,6 +32,7 @@ public: float sample_rate () const { return _sample_rate; } void set_length (framecnt_t len) { _length = len; } + void flush () {} bool destructive() const { return false; } bool can_be_analysed() const { return false; } diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h index 3f63f1c598..bed431c490 100644 --- a/libs/ardour/ardour/sndfilesource.h +++ b/libs/ardour/ardour/sndfilesource.h @@ -46,6 +46,7 @@ class SndFileSource : public AudioFileSource { float sample_rate () const; int update_header (framepos_t when, struct tm&, time_t); int flush_header (); + void flush (); framepos_t natural_position () const; diff --git a/libs/ardour/ardour/visibility.h b/libs/ardour/ardour/visibility.h new file mode 100644 index 0000000000..09287b877d --- /dev/null +++ b/libs/ardour/ardour/visibility.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2013 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 __libardour_visibility_h__ +#define __libardour_visibility_h__ + +/* _WIN32 is defined by most compilers targetting Windows, but within the + * ardour source tree, we also define COMPILER_MSVC or COMPILER_MINGW depending + * on how a Windows build is built. + */ + +#if defined _WIN32 || defined __CYGWIN__ || defined(COMPILER_MSVC) || defined(COMPILER_MINGW) + #define LIBARDOUR_HELPER_DLL_IMPORT __declspec(dllimport) + #define LIBARDOUR_HELPER_DLL_EXPORT __declspec(dllexport) + #define LIBARDOUR_HELPER_DLL_LOCAL +#else + #if __GNUC__ >= 4 + #define LIBARDOUR_HELPER_DLL_IMPORT __attribute__ ((visibility ("default"))) + #define LIBARDOUR_HELPER_DLL_EXPORT __attribute__ ((visibility ("default"))) + #define LIBARDOUR_HELPER_DLL_LOCAL __attribute__ ((visibility ("hidden"))) + #else + #define LIBARDOUR_HELPER_DLL_IMPORT + #define LIBARDOUR_HELPER_DLL_EXPORT + #define LIBARDOUR_HELPER_DLL_LOCAL + #endif +#endif + +#endif /* __libardour_visibility_h__ */ diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 35153b7fde..622a42edf2 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -27,8 +27,6 @@ #include <fcntl.h> #include <cstdlib> #include <ctime> -#include <sys/stat.h> -#include <sys/mman.h> #include "pbd/error.h" #include "pbd/xml++.h" @@ -925,7 +923,7 @@ AudioDiskstream::internal_playback_seek (framecnt_t distance) boost::shared_ptr<ChannelList> c = channels.reader(); for (chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->playback_buf->increment_read_ptr (std::llabs(distance)); + (*chan)->playback_buf->increment_read_ptr (llabs(distance)); } if (first_recordable_frame < max_framepos) { diff --git a/libs/ardour/audio_library.cc b/libs/ardour/audio_library.cc index c2b2f1bff7..4a6089dac3 100644 --- a/libs/ardour/audio_library.cc +++ b/libs/ardour/audio_library.cc @@ -17,11 +17,18 @@ */ +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + #include <sstream> #include <libxml/uri.h> +#ifdef HAVE_LRDF #include <lrdf.h> +#endif + #include <glibmm/miscutils.h> #include <glibmm/convert.h> @@ -57,7 +64,9 @@ AudioLibrary::AudioLibrary () touch_file(sfdb_file_path); +#ifdef HAVE_LRDF lrdf_read_file(src.c_str()); +#endif } AudioLibrary::~AudioLibrary () @@ -67,14 +76,17 @@ AudioLibrary::~AudioLibrary () void AudioLibrary::save_changes () { +#ifdef HAVE_LRDF if (lrdf_export_by_source(src.c_str(), src.substr(5).c_str())) { PBD::warning << string_compose(_("Could not open %1. Audio Library not saved"), src) << endmsg; } +#endif } void AudioLibrary::set_tags (string member, vector<string> tags) { +#ifdef HAVE_LRDF sort (tags.begin(), tags.end()); tags.erase (unique(tags.begin(), tags.end()), tags.end()); @@ -85,12 +97,14 @@ AudioLibrary::set_tags (string member, vector<string> tags) for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) { lrdf_add_triple (src.c_str(), file_uri.c_str(), TAG, (*i).c_str(), lrdf_literal); } +#endif } vector<string> AudioLibrary::get_tags (string member) { vector<string> tags; +#ifdef HAVE_LRDF lrdf_statement pattern; pattern.subject = strdup(Glib::filename_to_uri(member).c_str()); @@ -111,13 +125,14 @@ AudioLibrary::get_tags (string member) lrdf_free_statements (matches); sort (tags.begin(), tags.end()); - +#endif return tags; } void AudioLibrary::search_members_and (vector<string>& members, const vector<string>& tags) { +#ifdef HAVE_LRDF lrdf_statement **head; lrdf_statement* pattern = 0; lrdf_statement* old = 0; @@ -153,4 +168,5 @@ AudioLibrary::search_members_and (vector<string>& members, const vector<string>& pattern = pattern->next; delete old; } +#endif } diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 2e697a95cc..0530dbfce9 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -315,7 +315,7 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram if (!lm.locked()) { boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream(); framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes); - if (can_internal_playback_seek(std::llabs(playback_distance))) { + if (can_internal_playback_seek(llabs(playback_distance))) { /* TODO should declick */ internal_playback_seek(playback_distance); } diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 538a905ca2..1a24977399 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -34,6 +34,7 @@ #include <glibmm/threads.h> #include <glibmm/fileutils.h> #include <glibmm/miscutils.h> +#include <glib/gstdio.h> #include "ardour/ardour.h" #include "ardour/audioengine.h" @@ -2453,7 +2454,7 @@ AUPluginInfo::save_cached_info () if (!tree.write (path)) { error << string_compose (_("could not save AU cache to %1"), path) << endmsg; - unlink (path.c_str()); + g_unlink (path.c_str()); } } diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 08de54960c..5e3e5ba9e2 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -31,8 +31,6 @@ #include "pbd/unknown_type.h" #include "pbd/epa.h" -#include <jack/weakjack.h> - #include "midi++/port.h" #include "midi++/jack_midi_port.h" #include "midi++/mmc.h" @@ -1548,7 +1546,7 @@ AudioEngine::is_realtime () const } int -AudioEngine::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize) +AudioEngine::create_process_thread (boost::function<void()> f, jack_native_thread_t* thread, size_t stacksize) { GET_PRIVATE_JACK_POINTER_RET (_jack, 0); ThreadData* td = new ThreadData (this, f, stacksize); @@ -1561,6 +1559,28 @@ AudioEngine::create_process_thread (boost::function<void()> f, pthread_t* thread return 0; } +bool +AudioEngine::stop_process_thread (jack_native_thread_t thread) +{ + /** + * can't use GET_PRIVATE_JACK_POINTER_RET (_jack, 0) here + * because _jack is 0 when this is called. At least for + * Jack 2 _jack arg is not used so it should be OK + */ + +#if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined(PLATFORM_WINDOWS) + if (jack_client_stop_thread (_jack, thread) != 0) { + error << "AudioEngine: cannot stop process thread" << endmsg; + return false; + } +#else + void* status; + pthread_join (thread, &status); +#endif + + return true; +} + void* AudioEngine::_start_process_thread (void* arg) { @@ -1604,10 +1624,8 @@ AudioEngine::request_jack_monitors_input (const std::string& portname, bool yn) void AudioEngine::update_latencies () { - if (jack_recompute_total_latencies) { - GET_PRIVATE_JACK_POINTER (_jack); - jack_recompute_total_latencies (_priv_jack); - } + GET_PRIVATE_JACK_POINTER (_jack); + jack_recompute_total_latencies (_priv_jack); } void diff --git a/libs/ardour/audiofile_tagger.cc b/libs/ardour/audiofile_tagger.cc index 57650860ee..53b9afdd3e 100644 --- a/libs/ardour/audiofile_tagger.cc +++ b/libs/ardour/audiofile_tagger.cc @@ -25,11 +25,11 @@ #include "pbd/convert.h" #include "taglib/fileref.h" -#include "taglib/flacfile.h" -#include "taglib/oggfile.h" +#include "taglib/flac/flacfile.h" +#include "taglib/ogg/oggfile.h" #include "taglib/tag.h" -#include "taglib/taglib.h" -#include "taglib/xiphcomment.h" +#include "taglib/toolkit/taglib.h" +#include "taglib/ogg/xiphcomment.h" /* Convert string to TagLib::String */ #define TL_STR(string) TagLib::String ((string).c_str(), TagLib::String::UTF8) diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc index 13b03f8f48..014baa9031 100644 --- a/libs/ardour/audiofilesource.cc +++ b/libs/ardour/audiofilesource.cc @@ -40,6 +40,7 @@ #include <sndfile.h> +#include <glib/gstdio.h> #include <glibmm/miscutils.h> #include <glibmm/fileutils.h> #include <glibmm/threads.h> @@ -133,8 +134,8 @@ AudioFileSource::~AudioFileSource () { DEBUG_TRACE (DEBUG::Destruction, string_compose ("AudioFileSource destructor %1, removable? %2\n", _path, removable())); if (removable()) { - unlink (_path.c_str()); - unlink (peakpath.c_str()); + ::g_unlink (_path.c_str()); + ::g_unlink (peakpath.c_str()); } } @@ -292,7 +293,7 @@ AudioFileSource::mark_streaming_write_completed () int AudioFileSource::move_dependents_to_trash() { - return ::unlink (peakpath.c_str()); + return ::g_unlink (peakpath.c_str()); } void diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index 84a5b687f9..1dce801884 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -17,12 +17,15 @@ */ -#include <sys/stat.h> +#ifdef COMPILER_MSVC +#include <sys/utime.h> +#else #include <unistd.h> +#include <utime.h> +#endif +#include <sys/stat.h> #include <fcntl.h> -#include <poll.h> #include <float.h> -#include <utime.h> #include <cerrno> #include <ctime> #include <cmath> @@ -31,6 +34,12 @@ #include <algorithm> #include <vector> +#include <glib.h> +#include <glib/gstdio.h> + +#include <boost/scoped_array.hpp> +#include <boost/scoped_ptr.hpp> + #include <glibmm/fileutils.h> #include <glibmm/miscutils.h> @@ -42,6 +51,8 @@ #include "i18n.h" +#include "ardour/debug.h" + using namespace std; using namespace ARDOUR; using namespace PBD; @@ -173,9 +184,9 @@ AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnect void AudioSource::touch_peakfile () { - struct stat statbuf; + GStatBuf statbuf; - if (stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) { + if (g_stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) { return; } @@ -184,7 +195,7 @@ AudioSource::touch_peakfile () tbuf.actime = statbuf.st_atime; tbuf.modtime = time ((time_t*) 0); - utime (peakpath.c_str(), &tbuf); + g_utime (peakpath.c_str(), &tbuf); } int @@ -195,7 +206,7 @@ AudioSource::rename_peakfile (string newpath) string oldpath = peakpath; if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) { - if (rename (oldpath.c_str(), newpath.c_str()) != 0) { + if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) { error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg; return -1; } @@ -209,17 +220,19 @@ AudioSource::rename_peakfile (string newpath) int AudioSource::initialize_peakfile (string audio_path) { - struct stat statbuf; + GStatBuf statbuf; peakpath = peak_path (audio_path); + DEBUG_TRACE(DEBUG::Peaks, string_compose ("Initialize Peakfile %1 for Audio file %2\n", peakpath, audio_path)); + /* if the peak file should be there, but isn't .... */ if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) { peakpath = find_broken_peakfile (peakpath, audio_path); } - if (stat (peakpath.c_str(), &statbuf)) { + if (g_stat (peakpath.c_str(), &statbuf)) { if (errno != ENOENT) { /* it exists in the peaks dir, but there is some kind of error */ @@ -227,7 +240,7 @@ AudioSource::initialize_peakfile (string audio_path) return -1; } - /* peakfile does not exist */ + DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 does not exist\n", peakpath)); _peaks_built = false; @@ -236,7 +249,7 @@ AudioSource::initialize_peakfile (string audio_path) /* we found it in the peaks dir, so check it out */ if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) { - // empty + DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", peakpath)); _peaks_built = false; } else { // Check if the audio file has changed since the peakfile was built. @@ -248,6 +261,7 @@ AudioSource::initialize_peakfile (string audio_path) /* no audio path - nested source or we can't read it or ... whatever, use the peakfile as-is. */ + DEBUG_TRACE(DEBUG::Peaks, string_compose("Error when calling stat on Peakfile %1\n", peakpath)); _peaks_built = true; _peak_byte_max = statbuf.st_size; @@ -316,28 +330,15 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t int32_t to_read; uint32_t nread; framecnt_t zero_fill = 0; - int ret = -1; - PeakData* staging = 0; - Sample* raw_staging = 0; - FdFileDescriptor* peakfile_descriptor = new FdFileDescriptor (peakpath, false, 0664); + boost::scoped_ptr<FdFileDescriptor> peakfile_descriptor(new FdFileDescriptor (peakpath, false, 0664)); int peakfile_fd = -1; expected_peaks = (cnt / (double) samples_per_file_peak); scale = npeaks/expected_peaks; -#undef DEBUG_READ_PEAKS -#ifdef DEBUG_READ_PEAKS - cerr << "======>RP: npeaks = " << npeaks - << " start = " << start - << " cnt = " << cnt - << " len = " << _length - << " samples_per_visual_peak =" << samples_per_visual_peak - << " expected was " << expected_peaks << " ... scale = " << scale - << " PD ptr = " << peaks - <<endl; - -#endif + DEBUG_TRACE (DEBUG::Peaks, string_compose (" ======>RP: npeaks = %1 start = %2 cnt = %3 len = %4 samples_per_visual_peak = %5 expected was %6 ... scale = %7 PD ptr = %8\n" + , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks)); /* fix for near-end-of-file conditions */ @@ -353,16 +354,15 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t if (npeaks == cnt) { -#ifdef DEBUG_READ_PEAKS - cerr << "RAW DATA\n"; -#endif + DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n"); + /* no scaling at all, just get the sample data and duplicate it for both max and min peak values. */ - Sample* raw_staging = new Sample[cnt]; + boost::scoped_array<Sample> raw_staging(new Sample[cnt]); - if (read_unlocked (raw_staging, start, cnt) != cnt) { + if (read_unlocked (raw_staging.get(), start, cnt) != cnt) { error << _("cannot read sample data for unscaled peak computation") << endmsg; return -1; } @@ -372,43 +372,35 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t peaks[i].min = raw_staging[i]; } - delete peakfile_descriptor; - delete [] raw_staging; return 0; } if (scale == 1.0) { + off_t offset = 0; off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData); - + ssize_t bytes_to_read = sizeof (PeakData)* npeaks; /* open, read, close */ if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) { error << string_compose(_("AudioSource: cannot open peakpath (a) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg; - delete peakfile_descriptor; return -1; } -#ifdef DEBUG_READ_PEAKS - cerr << "DIRECT PEAKS\n"; -#endif + DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n"); - nread = ::pread (peakfile_fd, peaks, sizeof (PeakData)* npeaks, first_peak_byte); - - if (nread != sizeof (PeakData) * npeaks) { - cerr << "AudioSource[" - << _name - << "]: cannot read peaks from peakfile! (read only " - << nread - << " not " - << npeaks - << "at sample " - << start - << " = byte " - << first_peak_byte - << ')' - << endl; - delete peakfile_descriptor; + offset = lseek (peakfile_fd, first_peak_byte, SEEK_SET); + + if (offset != first_peak_byte) { + error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg; + return -1; + } + + nread = ::read (peakfile_fd, peaks, bytes_to_read); + + if (nread != bytes_to_read) { + DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: Cannot read peaks from peakfile! (read only %2 not %3 at sample %4 = byte %5 )\n" + , _name, nread, npeaks, start, first_peak_byte)); return -1; } @@ -416,7 +408,6 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill); } - delete peakfile_descriptor; return 0; } @@ -425,9 +416,8 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t if (scale < 1.0) { -#ifdef DEBUG_READ_PEAKS - cerr << "DOWNSAMPLE\n"; -#endif + DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n"); + /* the caller wants: - more frames-per-peak (lower resolution) than the peakfile, or to put it another way, @@ -440,7 +430,7 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0); - staging = new PeakData[chunksize]; + boost::scoped_array<PeakData> staging(new PeakData[chunksize]); /* compute the rounded up frame position */ @@ -461,8 +451,6 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) { error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg; - delete peakfile_descriptor; - delete [] staging; return 0; } @@ -473,33 +461,27 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t uint32_t start_byte = current_stored_peak * sizeof(PeakData); tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks); to_read = min (chunksize, tnp); + ssize_t bytes_to_read = sizeof (PeakData) * to_read; -#ifdef DEBUG_READ_PEAKS - cerr << "read " << sizeof (PeakData) * to_read << " from peakfile @ " << start_byte << endl; -#endif + DEBUG_TRACE (DEBUG::Peaks, string_compose ("reading %1 bytes from peakfile @ %2\n" + , bytes_to_read, start_byte)); - if ((nread = ::pread (peakfile_fd, staging, sizeof (PeakData) * to_read, start_byte)) - != sizeof (PeakData) * to_read) { - off_t fend = lseek (peakfile_fd, 0, SEEK_END); + off_t offset = lseek (peakfile_fd, start_byte, SEEK_SET); - cerr << "AudioSource[" - << _name - << "]: cannot read peak data from peakfile (" - << (nread / sizeof(PeakData)) - << " peaks instead of " - << to_read - << ") (" - << strerror (errno) - << ')' - << " at start_byte = " << start_byte - << " _length = " << _length << " versus len = " << fend - << " expected maxpeaks = " << (_length - current_frame)/samples_per_file_peak - << " npeaks was " << npeaks - << endl; - goto out; + if (offset != start_byte) { + error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg; + return -1; } + if ((nread = ::read (peakfile_fd, staging.get(), bytes_to_read)) != bytes_to_read) { + + off_t fend = lseek (peakfile_fd, 0, SEEK_END); + + DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: cannot read peak data from peakfile (%2 peaks instead of %3) (%4) at start_byte = %5 _length = %6 versus len = %7 expected maxpeaks = %8 npeaks was %9" + , _name, (nread / sizeof(PeakData)), to_read, g_strerror (errno), start_byte, _length, fend, ((_length - current_frame)/samples_per_file_peak), npeaks)); + return -1; + } i = 0; stored_peaks_read = nread / sizeof(PeakData); } @@ -530,13 +512,10 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill); } - ret = 0; - } else { -#ifdef DEBUG_READ_PEAKS - cerr << "UPSAMPLE\n"; -#endif + DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n"); + /* the caller wants - less frames-per-peak (more resolution) @@ -551,7 +530,7 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t framecnt_t i = 0; framecnt_t nvisual_peaks = 0; framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096); - raw_staging = new Sample[chunksize]; + boost::scoped_array<Sample> raw_staging(new Sample[chunksize]); framepos_t frame_pos = start; double pixel_pos = floor (frame_pos / samples_per_visual_peak); @@ -576,18 +555,18 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t this loop early */ - memset (raw_staging, 0, sizeof (Sample) * chunksize); + memset (raw_staging.get(), 0, sizeof (Sample) * chunksize); } else { to_read = min (chunksize, (_length - current_frame)); - if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) { + if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) { error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"), _name, to_read, current_frame, _length, strerror (errno)) << endmsg; - goto out; + return -1; } } @@ -615,32 +594,19 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t if (zero_fill) { memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill); } - - ret = 0; } - out: - delete peakfile_descriptor; - - delete [] staging; - delete [] raw_staging; - -#ifdef DEBUG_READ_PEAKS - cerr << "RP DONE\n"; -#endif - - return ret; + DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n"); + return 0; } -#undef DEBUG_PEAK_BUILD - int AudioSource::build_peaks_from_scratch () { - Sample* buf = 0; - const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal + DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n"); + int ret = -1; { @@ -656,20 +622,20 @@ AudioSource::build_peaks_from_scratch () framecnt_t cnt = _length; _peaks_built = false; - buf = new Sample[bufsize]; + boost::scoped_array<Sample> buf(new Sample[bufsize]); while (cnt) { framecnt_t frames_to_read = min (bufsize, cnt); framecnt_t frames_read; - if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) { + if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) { error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg; done_with_peakfile_writes (false); goto out; } - if (compute_and_write_peaks (buf, current_frame, frames_read, true, false, _FPP)) { + if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) { break; } @@ -690,11 +656,10 @@ AudioSource::build_peaks_from_scratch () out: if (ret) { - unlink (peakpath.c_str()); + DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath)); + ::g_unlink (peakpath.c_str()); } - delete [] buf; - return ret; } @@ -738,15 +703,13 @@ int AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt, bool force, bool intermediate_peaks_ready, framecnt_t fpp) { - Sample* buf2 = 0; framecnt_t to_do; uint32_t peaks_computed; - PeakData* peakbuf = 0; - int ret = -1; framepos_t current_frame; framecnt_t frames_done; const size_t blocksize = (128 * 1024); off_t first_peak_byte; + boost::scoped_array<Sample> buf2; if (_peakfile_descriptor == 0) { prepare_for_peakfile_writes (); @@ -769,9 +732,16 @@ AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, frame off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData); - if (::pwrite (_peakfile_fd, &x, sizeof (PeakData), byte) != sizeof (PeakData)) { + off_t offset = lseek (_peakfile_fd, byte, SEEK_SET); + + if (offset != byte) { + error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg; + return -1; + } + + if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) { error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg; - goto out; + return -1; } _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData))); @@ -797,19 +767,19 @@ AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, frame /* make a new contiguous buffer containing leftovers and the new stuff */ to_do = cnt + peak_leftover_cnt; - buf2 = new Sample[to_do]; + buf2.reset(new Sample[to_do]); /* the remnants */ - memcpy (buf2, peak_leftovers, peak_leftover_cnt * sizeof (Sample)); + memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample)); /* the new stuff */ - memcpy (buf2+peak_leftover_cnt, buf, cnt * sizeof (Sample)); + memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample)); /* no more leftovers */ peak_leftover_cnt = 0; /* use the temporary buffer */ - buf = buf2; + buf = buf2.get(); /* make sure that when we write into the peakfile, we startup where we left off */ @@ -819,7 +789,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, frame to_do = cnt; } - peakbuf = new PeakData[(to_do/fpp)+1]; + boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]); peaks_computed = 0; current_frame = first_frame; frames_done = 0; @@ -876,18 +846,31 @@ AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, frame off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize); if (endpos < target_length) { + DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath)); if (ftruncate (_peakfile_fd, target_length)) { /* error doesn't actually matter so continue on without testing */ } } } - if (::pwrite (_peakfile_fd, peakbuf, sizeof (PeakData) * peaks_computed, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaks_computed)) { + + off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET); + + if (offset != first_peak_byte) { + error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg; + return -1; + } + + ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed; + + ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write); + + if (bytes_written != bytes_to_write) { error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg; - goto out; + return -1; } - _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaks_computed)); + _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write)); if (frames_done) { Glib::Threads::Mutex::Lock lm (_peaks_ready_lock); @@ -897,13 +880,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, frame } } - ret = 0; - - out: - delete [] peakbuf; - delete [] buf2; - - return ret; + return 0; } void @@ -920,6 +897,7 @@ AudioSource::truncate_peakfile () off_t end = lseek (_peakfile_fd, 0, SEEK_END); if (end > _peak_byte_max) { + DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath)); if (ftruncate (_peakfile_fd, _peak_byte_max)) { error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"), peakpath, _peak_byte_max, errno) << endmsg; diff --git a/libs/ardour/automation_watch.cc b/libs/ardour/automation_watch.cc index 16e10c95f9..91fe4d38ed 100644 --- a/libs/ardour/automation_watch.cc +++ b/libs/ardour/automation_watch.cc @@ -19,6 +19,8 @@ #include <iostream> +#include <glibmm/timer.h> + #include "pbd/compose.h" #include "ardour/automation_control.h" @@ -134,7 +136,7 @@ void AutomationWatch::thread () { while (_run_thread) { - usleep ((useconds_t) floor (Config->get_automation_interval_msecs() * 1000)); + Glib::usleep ((gulong) floor (Config->get_automation_interval_msecs() * 1000)); timer (); } } diff --git a/libs/ardour/broadcast_info.cc b/libs/ardour/broadcast_info.cc index a7fa41aaf9..a08d2c7991 100644 --- a/libs/ardour/broadcast_info.cc +++ b/libs/ardour/broadcast_info.cc @@ -22,6 +22,7 @@ #include <iostream> #include <sstream> #include <iomanip> +#include <vector> #include <glibmm.h> @@ -37,15 +38,15 @@ namespace ARDOUR static void snprintf_bounded_null_filled (char* target, size_t target_size, char const * fmt, ...) { - char buf[target_size+1]; + std::vector<char> buf(target_size+1); va_list ap; va_start (ap, fmt); - vsnprintf (buf, target_size+1, fmt, ap); + vsnprintf (&buf[0], target_size+1, fmt, ap); va_end (ap); memset (target, 0, target_size); - memcpy (target, buf, target_size); + memcpy (target, &buf[0], target_size); } @@ -84,7 +85,7 @@ BroadcastInfo::set_originator_ref_from_session (Session const & /*session*/) /* random code is 9 digits */ - int random_code = random() % 999999999; + int random_code = g_random_int() % 999999999; /* Serial number is 12 chars */ diff --git a/libs/ardour/butler.cc b/libs/ardour/butler.cc index 89b2cc1303..1fe1524618 100644 --- a/libs/ardour/butler.cc +++ b/libs/ardour/butler.cc @@ -20,7 +20,11 @@ #include <errno.h> #include <fcntl.h> #include <unistd.h> + +#ifndef PLATFORM_WINDOWS #include <poll.h> +#endif + #include "pbd/error.h" #include "pbd/pthread_utils.h" #include "ardour/butler.h" @@ -38,7 +42,7 @@ namespace ARDOUR { Butler::Butler(Session& s) : SessionHandleRef (s) - , thread(0) + , thread() , audio_dstream_capture_buffer_size(0) , audio_dstream_playback_buffer_size(0) , midi_dstream_buffer_size(0) @@ -68,25 +72,10 @@ Butler::config_changed (std::string p) } } +#ifndef PLATFORM_WINDOWS int -Butler::start_thread() +Butler::setup_request_pipe () { - const float rate = (float)_session.frame_rate(); - - /* size is in Samples, not bytes */ - audio_dstream_capture_buffer_size = (uint32_t) floor (Config->get_audio_capture_buffer_seconds() * rate); - audio_dstream_playback_buffer_size = (uint32_t) floor (Config->get_audio_playback_buffer_seconds() * rate); - - /* size is in bytes - * XXX: Jack needs to tell us the MIDI buffer size - * (i.e. how many MIDI bytes we might see in a cycle) - */ - midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * rate); - - MidiDiskstream::set_readahead_frames ((framecnt_t) (Config->get_midi_readahead() * rate)); - - should_run = false; - if (pipe (request_pipe)) { error << string_compose(_("Cannot create transport request signal pipe (%1)"), strerror (errno)) << endmsg; @@ -104,6 +93,32 @@ Butler::start_thread() strerror (errno)) << endmsg; return -1; } + return 0; +} +#endif + +int +Butler::start_thread() +{ + const float rate = (float)_session.frame_rate(); + + /* size is in Samples, not bytes */ + audio_dstream_capture_buffer_size = (uint32_t) floor (Config->get_audio_capture_buffer_seconds() * rate); + audio_dstream_playback_buffer_size = (uint32_t) floor (Config->get_audio_playback_buffer_seconds() * rate); + + /* size is in bytes + * XXX: Jack needs to tell us the MIDI buffer size + * (i.e. how many MIDI bytes we might see in a cycle) + */ + midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * rate); + + MidiDiskstream::set_readahead_frames ((framecnt_t) (Config->get_midi_readahead() * rate)); + + should_run = false; + +#ifndef PLATFORM_WINDOWS + if (setup_request_pipe() != 0) return -1; +#endif if (pthread_create_and_store ("disk butler", &thread, _thread_work, this)) { error << _("Session: could not create butler thread") << endmsg; @@ -118,12 +133,9 @@ Butler::start_thread() void Butler::terminate_thread () { - if (thread) { - void* status; - const char c = Request::Quit; - (void) ::write (request_pipe[1], &c, 1); - pthread_join (thread, &status); - } + void* status; + queue_request (Request::Quit); + pthread_join (thread, &status); } void * @@ -134,28 +146,25 @@ Butler::_thread_work (void* arg) return ((Butler *) arg)->thread_work (); } -void * -Butler::thread_work () +bool +Butler::wait_for_requests () { - uint32_t err = 0; - +#ifndef PLATFORM_WINDOWS struct pollfd pfd[1]; - bool disk_work_outstanding = false; - RouteList::iterator i; - while (true) { - pfd[0].fd = request_pipe[0]; - pfd[0].events = POLLIN|POLLERR|POLLHUP; + pfd[0].fd = request_pipe[0]; + pfd[0].events = POLLIN|POLLERR|POLLHUP; - if (poll (pfd, 1, (disk_work_outstanding ? 0 : -1)) < 0) { + while(true) { + if (poll (pfd, 1, -1) < 0) { if (errno == EINTR) { continue; } error << string_compose (_("poll on butler request pipe failed (%1)"), - strerror (errno)) - << endmsg; + strerror (errno)) + << endmsg; break; } @@ -165,16 +174,60 @@ Butler::thread_work () } if (pfd[0].revents & POLLIN) { + return true; + } + } + return false; +#else + m_request_sem.wait (); + return true; +#endif +} - char req; +bool +Butler::dequeue_request (Request::Type& r) +{ +#ifndef PLATFORM_WINDOWS + char req; + size_t nread = ::read (request_pipe[0], &req, sizeof (req)); + if (nread == 1) { + r = (Request::Type) req; + return true; + } else if (nread == 0) { + return false; + } else if (errno == EAGAIN) { + return false; + } else { + fatal << _("Error reading from butler request pipe") << endmsg; + /*NOTREACHED*/ + } +#else + r = (Request::Type) m_request_state.get(); +#endif + return false; +} - /* empty the pipe of all current requests */ + void * +Butler::thread_work () +{ + uint32_t err = 0; - while (1) { - size_t nread = ::read (request_pipe[0], &req, sizeof (req)); - if (nread == 1) { + bool disk_work_outstanding = false; + RouteList::iterator i; - switch ((Request::Type) req) { + while (true) { + if(!disk_work_outstanding) { + if (wait_for_requests ()) { + Request::Type req; + + /* empty the pipe of all current requests */ +#ifdef PLATFORM_WINDOWS + dequeue_request (req); + { +#else + while(dequeue_request(req)) { +#endif + switch (req) { case Request::Run: should_run = true; @@ -192,14 +245,6 @@ Butler::thread_work () default: break; } - - } else if (nread == 0) { - break; - } else if (errno == EAGAIN) { - break; - } else { - fatal << _("Error reading from butler request pipe") << endmsg; - /*NOTREACHED*/ } } } @@ -338,18 +383,28 @@ Butler::schedule_transport_work () } void -Butler::summon () +Butler::queue_request (Request::Type r) { - char c = Request::Run; +#ifndef PLATFORM_WINDOWS + char c = r; (void) ::write (request_pipe[1], &c, 1); +#else + m_request_state.set (r); + m_request_sem.post (); +#endif +} + +void +Butler::summon () +{ + queue_request (Request::Run); } void Butler::stop () { Glib::Threads::Mutex::Lock lm (request_lock); - char c = Request::Pause; - (void) ::write (request_pipe[1], &c, 1); + queue_request (Request::Pause); paused.wait(request_lock); } @@ -357,8 +412,7 @@ void Butler::wait_until_finished () { Glib::Threads::Mutex::Lock lm (request_lock); - char c = Request::Pause; - (void) ::write (request_pipe[1], &c, 1); + queue_request (Request::Pause); paused.wait(request_lock); } diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc index 2e65a8d6f8..06c9c72cb4 100644 --- a/libs/ardour/control_protocol_manager.cc +++ b/libs/ardour/control_protocol_manager.cc @@ -17,7 +17,7 @@ */ -#include <dlfcn.h> +#include <glibmm/module.h> #include <glibmm/fileutils.h> @@ -29,8 +29,10 @@ #include "ardour/debug.h" #include "ardour/control_protocol_manager.h" + #include "ardour/control_protocol_search_path.h" + using namespace ARDOUR; using namespace std; using namespace PBD; @@ -179,7 +181,7 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi) cpi.protocol = 0; delete cpi.state; cpi.state = 0; - dlclose (cpi.descriptor->module); + delete (Glib::Module*)cpi.descriptor->module; ProtocolStatusChange (&cpi); @@ -264,7 +266,7 @@ ControlProtocolManager::control_protocol_discover (string path) string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name)); } - dlclose (descriptor->module); + delete (Glib::Module*)descriptor->module; } return 0; @@ -273,31 +275,31 @@ ControlProtocolManager::control_protocol_discover (string path) ControlProtocolDescriptor* ControlProtocolManager::get_descriptor (string path) { - void *module; + Glib::Module* module = new Glib::Module(path); ControlProtocolDescriptor *descriptor = 0; ControlProtocolDescriptor* (*dfunc)(void); - const char *errstr; + void* func = 0; - if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { - error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg; + if (!(*module)) { + error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg; + delete module; return 0; } - - dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor"); - - if ((errstr = dlerror()) != 0) { + if (!module->get_symbol("protocol_descriptor", func)) { error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg; - error << errstr << endmsg; - dlclose (module); + error << Glib::Module::get_last_error() << endmsg; + delete module; return 0; } + dfunc = (ControlProtocolDescriptor* (*)(void))func; descriptor = dfunc(); + if (descriptor) { - descriptor->module = module; + descriptor->module = (void*)module; } else { - dlclose (module); + delete module; } return descriptor; diff --git a/libs/ardour/control_protocol_search_path.cc b/libs/ardour/control_protocol_search_path.cc index 254cd03fe9..c5c5d0ba00 100644 --- a/libs/ardour/control_protocol_search_path.cc +++ b/libs/ardour/control_protocol_search_path.cc @@ -33,14 +33,14 @@ using namespace PBD; namespace ARDOUR { -SearchPath +Searchpath control_protocol_search_path () { - SearchPath spath(user_config_directory ()); + Searchpath spath(user_config_directory ()); spath += ardour_dll_directory (); spath.add_subdirectory_to_paths (surfaces_dir_name); - spath += SearchPath(Glib::getenv(surfaces_env_variable_name)); + spath += Searchpath(Glib::getenv(surfaces_env_variable_name)); return spath; } diff --git a/libs/ardour/debug.cc b/libs/ardour/debug.cc index afd5da2169..51115001cb 100644 --- a/libs/ardour/debug.cc +++ b/libs/ardour/debug.cc @@ -31,6 +31,7 @@ uint64_t PBD::DEBUG::MidiDiskstreamIO = PBD::new_debug_bit ("mididiskstreamio"); uint64_t PBD::DEBUG::SnapBBT = PBD::new_debug_bit ("snapbbt"); uint64_t PBD::DEBUG::Configuration = PBD::new_debug_bit ("configuration"); uint64_t PBD::DEBUG::Latency = PBD::new_debug_bit ("latency"); +uint64_t PBD::DEBUG::Peaks = PBD::new_debug_bit ("peaks"); uint64_t PBD::DEBUG::Processors = PBD::new_debug_bit ("processors"); uint64_t PBD::DEBUG::ProcessThreads = PBD::new_debug_bit ("processthreads"); uint64_t PBD::DEBUG::Graph = PBD::new_debug_bit ("graph"); diff --git a/libs/ardour/default_click.cc b/libs/ardour/default_click.cc index fd23f0166d..7e8eca8fd2 100644 --- a/libs/ardour/default_click.cc +++ b/libs/ardour/default_click.cc @@ -21,6 +21,10 @@ #include "ardour/session.h" #include "ardour/types.h" +#ifdef COMPILER_MSVC +#pragma warning(disable:4305) +#endif + using namespace ARDOUR; const Sample Session::default_click_emphasis[] = { diff --git a/libs/ardour/directory_names.cc b/libs/ardour/directory_names.cc index 0632c6f8f2..6fb15eaabd 100644 --- a/libs/ardour/directory_names.cc +++ b/libs/ardour/directory_names.cc @@ -36,6 +36,7 @@ const char* const export_formats_dir_name = X_("export"); const char* const templates_dir_name = X_("templates"); const char* const route_templates_dir_name = X_("route_templates"); const char* const surfaces_dir_name = X_("surfaces"); +const char* const ladspa_dir_name = X_("ladspa"); const char* const panner_dir_name = X_("panners"); /* these should end up using variants of PROGRAM_NAME */ diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index a359f228e8..e046d5a830 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -29,7 +29,6 @@ #include <cstdlib> #include <ctime> #include <sys/stat.h> -#include <sys/mman.h> #include <glibmm/threads.h> @@ -571,7 +570,7 @@ Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, list< Evora set<Evoral::Parameter> const a = processor->what_can_be_automated (); - for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) { + for (set<Evoral::Parameter>::const_iterator i = a.begin (); i != a.end (); ++i) { boost::shared_ptr<AutomationList> al = processor->automation_control(*i)->alist(); XMLNode & before = al->get_state (); bool const things_moved = al->move_ranges (movements); @@ -601,7 +600,7 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record) */ rolling = _session.transport_speed() != 0.0f; - possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record; + possibly_recording = (rolling << 2) | ((int)record_enabled() << 1) | (int)can_record; change = possibly_recording ^ last_possibly_recording; if (possibly_recording == last_possibly_recording) { diff --git a/libs/ardour/export_format_base.cc b/libs/ardour/export_format_base.cc index ed8bb9d5f8..1eda449915 100644 --- a/libs/ardour/export_format_base.cc +++ b/libs/ardour/export_format_base.cc @@ -185,7 +185,7 @@ ExportFormatBase::nearest_sample_rate (framecnt_t sample_rate) SampleRate best_match = SR_None; #define DO_SR_COMPARISON(rate) \ - diff = std::fabs((rate) - sample_rate); \ + diff = std::fabs((double)((rate) - sample_rate)); \ if(diff < smallest_diff) { \ smallest_diff = diff; \ best_match = (rate); \ diff --git a/libs/ardour/export_formats_search_path.cc b/libs/ardour/export_formats_search_path.cc index cf18b14a18..ffa096d33a 100644 --- a/libs/ardour/export_formats_search_path.cc +++ b/libs/ardour/export_formats_search_path.cc @@ -32,14 +32,14 @@ using namespace PBD; namespace ARDOUR { -SearchPath +Searchpath export_formats_search_path () { - SearchPath spath (ardour_data_search_path()); + Searchpath spath (ardour_data_search_path()); spath.add_subdirectory_to_paths (export_formats_dir_name); bool export_formats_path_defined = false; - SearchPath spath_env (Glib::getenv(export_env_variable_name, export_formats_path_defined)); + Searchpath spath_env (Glib::getenv(export_env_variable_name, export_formats_path_defined)); if (export_formats_path_defined) { spath += spath_env; diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc index c7875c0b9b..127546e8fc 100644 --- a/libs/ardour/export_graph_builder.cc +++ b/libs/ardour/export_graph_builder.cc @@ -20,6 +20,8 @@ #include "ardour/export_graph_builder.h" +#include <vector> + #include <glibmm/miscutils.h> #include "audiographer/process_context.h" @@ -317,8 +319,8 @@ ExportGraphBuilder::Normalizer::Normalizer (ExportGraphBuilder & parent, FileSpe { std::string tmpfile_path = parent.session.session_directory().export_path(); tmpfile_path = Glib::build_filename(tmpfile_path, "XXXXXX"); - char tmpfile_path_buf[tmpfile_path.size() + 1]; - std::copy(tmpfile_path.begin(), tmpfile_path.end(), tmpfile_path_buf); + std::vector<char> tmpfile_path_buf(tmpfile_path.size() + 1); + std::copy(tmpfile_path.begin(), tmpfile_path.end(), tmpfile_path_buf.begin()); tmpfile_path_buf[tmpfile_path.size()] = '\0'; config = new_config; @@ -334,7 +336,7 @@ ExportGraphBuilder::Normalizer::Normalizer (ExportGraphBuilder & parent, FileSpe normalizer->add_output (threader); int format = ExportFormatBase::F_RAW | ExportFormatBase::SF_Float; - tmp_file.reset (new TmpFile<float> (tmpfile_path_buf, format, channels, config.format->sample_rate())); + tmp_file.reset (new TmpFile<float> (&tmpfile_path_buf[0], format, channels, config.format->sample_rate())); tmp_file->FileWritten.connect_same_thread (post_processing_connection, boost::bind (&Normalizer::start_post_processing, this)); diff --git a/libs/ardour/export_handler.cc b/libs/ardour/export_handler.cc index 4a6b0552c5..5710ecc452 100644 --- a/libs/ardour/export_handler.cc +++ b/libs/ardour/export_handler.cc @@ -20,6 +20,7 @@ #include "ardour/export_handler.h" +#include <glib/gstdio.h> #include <glibmm.h> #include <glibmm/convert.h> @@ -415,10 +416,10 @@ ExportHandler::export_cd_marker_file (ExportTimespanPtr timespan, ExportFormatSp } catch (std::exception& e) { error << string_compose (_("an error occured while writing a TOC/CUE file: %1"), e.what()) << endmsg; - ::unlink (filepath.c_str()); + ::g_unlink (filepath.c_str()); } catch (Glib::Exception& e) { error << string_compose (_("an error occured while writing a TOC/CUE file: %1"), e.what()) << endmsg; - ::unlink (filepath.c_str()); + ::g_unlink (filepath.c_str()); } } diff --git a/libs/ardour/export_profile_manager.cc b/libs/ardour/export_profile_manager.cc index 42e494c0cb..7ff4282c74 100644 --- a/libs/ardour/export_profile_manager.cc +++ b/libs/ardour/export_profile_manager.cc @@ -685,7 +685,7 @@ ExportProfileManager::FormatStatePtr ExportProfileManager::deserialize_format (XMLNode & root) { XMLProperty * prop; - UUID id; + PBD::UUID id; if ((prop = root.property ("id"))) { id = prop->value(); diff --git a/libs/ardour/file_source.cc b/libs/ardour/file_source.cc index 0921498186..e06b3d624e 100644 --- a/libs/ardour/file_source.cc +++ b/libs/ardour/file_source.cc @@ -51,7 +51,7 @@ using namespace ARDOUR; using namespace PBD; using namespace Glib; -PBD::Signal3<int,std::string,std::string,std::vector<std::string> > FileSource::AmbiguousFileName; +PBD::Signal2<int,std::string,std::vector<std::string> > FileSource::AmbiguousFileName; FileSource::FileSource (Session& session, DataType type, const string& path, const string& origin, Source::Flag flag) : Source(session, type, path, flag) @@ -240,19 +240,15 @@ FileSource::find (Session& s, DataType type, const string& path, bool must_exist isnew = false; if (!Glib::path_is_absolute (path)) { - vector<string> dirs; vector<string> hits; string fullpath; + std::vector<std::string> dirs = s.source_search_path (type); - string search_path = s.source_search_path (type); - - if (search_path.length() == 0) { + if (dirs.size() == 0) { error << _("FileSource: search path not set") << endmsg; goto out; } - split (search_path, dirs, ':'); - hits.clear (); for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) { @@ -296,7 +292,7 @@ FileSource::find (Session& s, DataType type, const string& path, bool must_exist /* more than one match: ask the user */ - int which = FileSource::AmbiguousFileName (path, search_path, de_duped_hits).get_value_or (-1); + int which = FileSource::AmbiguousFileName (path, de_duped_hits).get_value_or (-1); if (which < 0) { goto out; @@ -310,8 +306,7 @@ FileSource::find (Session& s, DataType type, const string& path, bool must_exist if (must_exist) { error << string_compose( - _("Filesource: cannot find required file (%1): while searching %2"), - path, search_path) << endmsg; + _("Filesource: cannot find required file (%1)"), path) << endmsg; goto out; } else { isnew = true; @@ -357,8 +352,6 @@ bool FileSource::find_2X (Session& s, DataType type, const string& path, bool must_exist, bool& isnew, uint16_t& chan, string& found_path) { - string search_path = s.source_search_path (type); - string pathstr = path; string::size_type pos; bool ret = false; @@ -369,18 +362,17 @@ FileSource::find_2X (Session& s, DataType type, const string& path, bool must_ex /* non-absolute pathname: find pathstr in search path */ - vector<string> dirs; + vector<string> dirs = s.source_search_path (type); + int cnt; string fullpath; string keeppath; - if (search_path.length() == 0) { + if (dirs.size() == 0) { error << _("FileSource: search path not set") << endmsg; goto out; } - split (search_path, dirs, ':'); - cnt = 0; for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) { @@ -437,16 +429,15 @@ FileSource::find_2X (Session& s, DataType type, const string& path, bool must_ex if (cnt > 1) { error << string_compose ( - _("FileSource: \"%1\" is ambigous when searching %2\n\t"), - pathstr, search_path) << endmsg; + _("FileSource: \"%1\" is ambigous when searching\n\t"), pathstr) << endmsg; goto out; } else if (cnt == 0) { if (must_exist) { error << string_compose( - _("Filesource: cannot find required file (%1): while searching %2"), - pathstr, search_path) << endmsg; + _("Filesource: cannot find required file (%1): while searching") + , pathstr) << endmsg; goto out; } else { isnew = true; @@ -496,13 +487,14 @@ FileSource::find_2X (Session& s, DataType type, const string& path, bool must_ex goto out; } +#ifndef PLATFORM_WINDOWS if (errno != ENOENT) { error << string_compose( _("Filesource: cannot check for existing file (%1): %2"), path, strerror (errno)) << endmsg; goto out; } - +#endif /* a new file */ isnew = true; ret = true; diff --git a/libs/ardour/filesystem_paths.cc b/libs/ardour/filesystem_paths.cc index 73bfaff137..54f7508b65 100644 --- a/libs/ardour/filesystem_paths.cc +++ b/libs/ardour/filesystem_paths.cc @@ -86,49 +86,71 @@ user_config_directory () std::string ardour_dll_directory () { +#ifdef PLATFORM_WINDOWS + std::string dll_dir_path(g_win32_get_package_installation_directory_of_module(NULL)); + dll_dir_path = Glib::build_filename (dll_dir_path, "lib"); + return Glib::build_filename (dll_dir_path, "ardour3"); +#else std::string s = Glib::getenv("ARDOUR_DLL_PATH"); if (s.empty()) { std::cerr << _("ARDOUR_DLL_PATH not set in environment - exiting\n"); ::exit (1); } return s; +#endif +} + +#ifdef PLATFORM_WINDOWS +Searchpath +windows_search_path () +{ + std::string dll_dir_path(g_win32_get_package_installation_directory_of_module(NULL)); + dll_dir_path = Glib::build_filename (dll_dir_path, "share"); + return Glib::build_filename (dll_dir_path, "ardour3"); } +#endif -SearchPath +Searchpath ardour_config_search_path () { - static SearchPath search_path; + static Searchpath search_path; if (search_path.empty()) { search_path += user_config_directory(); - +#ifdef PLATFORM_WINDOWS + search_path += windows_search_path (); +#else std::string s = Glib::getenv("ARDOUR_CONFIG_PATH"); if (s.empty()) { std::cerr << _("ARDOUR_CONFIG_PATH not set in environment - exiting\n"); ::exit (1); } - search_path += SearchPath (s); + search_path += Searchpath (s); +#endif } return search_path; } -SearchPath +Searchpath ardour_data_search_path () { - static SearchPath search_path; + static Searchpath search_path; if (search_path.empty()) { search_path += user_config_directory(); - +#ifdef PLATFORM_WINDOWS + search_path += windows_search_path (); +#else std::string s = Glib::getenv("ARDOUR_DATA_PATH"); if (s.empty()) { std::cerr << _("ARDOUR_DATA_PATH not set in environment - exiting\n"); ::exit (1); } - search_path += SearchPath (s); + search_path += Searchpath (s); +#endif } return search_path; diff --git a/libs/ardour/find_session.cc b/libs/ardour/find_session.cc index f0a034d8d4..afcbe7393b 100644 --- a/libs/ardour/find_session.cc +++ b/libs/ardour/find_session.cc @@ -27,6 +27,7 @@ #include <glibmm/miscutils.h> #include "pbd/compose.h" +#include "pbd/pathexpand.h" #include "pbd/error.h" #include "ardour/filename_extensions.h" @@ -43,16 +44,10 @@ int find_session (string str, string& path, string& snapshot, bool& isnew) { struct stat statbuf; - char buf[PATH_MAX+1]; isnew = false; - if (!realpath (str.c_str(), buf) && (errno != ENOENT && errno != ENOTDIR)) { - error << string_compose (_("Could not resolve path: %1 (%2)"), buf, strerror(errno)) << endmsg; - return -1; - } - - str = buf; + str = canonical_path (str); /* check to see if it exists, and what it is */ diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 986d320aef..1406bbd43a 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -20,12 +20,18 @@ #include "libardour-config.h" #endif +#ifdef interface +#undef interface +#endif + #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain #include <cstdlib> #include <sys/stat.h> #include <sys/types.h> #include <sys/time.h> +#ifndef PLATFORM_WINDOWS #include <sys/resource.h> +#endif #include <unistd.h> #include <fcntl.h> #include <errno.h> @@ -42,7 +48,7 @@ #include "ardour/audio_unit.h" #endif -#ifdef __SSE__ +#if defined(__SSE__) || defined(USE_XMMINTRIN) #include <xmmintrin.h> #endif @@ -53,7 +59,9 @@ #include <glibmm/fileutils.h> #include <glibmm/miscutils.h> +#ifdef HAVE_LRDF #include <lrdf.h> +#endif #include "pbd/cpus.h" #include "pbd/error.h" @@ -194,6 +202,7 @@ setup_hardware_optimization (bool try_optimization) static void lotsa_files_please () { +#ifndef PLATFORM_WINDOWS struct rlimit rl; if (getrlimit (RLIMIT_NOFILE, &rl) == 0) { @@ -214,6 +223,7 @@ lotsa_files_please () } else { error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg; } +#endif } bool @@ -260,7 +270,9 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir // allow ardour the absolute maximum number of open files lotsa_files_please (); +#ifdef HAVE_LRDF lrdf_init(); +#endif Library = new AudioLibrary; BootMessage (_("Loading configuration")); @@ -357,7 +369,9 @@ int ARDOUR::cleanup () { delete Library; +#ifdef HAVE_LRDF lrdf_cleanup (); +#endif delete &ControlProtocolManager::instance(); #ifdef WINDOWS_VST_SUPPORT fst_exit (); @@ -374,7 +388,7 @@ void ARDOUR::find_bindings_files (map<string,string>& files) { vector<std::string> found; - SearchPath spath = ardour_config_search_path(); + Searchpath spath = ardour_config_search_path(); if (getenv ("ARDOUR_SAE")) { Glib::PatternSpec pattern("*SAE-*.bindings"); diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc index cb0fa1b21a..2425f8b6ef 100644 --- a/libs/ardour/graph.cc +++ b/libs/ardour/graph.cc @@ -22,6 +22,7 @@ #include "pbd/compose.h" #include "pbd/debug_rt_alloc.h" +#include "pbd/pthread_utils.h" #include "ardour/debug.h" #include "ardour/graph.h" @@ -101,7 +102,7 @@ Graph::reset_thread_list () } Glib::Threads::Mutex::Lock lm (_session.engine().process_lock()); - pthread_t a_thread; + jack_native_thread_t a_thread; if (!_thread_list.empty()) { drop_threads (); @@ -146,9 +147,8 @@ Graph::drop_threads () _callback_start_sem.signal (); - for (list<pthread_t>::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) { - void* status; - pthread_join (*i, &status); + for (list<jack_native_thread_t>::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) { + AudioEngine::instance()->stop_process_thread(*i); } _thread_list.clear (); @@ -366,7 +366,7 @@ Graph::run_one() /* update the number of threads that will still be sleeping */ _execution_tokens -= wakeup; - DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 signals %2\n", pthread_self(), wakeup)); + DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 signals %2\n", pthread_name(), wakeup)); for (int i = 0; i < wakeup; i++) { _execution_sem.signal (); @@ -375,12 +375,12 @@ Graph::run_one() while (to_run == 0) { _execution_tokens += 1; pthread_mutex_unlock (&_trigger_mutex); - DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 goes to sleep\n", pthread_self())); + DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 goes to sleep\n", pthread_name())); _execution_sem.wait (); if (_quit_threads) { return true; } - DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 is awake\n", pthread_self())); + DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 is awake\n", pthread_name())); pthread_mutex_lock (&_trigger_mutex); if (_trigger_queue.size()) { to_run = _trigger_queue.back(); @@ -392,7 +392,7 @@ Graph::run_one() to_run->process(); to_run->finish (_current_chain); - DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 has finished run_one()\n", pthread_self())); + DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 has finished run_one()\n", pthread_name())); return false; } @@ -560,7 +560,7 @@ Graph::process_one_route (Route* route) assert (route); - DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 runs route %2\n", pthread_self(), route->name())); + DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 runs route %2\n", pthread_name(), route->name())); if (_process_silent) { retval = route->silent_roll (_process_nframes, _process_start_frame, _process_end_frame, need_butler); @@ -584,10 +584,12 @@ Graph::process_one_route (Route* route) bool Graph::in_process_thread () const { +#ifndef COMPILER_MINGW for (list<pthread_t>::const_iterator i = _thread_list.begin (); i != _thread_list.end(); ++i) { - if (*i == pthread_self()) { + if (pthread_equal(*i, pthread_self())) { return true; } } +#endif return false; } diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 047b46f553..b66f354224 100644 --- a/libs/ardour/import.cc +++ b/libs/ardour/import.cc @@ -34,6 +34,7 @@ #include <sndfile.h> #include <samplerate.h> +#include <glib/gstdio.h> #include <glibmm.h> #include <boost/scoped_array.hpp> @@ -117,7 +118,7 @@ open_importable_source (const string& path, framecnt_t samplerate, ARDOUR::SrcQu } static std::string -get_non_existent_filename (HeaderFormat hf, DataType type, const bool allow_replacing, const std::string& destdir, const std::string& basename, uint channel, uint channels) +get_non_existent_filename (HeaderFormat hf, DataType type, const bool allow_replacing, const std::string& destdir, const std::string& basename, uint32_t channel, uint32_t channels) { char buf[PATH_MAX+1]; bool goodfile = false; @@ -172,14 +173,14 @@ get_non_existent_filename (HeaderFormat hf, DataType type, const bool allow_repl } static vector<string> -get_paths_for_new_sources (HeaderFormat hf, const bool allow_replacing, const string& import_file_path, const string& session_dir, uint channels) +get_paths_for_new_sources (HeaderFormat hf, const bool allow_replacing, const string& import_file_path, const string& session_dir, uint32_t channels) { vector<string> new_paths; const string basename = basename_nosuffix (import_file_path); SessionDirectory sdir(session_dir); - for (uint n = 0; n < channels; ++n) { + for (uint32_t n = 0; n < channels; ++n) { const DataType type = SMFSource::safe_midi_file_extension (import_file_path) ? DataType::MIDI : DataType::AUDIO; @@ -196,7 +197,7 @@ get_paths_for_new_sources (HeaderFormat hf, const bool allow_replacing, const st static bool map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/, - uint /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session) + uint32_t /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session) { for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i) @@ -215,7 +216,7 @@ map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/, static bool create_mono_sources_for_writing (const vector<string>& new_paths, - Session& sess, uint samplerate, + Session& sess, uint32_t samplerate, vector<boost::shared_ptr<Source> >& newfiles, framepos_t timeline_position) { @@ -253,10 +254,10 @@ create_mono_sources_for_writing (const vector<string>& new_paths, static string compose_status_message (const string& path, - uint file_samplerate, - uint session_samplerate, - uint /* current_file */, - uint /* total_files */) + uint32_t file_samplerate, + uint32_t session_samplerate, + uint32_t /* current_file */, + uint32_t /* total_files */) { if (file_samplerate != session_samplerate) { return string_compose (_("Resampling %1 from %2kHz to %3kHz"), @@ -274,12 +275,12 @@ write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status, { const framecnt_t nframes = ResampledImportableSource::blocksize; boost::shared_ptr<AudioFileSource> afs; - uint channels = source->channels(); + uint32_t channels = source->channels(); boost::scoped_array<float> data(new float[nframes * channels]); vector<boost::shared_array<Sample> > channel_data; - for (uint n = 0; n < channels; ++n) { + for (uint32_t n = 0; n < channels; ++n) { channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes])); } @@ -300,7 +301,7 @@ write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status, */ float peak = 0; - uint read_count = 0; + uint32_t read_count = 0; while (!status.cancel) { framecnt_t const nread = source->read (data.get(), nframes); @@ -324,15 +325,23 @@ write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status, progress_base = 0.5; } - uint read_count = 0; + uint32_t read_count = 0; while (!status.cancel) { framecnt_t nread, nfread; - uint x; - uint chn; + uint32_t x; + uint32_t chn; if ((nread = source->read (data.get(), nframes)) == 0) { +#ifdef PLATFORM_WINDOWS + /* Flush the data once we've finished importing the file. Windows can */ + /* cache the data for very long periods of time (perhaps not writing */ + /* it to disk until Ardour closes). So let's force it to flush now. */ + for (chn = 0; chn < channels; ++chn) + if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) + afs->flush (); +#endif break; } @@ -464,7 +473,7 @@ remove_file_source (boost::shared_ptr<Source> source) boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (source); if (fs) { - ::unlink (fs->path().c_str()); + ::g_unlink (fs->path().c_str()); } } @@ -479,7 +488,7 @@ Session::import_files (ImportStatus& status) Sources all_new_sources; boost::shared_ptr<AudioFileSource> afs; boost::shared_ptr<SMFSource> smfs; - uint channels = 0; + uint32_t channels = 0; status.sources.clear (); diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 21fdca6e96..a9d37d4315 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -19,6 +19,7 @@ #include <fstream> #include <algorithm> #include <cmath> +#include <vector> #include <unistd.h> #include <locale.h> @@ -395,7 +396,9 @@ IO::disconnect (void* src) int IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed) { +#ifndef PLATFORM_WINDOWS assert (!AudioEngine::instance()->process_lock().trylock()); +#endif boost::shared_ptr<Port> port; @@ -466,7 +469,9 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed) int IO::ensure_ports (ChanCount count, bool clear, void* src) { +#ifndef PLATFORM_WINDOWS assert (!AudioEngine::instance()->process_lock().trylock()); +#endif bool changed = false; @@ -501,7 +506,9 @@ IO::ensure_ports (ChanCount count, bool clear, void* src) int IO::ensure_io (ChanCount count, bool clear, void* src) { +#ifndef PLATFORM_WINDOWS assert (!AudioEngine::instance()->process_lock().trylock()); +#endif return ensure_ports (count, clear, src); } @@ -1373,20 +1380,20 @@ IO::build_legal_port_name (DataType type) limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5); - char buf1[name_size+1]; - char buf2[name_size+1]; + std::vector<char> buf1(name_size+1); + std::vector<char> buf2(name_size+1); /* colons are illegal in port names, so fix that */ string nom = _name.val(); replace_all (nom, ":", ";"); - snprintf (buf1, name_size+1, ("%.*s/%s"), limit, nom.c_str(), suffix.c_str()); + snprintf (&buf1[0], name_size+1, ("%.*s/%s"), limit, nom.c_str(), suffix.c_str()); - int port_number = find_port_hole (buf1); - snprintf (buf2, name_size+1, "%s %d", buf1, port_number); + int port_number = find_port_hole (&buf1[0]); + snprintf (&buf2[0], name_size+1, "%s %d", &buf1[0], port_number); - return string (buf2); + return string (&buf2[0]); } int32_t @@ -1404,13 +1411,13 @@ IO::find_port_hole (const char* base) */ for (n = 1; n < 9999; ++n) { - char buf[jack_port_name_size()]; + std::vector<char> buf(jack_port_name_size()); PortSet::iterator i = _ports.begin(); - snprintf (buf, jack_port_name_size(), _("%s %u"), base, n); + snprintf (&buf[0], jack_port_name_size(), _("%s %u"), base, n); for ( ; i != _ports.end(); ++i) { - if (i->name() == buf) { + if (string(i->name()) == string(&buf[0])) { break; } } diff --git a/libs/ardour/jack_utils.cc b/libs/ardour/jack_utils.cc new file mode 100644 index 0000000000..64e58bf608 --- /dev/null +++ b/libs/ardour/jack_utils.cc @@ -0,0 +1,914 @@ +/* + Copyright (C) 2010 Paul Davis + Copyright (C) 2011 Tim Mayberry + + 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. + +*/ + +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + +#ifdef HAVE_ALSA +#include <alsa/asoundlib.h> +#endif + +#ifdef __APPLE__ +#include <CoreAudio/CoreAudio.h> +#include <CoreFoundation/CFString.h> +#include <sys/param.h> +#include <mach-o/dyld.h> +#endif + +#ifdef HAVE_PORTAUDIO +#include <portaudio.h> +#endif + +#include <jack/jack.h> + +#include <fstream> + +#include <boost/scoped_ptr.hpp> + +#include <glibmm/miscutils.h> + +#include "pbd/epa.h" +#include "pbd/error.h" +#include "pbd/convert.h" +#include "pbd/file_utils.h" +#include "pbd/search_path.h" + +#include "ardour/jack_utils.h" + +#ifdef __APPLE +#include <CFBundle.h> +#endif + +#include "i18n.h" + +using namespace std; +using namespace PBD; + +namespace ARDOUR { + // The pretty driver names + const char * const portaudio_driver_name = X_("Portaudio"); + const char * const coreaudio_driver_name = X_("CoreAudio"); + const char * const alsa_driver_name = X_("ALSA"); + const char * const oss_driver_name = X_("OSS"); + const char * const freebob_driver_name = X_("FreeBoB"); + const char * const ffado_driver_name = X_("FFADO"); + const char * const netjack_driver_name = X_("NetJACK"); + const char * const dummy_driver_name = X_("Dummy"); +} + +namespace { + + // The real driver names + const char * const portaudio_driver_command_line_name = X_("portaudio"); + const char * const coreaudio_driver_command_line_name = X_("coreaudio"); + const char * const alsa_driver_command_line_name = X_("alsa"); + const char * const oss_driver_command_line_name = X_("oss"); + const char * const freebob_driver_command_line_name = X_("freebob"); + const char * const ffado_driver_command_line_name = X_("firewire"); + const char * const netjack_driver_command_line_name = X_("netjack"); + const char * const dummy_driver_command_line_name = X_("dummy"); + + // should we provide more "pretty" names like above? + const char * const alsaseq_midi_driver_name = X_("seq"); + const char * const alsaraw_midi_driver_name = X_("raw"); + const char * const winmme_midi_driver_name = X_("winmme"); + const char * const coremidi_midi_driver_name = X_("coremidi"); + + // this should probably be translated + const char * const default_device_name = X_("Default"); +} + +std::string +get_none_string () +{ + return _("None"); +} + +void +ARDOUR::get_jack_audio_driver_names (vector<string>& audio_driver_names) +{ +#ifdef PLATFORM_WINDOWS + audio_driver_names.push_back (portaudio_driver_name); +#elif __APPLE__ + audio_driver_names.push_back (coreaudio_driver_name); +#else +#ifdef HAVE_ALSA + audio_driver_names.push_back (alsa_driver_name); +#endif + audio_driver_names.push_back (oss_driver_name); + audio_driver_names.push_back (freebob_driver_name); + audio_driver_names.push_back (ffado_driver_name); +#endif + audio_driver_names.push_back (netjack_driver_name); + audio_driver_names.push_back (dummy_driver_name); +} + +void +ARDOUR::get_jack_default_audio_driver_name (string& audio_driver_name) +{ + vector<string> drivers; + get_jack_audio_driver_names (drivers); + audio_driver_name = drivers.front (); +} + +void +ARDOUR::get_jack_midi_system_names (const string& driver, vector<string>& midi_system_names) +{ + midi_system_names.push_back (get_none_string ()); +#ifdef PLATFORM_WINDOWS + midi_system_names.push_back (winmme_midi_driver_name); +#elif __APPLE__ + midi_system_names.push_back (coremidi_midi_driver_name); +#else +#ifdef HAVE_ALSA + if (driver == alsa_driver_name) { + midi_system_names.push_back (alsaseq_midi_driver_name); + midi_system_names.push_back (alsaraw_midi_driver_name); + } +#endif +#endif +} + +void +ARDOUR::get_jack_default_midi_system_name (const string& driver, string& midi_system_name) +{ + vector<string> drivers; + get_jack_midi_system_names (driver, drivers); + midi_system_name = drivers.front (); +} + +void +ARDOUR::get_jack_sample_rate_strings (vector<string>& samplerates) +{ + // do these really need to be translated? + samplerates.push_back (_("8000Hz")); + samplerates.push_back (_("22050Hz")); + samplerates.push_back (_("44100Hz")); + samplerates.push_back (_("48000Hz")); + samplerates.push_back (_("88200Hz")); + samplerates.push_back (_("96000Hz")); + samplerates.push_back (_("192000Hz")); +} + +string +ARDOUR::get_jack_default_sample_rate () +{ + return _("48000Hz"); +} + +void +ARDOUR::get_jack_period_size_strings (std::vector<std::string>& period_sizes) +{ + period_sizes.push_back ("32"); + period_sizes.push_back ("64"); + period_sizes.push_back ("128"); + period_sizes.push_back ("256"); + period_sizes.push_back ("512"); + period_sizes.push_back ("1024"); + period_sizes.push_back ("2048"); + period_sizes.push_back ("4096"); + period_sizes.push_back ("8192"); +} + +string +ARDOUR::get_jack_default_period_size () +{ + return "1024"; +} + +void +ARDOUR::get_jack_dither_mode_strings (const string& driver, vector<string>& dither_modes) +{ + dither_modes.push_back (get_none_string ()); + + if (driver == alsa_driver_name ) { + dither_modes.push_back (_("Triangular")); + dither_modes.push_back (_("Rectangular")); + dither_modes.push_back (_("Shaped")); + } +} + +string +ARDOUR::get_jack_default_dither_mode (const string& /*driver*/) +{ + return get_none_string (); +} + +string +ARDOUR::get_jack_latency_string (string samplerate, float periods, string period_size) +{ + uint32_t rate = atoi (samplerate); + float psize = atof (period_size); + + char buf[32]; + snprintf (buf, sizeof(buf), "%.1fmsec", (periods * psize) / (rate/1000.0)); + + return buf; +} + +bool +get_jack_command_line_audio_driver_name (const string& driver_name, string& command_line_name) +{ + using namespace ARDOUR; + if (driver_name == portaudio_driver_name) { + command_line_name = portaudio_driver_command_line_name; + return true; + } else if (driver_name == coreaudio_driver_name) { + command_line_name = coreaudio_driver_command_line_name; + return true; + } else if (driver_name == alsa_driver_name) { + command_line_name = alsa_driver_command_line_name; + return true; + } else if (driver_name == oss_driver_name) { + command_line_name = oss_driver_command_line_name; + return true; + } else if (driver_name == freebob_driver_name) { + command_line_name = freebob_driver_command_line_name; + return true; + } else if (driver_name == ffado_driver_name) { + command_line_name = ffado_driver_command_line_name; + return true; + } else if (driver_name == netjack_driver_name) { + command_line_name = netjack_driver_command_line_name; + return true; + } else if (driver_name == dummy_driver_name) { + command_line_name = dummy_driver_command_line_name; + return true; + } + return false; +} + +bool +get_jack_command_line_audio_device_name (const string& driver_name, + const string& device_name, string& command_line_device_name) +{ + using namespace ARDOUR; + device_map_t devices; + + get_jack_device_names_for_audio_driver (driver_name, devices); + + for (device_map_t::const_iterator i = devices.begin (); i != devices.end(); ++i) { + if (i->first == device_name) { + command_line_device_name = i->second; + return true; + } + } + return false; +} + +bool +get_jack_command_line_dither_mode (const string& dither_mode, string& command_line_dither_mode) +{ + using namespace ARDOUR; + + if (dither_mode == _("Triangular")) { + command_line_dither_mode = "triangular"; + return true; + } else if (dither_mode == _("Rectangular")) { + command_line_dither_mode = "rectangular"; + return true; + } else if (dither_mode == _("Shaped")) { + command_line_dither_mode = "shaped"; + return true; + } + + return false; +} + +bool +ARDOUR::jack_server_running () +{ + EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa (); + boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa; + + /* revert all environment settings back to whatever they were when ardour started + */ + + if (global_epa) { + current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */ + global_epa->restore (); + } + + jack_status_t status; + jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status); + + if (status == 0) { + jack_client_close (c); + return true; + } + return false; + +} + +void +ARDOUR::get_jack_alsa_device_names (device_map_t& devices) +{ +#ifdef HAVE_ALSA + snd_ctl_t *handle; + snd_ctl_card_info_t *info; + snd_pcm_info_t *pcminfo; + snd_ctl_card_info_alloca(&info); + snd_pcm_info_alloca(&pcminfo); + string devname; + int cardnum = -1; + int device = -1; + + while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) { + + devname = "hw:"; + devname += PBD::to_string (cardnum, std::dec); + + if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) { + + while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) { + + snd_pcm_info_set_device (pcminfo, device); + snd_pcm_info_set_subdevice (pcminfo, 0); + snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK); + + if (snd_ctl_pcm_info (handle, pcminfo) >= 0) { + devname += ','; + devname += PBD::to_string (device, std::dec); + devices.insert (std::make_pair (snd_pcm_info_get_name (pcminfo), devname)); + } + } + + snd_ctl_close(handle); + } + } +#else + (void) devices; +#endif +} + +#ifdef __APPLE__ +static OSStatus +getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize) +{ + UInt32 size = sizeof(CFStringRef); + CFStringRef UI; + OSStatus res = AudioDeviceGetProperty(id, 0, false, + kAudioDevicePropertyDeviceUID, &size, &UI); + if (res == noErr) + CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding()); + CFRelease(UI); + return res; +} +#endif + +void +ARDOUR::get_jack_coreaudio_device_names (device_map_t& devices) +{ +#ifdef __APPLE__ + // Find out how many Core Audio devices are there, if any... + // (code snippet gently "borrowed" from St?hane Letz jackdmp;) + OSStatus err; + Boolean isWritable; + UInt32 outSize = sizeof(isWritable); + + err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, + &outSize, &isWritable); + if (err == noErr) { + // Calculate the number of device available... + int numCoreDevices = outSize / sizeof(AudioDeviceID); + // Make space for the devices we are about to get... + AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices]; + err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, + &outSize, (void *) coreDeviceIDs); + if (err == noErr) { + // Look for the CoreAudio device name... + char coreDeviceName[256]; + UInt32 nameSize; + + for (int i = 0; i < numCoreDevices; i++) { + + nameSize = sizeof (coreDeviceName); + + /* enforce duplex devices only */ + + err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], + 0, true, kAudioDevicePropertyStreams, + &outSize, &isWritable); + + if (err != noErr || outSize == 0) { + continue; + } + + err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], + 0, false, kAudioDevicePropertyStreams, + &outSize, &isWritable); + + if (err != noErr || outSize == 0) { + continue; + } + + err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], + 0, true, kAudioDevicePropertyDeviceName, + &outSize, &isWritable); + if (err == noErr) { + err = AudioDeviceGetProperty(coreDeviceIDs[i], + 0, true, kAudioDevicePropertyDeviceName, + &nameSize, (void *) coreDeviceName); + if (err == noErr) { + char drivername[128]; + + // this returns the unique id for the device + // that must be used on the commandline for jack + + if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) { + devices.insert (make_pair (coreDeviceName, drivername)); + } + } + } + } + } + delete [] coreDeviceIDs; + } +#else + (void) devices; +#endif +} + +void +ARDOUR::get_jack_portaudio_device_names (device_map_t& devices) +{ +#ifdef HAVE_PORTAUDIO + if (Pa_Initialize() != paNoError) { + return; + } + + for (PaDeviceIndex i = 0; i < Pa_GetDeviceCount (); ++i) { + string api_name; + string readable_name; + string jack_device_name; + const PaDeviceInfo* device_info = Pa_GetDeviceInfo(i); + + if (device_info != NULL) { // it should never be ? + api_name = Pa_GetHostApiInfo (device_info->hostApi)->name; + readable_name = api_name + " " + device_info->name; + jack_device_name = api_name + "::" + device_info->name; + devices.insert (make_pair (readable_name, jack_device_name)); + } + } + Pa_Terminate(); +#else + (void) devices; +#endif +} + +void +ARDOUR::get_jack_oss_device_names (device_map_t& devices) +{ + devices.insert (make_pair (default_device_name, default_device_name)); +} + +void +ARDOUR::get_jack_freebob_device_names (device_map_t& devices) +{ + devices.insert (make_pair (default_device_name, default_device_name)); +} + +void +ARDOUR::get_jack_ffado_device_names (device_map_t& devices) +{ + devices.insert (make_pair (default_device_name, default_device_name)); +} + +void +ARDOUR::get_jack_netjack_device_names (device_map_t& devices) +{ + devices.insert (make_pair (default_device_name, default_device_name)); +} + +void +ARDOUR::get_jack_dummy_device_names (device_map_t& devices) +{ + devices.insert (make_pair (default_device_name, default_device_name)); +} + +bool +ARDOUR::get_jack_device_names_for_audio_driver (const string& driver_name, device_map_t& devices) +{ + devices.clear(); + + if (driver_name == portaudio_driver_name) { + get_jack_portaudio_device_names (devices); + } else if (driver_name == coreaudio_driver_name) { + get_jack_coreaudio_device_names (devices); + } else if (driver_name == alsa_driver_name) { + get_jack_alsa_device_names (devices); + } else if (driver_name == oss_driver_name) { + get_jack_oss_device_names (devices); + } else if (driver_name == freebob_driver_name) { + get_jack_freebob_device_names (devices); + } else if (driver_name == ffado_driver_name) { + get_jack_ffado_device_names (devices); + } else if (driver_name == netjack_driver_name) { + get_jack_netjack_device_names (devices); + } else if (driver_name == dummy_driver_name) { + get_jack_dummy_device_names (devices); + } + + return !devices.empty(); +} + + +std::vector<std::string> +ARDOUR::get_jack_device_names_for_audio_driver (const string& driver_name) +{ + std::vector<std::string> readable_names; + device_map_t devices; + + get_jack_device_names_for_audio_driver (driver_name, devices); + + for (device_map_t::const_iterator i = devices.begin (); i != devices.end(); ++i) { + readable_names.push_back (i->first); + } + + return readable_names; +} + +bool +ARDOUR::get_jack_audio_driver_supports_two_devices (const string& driver) +{ + return (driver == alsa_driver_name || driver == oss_driver_name); +} + +bool +ARDOUR::get_jack_audio_driver_supports_latency_adjustment (const string& driver) +{ + return (driver == alsa_driver_name || driver == coreaudio_driver_name || + driver == ffado_driver_name || driver == portaudio_driver_name); +} + +bool +ARDOUR::get_jack_audio_driver_supports_setting_period_count (const string& driver) +{ + return !(driver == dummy_driver_name || driver == coreaudio_driver_name || + driver == portaudio_driver_name); +} + +bool +ARDOUR::get_jack_server_application_names (std::vector<std::string>& server_names) +{ +#ifdef PLATFORM_WINDOWS + server_names.push_back ("jackd.exe"); +#else + server_names.push_back ("jackd"); + server_names.push_back ("jackdmp"); +#endif + return !server_names.empty(); +} + +void +ARDOUR::set_path_env_for_jack_autostart (const vector<std::string>& dirs) +{ +#ifdef __APPLE__ + // push it back into the environment so that auto-started JACK can find it. + // XXX why can't we just expect OS X users to have PATH set correctly? we can't ... + setenv ("PATH", Searchpath(dirs).to_string().c_str(), 1); +#else + (void) dirs; +#endif +} + +bool +ARDOUR::get_jack_server_dir_paths (vector<std::string>& server_dir_paths) +{ +#ifdef __APPLE__ + /* this magic lets us finds the path to the OSX bundle, and then + we infer JACK's location from there + */ + + char execpath[MAXPATHLEN+1]; + uint32_t pathsz = sizeof (execpath); + + _NSGetExecutablePath (execpath, &pathsz); + + server_dir_paths.push_back (Glib::path_get_dirname (execpath)); +#endif + + Searchpath sp(string(g_getenv("PATH"))); + +#ifdef PLATFORM_WINDOWS + gchar *install_dir = g_win32_get_package_installation_directory_of_module (NULL); + if (install_dir) { + sp.push_back (install_dir); + g_free (install_dir); + } + // don't try and use a system wide JACK install yet. +#else + if (sp.empty()) { + sp.push_back ("/usr/bin"); + sp.push_back ("/bin"); + sp.push_back ("/usr/local/bin"); + sp.push_back ("/opt/local/bin"); + } +#endif + + std::copy (sp.begin(), sp.end(), std::back_inserter(server_dir_paths)); + + return !server_dir_paths.empty(); +} + +bool +ARDOUR::get_jack_server_paths (const vector<std::string>& server_dir_paths, + const vector<string>& server_names, + vector<std::string>& server_paths) +{ + for (vector<string>::const_iterator i = server_names.begin(); i != server_names.end(); ++i) { + Glib::PatternSpec ps (*i); + find_matching_files_in_directories (server_dir_paths, ps, server_paths); + } + return !server_paths.empty(); +} + +bool +ARDOUR::get_jack_server_paths (vector<std::string>& server_paths) +{ + vector<std::string> server_dirs; + + if (!get_jack_server_dir_paths (server_dirs)) { + return false; + } + + vector<string> server_names; + + if (!get_jack_server_application_names (server_names)) { + return false; + } + + if (!get_jack_server_paths (server_dirs, server_names, server_paths)) { + return false; + } + + return !server_paths.empty(); +} + +bool +ARDOUR::get_jack_default_server_path (std::string& server_path) +{ + vector<std::string> server_paths; + + if (!get_jack_server_paths (server_paths)) { + return false; + } + + server_path = server_paths.front (); + return true; +} + +string +quote_string (const string& str) +{ + return "\"" + str + "\""; +} + +ARDOUR::JackCommandLineOptions::JackCommandLineOptions () + : server_path () + , timeout(0) + , no_mlock(false) + , ports_max(128) + , realtime(true) + , priority(0) + , unlock_gui_libs(false) + , verbose(false) + , temporary(true) + , driver() + , input_device() + , output_device() + , num_periods(2) + , period_size(1024) + , samplerate(48000) + , input_latency(0) + , output_latency(0) + , hardware_metering(false) + , hardware_monitoring(false) + , dither_mode() + , force16_bit(false) + , soft_mode(false) + , midi_driver() +{ + +} + +bool +ARDOUR::get_jack_command_line_string (const JackCommandLineOptions& options, string& command_line) +{ + vector<string> args; + + args.push_back (options.server_path); + +#ifdef PLATFORM_WINDOWS + // must use sync mode on windows + args.push_back ("-S"); + + // this needs to be added now on windows + if (!options.midi_driver.empty () && options.midi_driver != get_none_string ()) { + args.push_back ("-X"); + args.push_back (options.midi_driver); + } +#endif + + if (options.timeout) { + args.push_back ("-t"); + args.push_back (to_string (options.timeout, std::dec)); + } + + if (options.no_mlock) { + args.push_back ("-m"); + } + + args.push_back ("-p"); + args.push_back (to_string(options.ports_max, std::dec)); + + if (options.realtime) { + args.push_back ("-R"); + if (options.priority != 0) { + args.push_back ("-P"); + args.push_back (to_string(options.priority, std::dec)); + } + } else { + args.push_back ("-r"); + } + + if (options.unlock_gui_libs) { + args.push_back ("-u"); + } + + if (options.verbose) { + args.push_back ("-v"); + } + +#ifndef PLATFORM_WINDOWS + if (options.temporary) { + args.push_back ("-T"); + } +#endif + + string command_line_driver_name; + + if (!get_jack_command_line_audio_driver_name (options.driver, command_line_driver_name)) { + return false; + } + + args.push_back ("-d"); + args.push_back (command_line_driver_name); + + if (options.output_device.empty() && options.input_device.empty()) { + return false; + } + + string command_line_input_device_name; + string command_line_output_device_name; + + if (!get_jack_command_line_audio_device_name (options.driver, + options.input_device, command_line_input_device_name)) + { + return false; + } + + if (!get_jack_command_line_audio_device_name (options.driver, + options.output_device, command_line_output_device_name)) + { + return false; + } + + if (options.input_device.empty()) { + // playback only + if (options.output_device.empty()) { + return false; + } + args.push_back ("-P"); + } else if (options.output_device.empty()) { + // capture only + if (options.input_device.empty()) { + return false; + } + args.push_back ("-C"); + } else if (options.input_device != options.output_device) { + // capture and playback on two devices if supported + if (get_jack_audio_driver_supports_two_devices (options.driver)) { + args.push_back ("-C"); + args.push_back (command_line_input_device_name); + args.push_back ("-P"); + args.push_back (command_line_output_device_name); + } else { + return false; + } + } + + if (get_jack_audio_driver_supports_setting_period_count (options.driver)) { + args.push_back ("-n"); + args.push_back (to_string (options.num_periods, std::dec)); + } + + args.push_back ("-r"); + args.push_back (to_string (options.samplerate, std::dec)); + + args.push_back ("-p"); + args.push_back (to_string (options.period_size, std::dec)); + + if (get_jack_audio_driver_supports_latency_adjustment (options.driver)) { + if (options.input_latency) { + args.push_back ("-I"); + args.push_back (to_string (options.input_latency, std::dec)); + } + if (options.output_latency) { + args.push_back ("-0"); + args.push_back (to_string (options.output_latency, std::dec)); + } + } + + if (options.input_device == options.output_device && options.input_device != default_device_name) { + args.push_back ("-d"); + args.push_back (command_line_input_device_name); + } + + if (options.driver == alsa_driver_name) { + if (options.hardware_metering) { + args.push_back ("-M"); + } + if (options.hardware_monitoring) { + args.push_back ("-H"); + } + + string command_line_dither_mode; + if (get_jack_command_line_dither_mode (options.dither_mode, command_line_dither_mode)) { + args.push_back ("-z"); + args.push_back (command_line_dither_mode); + } + if (options.force16_bit) { + args.push_back ("-S"); + } + if (options.soft_mode) { + args.push_back ("-s"); + } + + if (!options.midi_driver.empty() && options.midi_driver != get_none_string ()) { + args.push_back ("-X"); + args.push_back (options.midi_driver); + } + } + + ostringstream oss; + + for (vector<string>::const_iterator i = args.begin(); i != args.end();) { + oss << *i; + if (++i != args.end()) oss << ' '; + } + + command_line = oss.str(); + return true; +} + +string +ARDOUR::get_jack_server_config_file_name () +{ + return ".jackdrc"; +} + +std::string +ARDOUR::get_jack_server_user_config_dir_path () +{ + return Glib::get_home_dir (); +} + +std::string +ARDOUR::get_jack_server_user_config_file_path () +{ + return Glib::build_filename (get_jack_server_user_config_dir_path (), get_jack_server_config_file_name ()); +} + +bool +ARDOUR::write_jack_config_file (const std::string& config_file_path, const string& command_line) +{ + ofstream jackdrc (config_file_path.c_str()); + + if (!jackdrc) { + error << string_compose (_("cannot open JACK rc file %1 to store parameters"), config_file_path) << endmsg; + return false; + } + + jackdrc << command_line << endl; + jackdrc.close (); + return true; +} diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 5a6e577f2d..78e16f9941 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -17,6 +17,10 @@ */ +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + #include <inttypes.h> #include <vector> @@ -25,11 +29,15 @@ #include <cstdlib> #include <cstdio> // so libraptor doesn't complain #include <cmath> +#ifndef COMPILER_MSVC #include <dirent.h> +#endif #include <sys/stat.h> #include <cerrno> +#ifdef HAVE_LRDF #include <lrdf.h> +#endif #include "pbd/compose.h" #include "pbd/error.h" @@ -52,16 +60,16 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate) +LadspaPlugin::LadspaPlugin (string module_path, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate) : Plugin (e, session) { - init (mod, index, rate); + init (module_path, index, rate); } LadspaPlugin::LadspaPlugin (const LadspaPlugin &other) : Plugin (other) { - init (other._module, other._index, other._sample_rate); + init (other._module_path, other._index, other._sample_rate); for (uint32_t i = 0; i < parameter_count(); ++i) { _control_data[i] = other._shadow_data[i]; @@ -70,25 +78,32 @@ LadspaPlugin::LadspaPlugin (const LadspaPlugin &other) } void -LadspaPlugin::init (void *mod, uint32_t index, framecnt_t rate) +LadspaPlugin::init (string module_path, uint32_t index, framecnt_t rate) { + void* func; LADSPA_Descriptor_Function dfunc; uint32_t i, port_cnt; - const char *errstr; - _module = mod; + _module_path = module_path; + _module = new Glib::Module(_module_path); _control_data = 0; _shadow_data = 0; _latency_control_port = 0; _was_activated = false; - dfunc = (LADSPA_Descriptor_Function) dlsym (_module, "ladspa_descriptor"); + if (!(*_module)) { + error << _("LADSPA: Unable to open module: ") << Glib::Module::get_last_error() << endmsg; + delete _module; + throw failed_constructor(); + } - if ((errstr = dlerror()) != NULL) { + if (!_module->get_symbol("ladspa_descriptor", func)) { error << _("LADSPA: module has no descriptor function.") << endmsg; throw failed_constructor(); } + dfunc = (LADSPA_Descriptor_Function)func; + if ((_descriptor = dfunc (index)) == 0) { error << _("LADSPA: plugin has gone away since discovery!") << endmsg; throw failed_constructor(); @@ -142,9 +157,8 @@ LadspaPlugin::~LadspaPlugin () deactivate (); cleanup (); - /* XXX who should close a plugin? */ - - // dlclose (module); + // glib has internal reference counting on modules so this is ok + delete _module; delete [] _control_data; delete [] _shadow_data; @@ -629,10 +643,11 @@ LadspaPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const boost::shared_ptr<Plugin::ScalePoints> LadspaPlugin::get_scale_points(uint32_t port_index) const { + boost::shared_ptr<Plugin::ScalePoints> ret; +#ifdef HAVE_LRDF const uint32_t id = atol(unique_id().c_str()); lrdf_defaults* points = lrdf_get_scale_values(id, port_index); - boost::shared_ptr<Plugin::ScalePoints> ret; if (!points) { return ret; } @@ -645,6 +660,7 @@ LadspaPlugin::get_scale_points(uint32_t port_index) const } lrdf_free_setting_values(points); +#endif return ret; } @@ -710,17 +726,7 @@ PluginPtr LadspaPluginInfo::load (Session& session) { try { - PluginPtr plugin; - void *module; - - if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { - error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg; - error << dlerror() << endmsg; - return PluginPtr ((Plugin*) 0); - } else { - plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate())); - } - + PluginPtr plugin (new LadspaPlugin (path, session.engine(), session, index, session.frame_rate())); plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this))); return plugin; } @@ -739,6 +745,7 @@ LadspaPluginInfo::LadspaPluginInfo() void LadspaPlugin::find_presets () { +#ifdef HAVE_LRDF uint32_t id; std::string unique (unique_id()); @@ -759,12 +766,14 @@ LadspaPlugin::find_presets () } lrdf_free_uris(set_uris); } +#endif } bool LadspaPlugin::load_preset (PresetRecord r) { +#ifdef HAVE_LRDF lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str()); if (defs) { @@ -777,6 +786,7 @@ LadspaPlugin::load_preset (PresetRecord r) } Plugin::load_preset (r); +#endif return true; } @@ -784,6 +794,7 @@ LadspaPlugin::load_preset (PresetRecord r) static void lrdf_remove_preset (const char* /*source*/, const char *setting_uri) { +#ifdef HAVE_LRDF lrdf_statement p; lrdf_statement *q; lrdf_statement *i; @@ -817,11 +828,13 @@ lrdf_remove_preset (const char* /*source*/, const char *setting_uri) p.predicate = NULL; p.object = NULL; lrdf_remove_matches (&p); +#endif } void LadspaPlugin::do_remove_preset (string name) { +#ifdef HAVE_LRDF string const envvar = preset_envvar (); if (envvar.empty()) { warning << _("Could not locate HOME. Preset not removed.") << endmsg; @@ -837,6 +850,7 @@ LadspaPlugin::do_remove_preset (string name) lrdf_remove_preset (source.c_str(), p->uri.c_str ()); write_preset_file (envvar); +#endif } string @@ -859,6 +873,7 @@ LadspaPlugin::preset_source (string envvar) const bool LadspaPlugin::write_preset_file (string envvar) { +#ifdef HAVE_LRDF string path = string_compose("%1/.ladspa", envvar); if (g_mkdir_with_parents (path.c_str(), 0775)) { warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg; @@ -879,11 +894,15 @@ LadspaPlugin::write_preset_file (string envvar) } return true; +#else + return false; +#endif } string LadspaPlugin::do_save_preset (string name) { +#ifdef HAVE_LRDF /* make a vector of pids that are input parameters */ vector<int> input_parameter_pids; for (uint32_t i = 0; i < parameter_count(); ++i) { @@ -902,8 +921,8 @@ LadspaPlugin::do_save_preset (string name) lrdf_defaults defaults; defaults.count = input_parameter_pids.size (); - lrdf_portvalue portvalues[input_parameter_pids.size()]; - defaults.items = portvalues; + std::vector<lrdf_portvalue> portvalues(input_parameter_pids.size()); + defaults.items = &portvalues[0]; for (vector<int>::size_type i = 0; i < input_parameter_pids.size(); ++i) { portvalues[i].pid = input_parameter_pids[i]; @@ -927,6 +946,9 @@ LadspaPlugin::do_save_preset (string name) } return uri; +#else + return string(); +#endif } LADSPA_PortDescriptor diff --git a/libs/ardour/ladspa_search_path.cc b/libs/ardour/ladspa_search_path.cc new file mode 100644 index 0000000000..49a2645f5d --- /dev/null +++ b/libs/ardour/ladspa_search_path.cc @@ -0,0 +1,61 @@ +/* + Copyright (C) 2011 Tim Mayberry + + 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 <glibmm/miscutils.h> + +#include "pbd/pathexpand.h" + +#include "ardour/ladspa_search_path.h" +#include "ardour/directory_names.h" +#include "ardour/filesystem_paths.h" + +namespace { + const char * const ladspa_env_variable_name = "LADSPA_PATH"; +} // anonymous + +using namespace PBD; + +namespace ARDOUR { + +Searchpath +ladspa_search_path () +{ + Searchpath spath_env (Glib::getenv(ladspa_env_variable_name)); + + Searchpath spath (user_config_directory ()); + + spath += ardour_dll_directory (); + spath.add_subdirectory_to_paths (ladspa_dir_name); + +#ifndef PLATFORM_WINDOWS + spath.push_back ("/usr/local/lib64/ladspa"); + spath.push_back ("/usr/local/lib/ladspa"); + spath.push_back ("/usr/lib64/ladspa"); + spath.push_back ("/usr/lib/ladspa"); +#endif + +#ifdef __APPLE__ + spath.push_back (path_expand ("~/Library/Audio/Plug-Ins/LADSPA")); + spath.push_back ("/Library/Audio/Plug-Ins/LADSPA"); +#endif + + return spath_env + spath; +} + +} // namespace ARDOUR diff --git a/libs/ardour/ltc_slave.cc b/libs/ardour/ltc_slave.cc index 8d08fd6bb5..ac93ccdb40 100644 --- a/libs/ardour/ltc_slave.cc +++ b/libs/ardour/ltc_slave.cc @@ -19,11 +19,11 @@ */ #include <iostream> #include <errno.h> -#include <poll.h> #include <sys/types.h> #include <unistd.h> #include "pbd/error.h" +#include "pbd/pthread_utils.h" #include "ardour/debug.h" #include "ardour/slave.h" @@ -150,7 +150,7 @@ LTC_Slave::reset() } void -LTC_Slave::parse_ltc(const jack_nframes_t nframes, const jack_default_audio_sample_t * const in, const framecnt_t posinfo) +LTC_Slave::parse_ltc(const jack_nframes_t nframes, const jack_default_audio_sample_t * const in, const ARDOUR::framecnt_t posinfo) { jack_nframes_t i; unsigned char sound[8192]; @@ -432,7 +432,7 @@ LTC_Slave::speed_and_position (double& speed, framepos_t& pos) frameoffset_t skip = now - (monotonic_cnt + nframes); monotonic_cnt = now; - DEBUG_TRACE (DEBUG::LTC, string_compose ("speed_and_position - TID:%1 | latency: %2 | skip %3\n", ::pthread_self(), ltc_slave_latency.max, skip)); + DEBUG_TRACE (DEBUG::LTC, string_compose ("speed_and_position - TID:%1 | latency: %2 | skip %3\n", pthread_name(), ltc_slave_latency.max, skip)); if (last_timestamp == 0) { engine_dll_initstate = 0; @@ -591,7 +591,7 @@ LTC_Slave::approximate_current_delta() const snprintf(delta, sizeof(delta), _("flywheel")); } else { snprintf(delta, sizeof(delta), "\u0394<span foreground=\"green\" face=\"monospace\" >%s%s%" PRIi64 "</span>sm", - LEADINGZERO(abs(current_delta)), PLUSMINUS(-current_delta), abs(current_delta)); + LEADINGZERO(llabs(current_delta)), PLUSMINUS(-current_delta), llabs(current_delta)); } return std::string(delta); } diff --git a/libs/ardour/lv2_bundled_search_path.cc b/libs/ardour/lv2_bundled_search_path.cc index d8cd1c1075..2454ea2ae1 100644 --- a/libs/ardour/lv2_bundled_search_path.cc +++ b/libs/ardour/lv2_bundled_search_path.cc @@ -29,10 +29,10 @@ using namespace PBD; namespace ARDOUR { -SearchPath +Searchpath lv2_bundled_search_path () { - SearchPath spath( ardour_dll_directory () ); + Searchpath spath( ardour_dll_directory () ); spath.add_subdirectory_to_paths ("LV2"); return spath; diff --git a/libs/ardour/lv2_evbuf.c b/libs/ardour/lv2_evbuf.c index 8942d19a9b..fba7fd521d 100644 --- a/libs/ardour/lv2_evbuf.c +++ b/libs/ardour/lv2_evbuf.c @@ -219,7 +219,7 @@ lv2_evbuf_get(LV2_Evbuf_Iterator iter, *subframes = 0; *type = aev->body.type; *size = aev->body.size; - *data = LV2_ATOM_BODY(&aev->body); + *data = (uint8_t*)LV2_ATOM_BODY(&aev->body); break; } diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index e056b55d9d..30134a5dbb 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -25,6 +25,7 @@ #include <cstdlib> #include <cstring> +#include <glib/gstdio.h> #include <giomm/file.h> #include <glib/gprintf.h> #include <glibmm.h> @@ -1104,7 +1105,7 @@ LV2Plugin::do_remove_preset(string name) name + ".ttl" ) ); - unlink(preset_file.c_str()); + ::g_unlink(preset_file.c_str()); } bool @@ -1132,16 +1133,16 @@ LV2Plugin::write_to(RingBuffer<uint8_t>* dest, uint32_t size, const uint8_t* body) { - const uint32_t buf_size = sizeof(UIMessage) + size; - uint8_t buf[buf_size]; + const uint32_t buf_size = sizeof(UIMessage) + size; + vector<uint8_t> buf(buf_size); - UIMessage* msg = (UIMessage*)buf; + UIMessage* msg = (UIMessage*)&buf[0]; msg->index = index; msg->protocol = protocol; msg->size = size; memcpy(msg + 1, body, size); - return (dest->write(buf, buf_size) == buf_size); + return (dest->write(&buf[0], buf_size) == buf_size); } bool @@ -1212,13 +1213,13 @@ LV2Plugin::emit_to_ui(void* controller, UIMessageSink sink) error << "Error reading from Plugin=>UI RingBuffer" << endmsg; break; } - uint8_t body[msg.size]; - if (_to_ui->read(body, msg.size) != msg.size) { + vector<uint8_t> body(msg.size); + if (_to_ui->read(&body[0], msg.size) != msg.size) { error << "Error reading from Plugin=>UI RingBuffer" << endmsg; break; } - sink(controller, msg.index, msg.size, msg.protocol, body); + sink(controller, msg.index, msg.size, msg.protocol, &body[0]); read_space -= sizeof(msg) + msg.size; } @@ -1693,15 +1694,15 @@ LV2Plugin::connect_and_run(BufferSet& bufs, error << "Error reading from UI=>Plugin RingBuffer" << endmsg; break; } - uint8_t body[msg.size]; - if (_from_ui->read(body, msg.size) != msg.size) { + vector<uint8_t> body(msg.size); + if (_from_ui->read(&body[0], msg.size) != msg.size) { error << "Error reading from UI=>Plugin RingBuffer" << endmsg; break; } if (msg.protocol == urids.atom_eventTransfer) { LV2_Evbuf* buf = _ev_buffers[msg.index]; LV2_Evbuf_Iterator i = lv2_evbuf_end(buf); - const LV2_Atom* const atom = (const LV2_Atom*)body; + const LV2_Atom* const atom = (const LV2_Atom*)&body[0]; if (!lv2_evbuf_write(&i, nframes, 0, atom->type, atom->size, (const uint8_t*)(atom + 1))) { error << "Failed to write data to LV2 event buffer\n"; @@ -2007,7 +2008,7 @@ LV2World::load_bundled_plugins() vector<string *> *plugin_objects = scanner (ARDOUR::lv2_bundled_search_path().to_string(), lv2_filter, 0, true, true); if (plugin_objects) { for ( vector<string *>::iterator x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { -#ifdef WINDOWS +#ifdef PLATFORM_WINDOWS string uri = "file:///" + **x + "/"; #else string uri = "file://" + **x + "/"; diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc index a7857f5859..6c5470bbb9 100644 --- a/libs/ardour/meter.cc +++ b/libs/ardour/meter.cc @@ -18,6 +18,7 @@ #include <algorithm> #include <cmath> +#include <limits> #include "pbd/compose.h" @@ -149,7 +150,7 @@ void PeakMeter::reset_max () { for (size_t i = 0; i < _max_peak_power.size(); ++i) { - _max_peak_power[i] = -INFINITY; + _max_peak_power[i] = -std::numeric_limits<float>::infinity(); _max_peak_signal[i] = 0; } @@ -159,7 +160,7 @@ PeakMeter::reset_max () if (n < n_midi) { _visible_peak_power[n] = 0; } else { - _visible_peak_power[n] = -INFINITY; + _visible_peak_power[n] = -std::numeric_limits<float>::infinity(); } } } @@ -298,7 +299,7 @@ PeakMeter::meter () _peak_signal[n] = 0; /* ... to here */ if (n < n_midi) { - _max_peak_power[n] = -INFINITY; // std::max (new_peak, _max_peak_power[n]); // XXX + _max_peak_power[n] = -std::numeric_limits<float>::infinity(); // std::max (new_peak, _max_peak_power[n]); // XXX _max_peak_signal[n] = 0; if (midi_meter_falloff == 0.0f || new_peak > _visible_peak_power[n]) { ; @@ -332,7 +333,7 @@ PeakMeter::meter () } else { // do falloff new_peak = _visible_peak_power[n] - (audio_meter_falloff); - _visible_peak_power[n] = std::max (new_peak, -INFINITY); + _visible_peak_power[n] = std::max (new_peak, -std::numeric_limits<float>::infinity()); } } } diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc index 6f54d17d02..75f3c13f1c 100644 --- a/libs/ardour/midi_clock_slave.cc +++ b/libs/ardour/midi_clock_slave.cc @@ -20,7 +20,6 @@ #include <cmath> #include <errno.h> -#include <poll.h> #include <sys/types.h> #include <unistd.h> #include "pbd/error.h" @@ -252,7 +251,7 @@ MIDIClock_Slave::stop (Parser& /*parser*/, framepos_t /*timestamp*/) } void -MIDIClock_Slave::position (Parser& /*parser*/, byte* message, size_t size) +MIDIClock_Slave::position (Parser& /*parser*/, MIDI::byte* message, size_t size) { // we are note supposed to get position messages while we are running // so lets be robust and ignore those @@ -261,8 +260,8 @@ MIDIClock_Slave::position (Parser& /*parser*/, byte* message, size_t size) } assert(size == 3); - byte lsb = message[1]; - byte msb = message[2]; + MIDI::byte lsb = message[1]; + MIDI::byte msb = message[2]; assert((lsb <= 0x7f) && (msb <= 0x7f)); uint16_t position_in_sixteenth_notes = (uint16_t(msb) << 7) | uint16_t(lsb); diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 489a84e477..cf143bf595 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -26,11 +26,10 @@ #include <fcntl.h> #include <cstdlib> #include <ctime> -#include <strings.h> // for ffs(3) #include <sys/stat.h> -#include <sys/mman.h> #include "pbd/error.h" +#include "pbd/ffs.h" #include "pbd/basename.h" #include <glibmm/threads.h> #include "pbd/xml++.h" @@ -439,7 +438,7 @@ MidiDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t break; case ForceChannel: if (ev.is_channel_event()) { - ev.set_channel (ffs(mask) - 1); + ev.set_channel (PBD::ffs(mask) - 1); } _capture_buf->write(transport_frame + loop_offset + ev.time(), ev.type(), ev.size(), ev.buffer()); diff --git a/libs/ardour/midi_patch_manager.cc b/libs/ardour/midi_patch_manager.cc index 4bced4e46d..f2d964bb77 100644 --- a/libs/ardour/midi_patch_manager.cc +++ b/libs/ardour/midi_patch_manager.cc @@ -28,6 +28,7 @@ #include "ardour/session.h" #include "ardour/session_directory.h" #include "ardour/midi_patch_manager.h" + #include "ardour/midi_patch_search_path.h" #include "i18n.h" @@ -102,7 +103,7 @@ MidiPatchManager::refresh() _master_devices_by_model.clear(); _all_models.clear(); - SearchPath search_path = midi_patch_search_path (); + Searchpath search_path = midi_patch_search_path (); Glib::PatternSpec pattern (string("*.midnam")); vector<std::string> result; diff --git a/libs/ardour/midi_patch_search_path.cc b/libs/ardour/midi_patch_search_path.cc index ccad1de466..c099c379e9 100644 --- a/libs/ardour/midi_patch_search_path.cc +++ b/libs/ardour/midi_patch_search_path.cc @@ -31,14 +31,14 @@ using namespace PBD; namespace ARDOUR { -SearchPath +Searchpath midi_patch_search_path () { - SearchPath spath (ardour_data_search_path()); + Searchpath spath (ardour_data_search_path()); spath.add_subdirectory_to_paths(midi_patch_dir_name); bool midi_patch_path_defined = false; - SearchPath spath_env (Glib::getenv(midi_patch_env_variable_name, midi_patch_path_defined)); + Searchpath spath_env (Glib::getenv(midi_patch_env_variable_name, midi_patch_path_defined)); if (midi_patch_path_defined) { spath += spath_env; diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 124d3f7c9b..1887b74302 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -20,7 +20,6 @@ #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> -#include <poll.h> #include <float.h> #include <cerrno> #include <ctime> diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 7dff7ac639..6a998de90e 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -17,8 +17,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <strings.h> // for ffs(3) - +#include "pbd/ffs.h" #include "pbd/enumwriter.h" #include "pbd/convert.h" #include "evoral/midi_util.h" @@ -321,7 +320,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame if (!lm.locked()) { boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream(); framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes); - if (can_internal_playback_seek(std::llabs(playback_distance))) { + if (can_internal_playback_seek(llabs(playback_distance))) { /* TODO should declick, and/or note-off */ internal_playback_seek(playback_distance); } @@ -513,7 +512,7 @@ MidiTrack::filter_channels (BufferSet& bufs, ChannelMode mode, uint32_t mask) } break; case ForceChannel: - ev.set_channel (ffs (mask) - 1); + ev.set_channel (PBD::ffs (mask) - 1); ++e; break; case AllChannels: @@ -633,9 +632,9 @@ void MidiTrack::MidiControl::set_value(double val) { bool valid = false; - if (std::isinf(val)) { + if (isinf(val)) { cerr << "MIDIControl value is infinity" << endl; - } else if (std::isnan(val)) { + } else if (isnan(val)) { cerr << "MIDIControl value is NaN" << endl; } else if (val < _list->parameter().min()) { cerr << "MIDIControl value is < " << _list->parameter().min() << endl; diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc index 78da32e427..5822cc509e 100644 --- a/libs/ardour/midi_ui.cc +++ b/libs/ardour/midi_ui.cc @@ -104,7 +104,9 @@ MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port) if (ioc & IO_IN) { +#ifndef PLATFORM_WINDOWS CrossThreadChannel::drain (port->selectable()); +#endif DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name())); framepos_t now = _session.engine().frame_time(); diff --git a/libs/ardour/mix.cc b/libs/ardour/mix.cc index 3a873a8e50..220cd0660c 100644 --- a/libs/ardour/mix.cc +++ b/libs/ardour/mix.cc @@ -24,6 +24,8 @@ #include "ardour/runtime_functions.h" #include <stdint.h> +using std::min; +using std::max; using namespace ARDOUR; #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS) @@ -93,22 +95,22 @@ default_compute_peak (const ARDOUR::Sample * buf, pframes_t nsamples, float curr } void -default_find_peaks (const ARDOUR::Sample * buf, pframes_t nframes, float *min, float *max) +default_find_peaks (const ARDOUR::Sample * buf, pframes_t nframes, float *minf, float *maxf) { pframes_t i; float a, b; - a = *max; - b = *min; + a = *maxf; + b = *minf; for (i = 0; i < nframes; i++) { - a = fmax (buf[i], a); - b = fmin (buf[i], b); + a = max (buf[i], a); + b = min (buf[i], b); } - *max = a; - *min = b; + *maxf = a; + *minf = b; } void diff --git a/libs/ardour/msvc/msvc_libardour.cc b/libs/ardour/msvc/msvc_libardour.cc new file mode 100644 index 0000000000..bd186728ea --- /dev/null +++ b/libs/ardour/msvc/msvc_libardour.cc @@ -0,0 +1,276 @@ +/* + Copyright (C) 2009 John Emmas + + 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. + +*/ + +#if (defined(PLATFORM_WINDOWS) && !defined(COMPILER_CYGWIN)) +#include <shlobj.h> +#include <glibmm.h> +#ifdef COMPILER_MSVC +#pragma warning(disable:4996) +#endif +#else +#include <glib.h> +#endif + +#include <string.h> +#include <stdlib.h> +#include <ardour/msvc_libardour.h> + +namespace ARDOUR { + +//*************************************************************** +// +// placeholder_for_non_msvc_specific_function() +// +// Description +// +// Returns: +// +// On Success: +// +// On Failure: +// +/* LIBARDOUR_API char* LIBARDOUR_APICALLTYPE + placeholder_for_non_msvc_specific_function() +{ +char *pRet = buffer; + + return (pRet); +} +*/ + +} // namespace ARDOUR + +#ifdef COMPILER_MSVC + +#include <errno.h> + +namespace ARDOUR { + +//*************************************************************** +// +// symlink() +// +// Emulates POSIX symlink() but creates a Windows shortcut. To +// create a Windows shortcut the supplied shortcut name must end +// in ".lnk" +// Note that you can only create a shortcut in a folder for which +// you have appropriate access rights. Note also that the folder +// must already exist. If it doesn't exist or if you don't have +// sufficient access rights to it, symlink() will generate an +// error (in common with its POSIX counterpart). +// +// Returns: +// +// On Success: Zero +// On Failure: -1 ('errno' will contain the specific error) +// +LIBARDOUR_API int LIBARDOUR_APICALLTYPE +symlink(const char *dest, const char *shortcut, const char *working_directory /*= NULL */) +{ +IShellLinkA *pISL = NULL; +IPersistFile *ppf = NULL; +int ret = (-1); + + if ((NULL == dest) || (NULL == shortcut) || (strlen(shortcut) < 5) || (strlen(dest) == 0)) + _set_errno(EINVAL); + else if ((strlen(shortcut) > _MAX_PATH) || (strlen(dest) > _MAX_PATH)) + _set_errno(ENAMETOOLONG); + else if (Glib::file_test(shortcut, Glib::FILE_TEST_EXISTS)) + _set_errno(EEXIST); + else + { + HRESULT hRet = 0; + + if (SUCCEEDED (hRet = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pISL))) + { + if (SUCCEEDED (pISL->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf))) + { + char sc_path_lower_case[_MAX_PATH]; + WCHAR shortcut_path[_MAX_PATH]; + + // Fail if the path isn't a shortcut + strcpy(sc_path_lower_case, shortcut); + strlwr(sc_path_lower_case); + const char *p = strlen(sc_path_lower_case) + sc_path_lower_case - 4; + + if (0 == strcmp(p, ".lnk")) + { + HRESULT hr; + + // We're apparently been given valid Windows shortcut name + MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, shortcut, -1, shortcut_path, _MAX_PATH); + + // Create the shortcut + if (FAILED (hr = ppf->Load(shortcut_path, STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE))) + hr = ppf->Save(shortcut_path, TRUE); + + if (S_OK == hr) + { + // Set its target path + if (S_OK == pISL->SetPath(dest)) + { + // Set its working directory + if (working_directory) + p = working_directory; + else + p = ""; + + if (S_OK == pISL->SetWorkingDirectory(p)) + { + // Set its 'Show' command + if (S_OK == pISL->SetShowCmd(SW_SHOWNORMAL)) + { + // And finally, set its icon to the same file as the target. + // For the time being, don't fail if the target has no icon. + if (Glib::file_test(dest, Glib::FILE_TEST_IS_DIR)) + pISL->SetIconLocation("%SystemRoot%\\system32\\shell32.dll", 1); + else + pISL->SetIconLocation(dest, 0); + + if (S_OK == ppf->Save(shortcut_path, FALSE)) + { + Sleep(1500); + + ret = 0; + // _set_errno(0); + } + else + _set_errno(EACCES); + } + else + _set_errno(EACCES); + } + else + _set_errno(EACCES); + } + else + _set_errno(EACCES); + } + else + _set_errno(EBADF); + } + else + _set_errno(EACCES); + } + else + _set_errno(EBADF); + } + else + { + if (E_POINTER == hRet) + _set_errno(EINVAL); + else + _set_errno(EIO); + } + } + + return (ret); +} + + +//*************************************************************** +// +// readlink() +// +// Emulates POSIX readlink() but using Windows shortcuts +// Doesn't (currently) resolve shortcuts to shortcuts. This would +// be quite simple to incorporate but we'd need to check for +// recursion (i.e. a shortcut that points to an earlier shortcut +// in the same chain). +// +// Returns: +// +// On Success: Zero +// On Failure: -1 ('errno' will contain the specific error) +// +LIBARDOUR_API int LIBARDOUR_APICALLTYPE +readlink(const char *__restrict shortcut, char *__restrict buf, size_t bufsize) +{ +IShellLinkA *pISL = NULL; +IPersistFile *ppf = NULL; +int ret = (-1); + + if ((NULL == shortcut) || (NULL == buf) || (strlen(shortcut) < 5) || (bufsize == 0)) + _set_errno(EINVAL); + else if ((bufsize > _MAX_PATH) || (strlen(shortcut) > _MAX_PATH)) + _set_errno(ENAMETOOLONG); + else + { + HRESULT hRet = 0; + + if (SUCCEEDED (hRet = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pISL))) + { + if (SUCCEEDED (pISL->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf))) + { + char target_path[_MAX_PATH]; + WCHAR shortcut_path[_MAX_PATH]; + + // Fail if the path isn't a shortcut + strcpy(target_path, shortcut); // Use 'target_path' temporarily + strlwr(target_path); + const char *p = strlen(target_path) + target_path - 4; + + if (0 == strcmp(p, ".lnk")) + { + // We're apparently pointing to a valid Windows shortcut + MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, shortcut, -1, shortcut_path, _MAX_PATH); + + // Load the shortcut into our persistent file + if (SUCCEEDED (ppf->Load(shortcut_path, 0))) + { + // Read the target information from the shortcut object + if (S_OK == (pISL->GetPath (target_path, _MAX_PATH, NULL, SLGP_UNCPRIORITY))) + { + strncpy(buf, target_path, bufsize); + ret = ((ret = strlen(buf)) > bufsize) ? bufsize : ret; + // _set_errno(0); + } + else + _set_errno(EACCES); + } + else + _set_errno(EBADF); + } + else + _set_errno(EINVAL); + } + else + _set_errno(EBADF); + } + else + { + if (E_POINTER == hRet) + _set_errno(EINVAL); + else + _set_errno(EIO); + } + + if (ppf) + ppf->Release(); + + if (pISL) + pISL->Release(); + } + + return (ret); +} + +} // namespace ARDOUR + +#endif // COMPILER_MSVC diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index 8ce0722d8b..c41c6d6c94 100644 --- a/libs/ardour/mtc_slave.cc +++ b/libs/ardour/mtc_slave.cc @@ -19,11 +19,11 @@ */ #include <iostream> #include <errno.h> -#include <poll.h> #include <sys/types.h> #include <unistd.h> #include "pbd/error.h" +#include "pbd/pthread_utils.h" #include "midi++/port.h" #include "ardour/debug.h" @@ -31,6 +31,8 @@ #include "ardour/session.h" #include "ardour/audioengine.h" +#include <glibmm/timer.h> + #include "i18n.h" using namespace std; @@ -233,7 +235,7 @@ MTC_Slave::read_current (SafeTime *st) const do { if (tries == 10) { error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg; - usleep (20); + Glib::usleep (20); tries = 0; } *st = current; @@ -297,7 +299,7 @@ MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, framepos_t now) * when a full TC has been received * OR on locate */ void -MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) +MTC_Slave::update_mtc_time (const MIDI::byte *msg, bool was_full, framepos_t now) { busy_guard1++; @@ -306,7 +308,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) a locate command via MMC. */ - //DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::update_mtc_time - TID:%1\n", ::pthread_self())); + //DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::update_mtc_time - TID:%1\n", pthread_name())); TimecodeFormat tc_format; bool reset_tc = true; @@ -422,7 +424,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now) now, timecode, mtc_frame, was_full, speedup_due_to_tc_mismatch)); if (was_full || outside_window (mtc_frame)) { - DEBUG_TRACE (DEBUG::MTC, string_compose ("update_mtc_time: full TC or outside window. - TID:%1\n", ::pthread_self())); + DEBUG_TRACE (DEBUG::MTC, string_compose ("update_mtc_time: full TC or outside window. - TID:%1\n", pthread_name())); session.request_locate (mtc_frame, false); session.request_transport_speed (0); update_mtc_status (MIDI::MTC_Stopped); @@ -486,7 +488,7 @@ MTC_Slave::update_mtc_status (MIDI::MTC_Status status) /* XXX !!! thread safety ... called from MIDI I/O context * on locate (via ::update_mtc_time()) */ - DEBUG_TRACE (DEBUG::MTC, string_compose("MTC_Slave::update_mtc_status - TID:%1\n", ::pthread_self())); + DEBUG_TRACE (DEBUG::MTC, string_compose("MTC_Slave::update_mtc_status - TID:%1\n", pthread_name())); return; // why was this fn needed anyway ? it just messes up things -> use reset. busy_guard1++; diff --git a/libs/ardour/panner_manager.cc b/libs/ardour/panner_manager.cc index c3601d41de..f757279d29 100644 --- a/libs/ardour/panner_manager.cc +++ b/libs/ardour/panner_manager.cc @@ -28,6 +28,7 @@ #include "ardour/debug.h" #include "ardour/panner_manager.h" + #include "ardour/panner_search_path.h" #include "i18n.h" @@ -66,6 +67,7 @@ PannerManager::discover_panners () Glib::PatternSpec so_extension_pattern("*.so"); Glib::PatternSpec dylib_extension_pattern("*.dylib"); + Glib::PatternSpec dll_extension_pattern("*.dll"); find_matching_files_in_search_path (panner_search_path (), so_extension_pattern, panner_modules); @@ -73,6 +75,9 @@ PannerManager::discover_panners () find_matching_files_in_search_path (panner_search_path (), dylib_extension_pattern, panner_modules); + find_matching_files_in_search_path (panner_search_path (), + dll_extension_pattern, panner_modules); + DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for panners in %1"), panner_search_path().to_string())); for (vector<std::string>::iterator i = panner_modules.begin(); i != panner_modules.end(); ++i) { @@ -106,31 +111,33 @@ PannerManager::panner_discover (string path) PannerInfo* PannerManager::get_descriptor (string path) { - void *module; + Glib::Module* module = new Glib::Module(path); PannerInfo* info = 0; PanPluginDescriptor *descriptor = 0; PanPluginDescriptor* (*dfunc)(void); - const char *errstr; + void* func = 0; - if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { - error << string_compose(_("PannerManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg; + if (!module) { + error << string_compose(_("PannerManager: cannot load module \"%1\" (%2)"), path, + Glib::Module::get_last_error()) << endmsg; + delete module; return 0; } - dfunc = (PanPluginDescriptor* (*)(void)) dlsym (module, "panner_descriptor"); - - if ((errstr = dlerror()) != 0) { + if (!module->get_symbol("panner_descriptor", func)) { error << string_compose(_("PannerManager: module \"%1\" has no descriptor function."), path) << endmsg; - error << errstr << endmsg; - dlclose (module); + error << Glib::Module::get_last_error() << endmsg; + delete module; return 0; } + dfunc = (PanPluginDescriptor* (*)(void))func; descriptor = dfunc(); + if (descriptor) { info = new PannerInfo (*descriptor, module); } else { - dlclose (module); + delete module; } return info; diff --git a/libs/ardour/panner_search_path.cc b/libs/ardour/panner_search_path.cc index 63802ffc4e..100c406edd 100644 --- a/libs/ardour/panner_search_path.cc +++ b/libs/ardour/panner_search_path.cc @@ -31,14 +31,14 @@ using namespace PBD; namespace ARDOUR { -SearchPath +Searchpath panner_search_path () { - SearchPath spath(user_config_directory ()); + Searchpath spath(user_config_directory ()); spath += ardour_dll_directory (); spath.add_subdirectory_to_paths(panner_dir_name); - spath += SearchPath(Glib::getenv(panner_env_variable_name)); + spath += Searchpath(Glib::getenv(panner_env_variable_name)); return spath; } diff --git a/libs/ardour/pcm_utils.cc b/libs/ardour/pcm_utils.cc index de3497d977..ae3bd4a4e0 100644 --- a/libs/ardour/pcm_utils.cc +++ b/libs/ardour/pcm_utils.cc @@ -17,8 +17,10 @@ */ +#ifdef COMPILER_MSVC +#include <ardourext/float_cast.h> +#endif #include "ardour/pcm_utils.h" - #include <cmath> using namespace std; diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index bb79801c9f..47462a3575 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -1997,11 +1997,11 @@ Playlist::find_next_region (framepos_t frame, RegionPoint point, int dir) freeze (); /* add the added regions */ - for (RegionListProperty::ChangeContainer::iterator i = change.added.begin(); i != change.added.end(); ++i) { + for (RegionListProperty::ChangeContainer::const_iterator i = change.added.begin(); i != change.added.end(); ++i) { add_region_internal ((*i), (*i)->position()); } /* remove the removed regions */ - for (RegionListProperty::ChangeContainer::iterator i = change.removed.begin(); i != change.removed.end(); ++i) { + for (RegionListProperty::ChangeContainer::const_iterator i = change.removed.begin(); i != change.removed.end(); ++i) { remove_region (*i); } @@ -2488,7 +2488,7 @@ Playlist::uses_source (boost::shared_ptr<const Source> src) const { RegionReadLock rlock (const_cast<Playlist*> (this)); - for (set<boost::shared_ptr<Region> >::iterator r = all_regions.begin(); r != all_regions.end(); ++r) { + for (set<boost::shared_ptr<Region> >::const_iterator r = all_regions.begin(); r != all_regions.end(); ++r) { if ((*r)->uses_source (src)) { return true; } @@ -2533,7 +2533,7 @@ Playlist::region_by_id (const ID& id) const { /* searches all regions ever added to this playlist */ - for (set<boost::shared_ptr<Region> >::iterator i = all_regions.begin(); i != all_regions.end(); ++i) { + for (set<boost::shared_ptr<Region> >::const_iterator i = all_regions.begin(); i != all_regions.end(); ++i) { if ((*i)->id() == id) { return *i; } diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index 9b2170c349..11d859ed8c 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -27,12 +27,16 @@ #include <cstdlib> #include <cstdio> // so libraptor doesn't complain #include <cmath> +#ifndef COMPILER_MSVC #include <dirent.h> +#endif #include <sys/stat.h> #include <cerrno> #include <utility> +#ifdef HAVE_LRDF #include <lrdf.h> +#endif #include "pbd/compose.h" #include "pbd/error.h" diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 90522a7e06..8d209cc78e 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -25,11 +25,13 @@ #include <sys/types.h> #include <cstdio> -#include <lrdf.h> -#include <dlfcn.h> #include <cstdlib> #include <fstream> +#ifdef HAVE_LRDF +#include <lrdf.h> +#endif + #ifdef WINDOWS_VST_SUPPORT #include "fst.h" #include "pbd/basename.h" @@ -43,9 +45,11 @@ #endif //LXVST_SUPPORT #include <glibmm/miscutils.h> +#include <glibmm/pattern.h> #include "pbd/pathscanner.h" #include "pbd/whitespace.h" +#include "pbd/file_utils.h" #include "ardour/debug.h" #include "ardour/filesystem_paths.h" @@ -55,6 +59,8 @@ #include "ardour/plugin_manager.h" #include "ardour/rc_configuration.h" +#include "ardour/ladspa_search_path.h" + #ifdef LV2_SUPPORT #include "ardour/lv2_plugin.h" #endif @@ -77,6 +83,8 @@ #include "i18n.h" +#include "ardour/debug.h" + using namespace ARDOUR; using namespace PBD; using namespace std; @@ -126,10 +134,6 @@ PluginManager::PluginManager () } #endif /* Native LinuxVST support*/ - if ((s = getenv ("LADSPA_PATH"))) { - ladspa_path = s; - } - if ((s = getenv ("VST_PATH"))) { windows_vst_path = s; } else if ((s = getenv ("VST_PLUGINS"))) { @@ -198,91 +202,38 @@ PluginManager::refresh () void PluginManager::ladspa_refresh () { - if (_ladspa_plugin_info) + if (_ladspa_plugin_info) { _ladspa_plugin_info->clear (); - else + } else { _ladspa_plugin_info = new ARDOUR::PluginInfoList (); - - static const char *standard_paths[] = { - "/usr/local/lib64/ladspa", - "/usr/local/lib/ladspa", - "/usr/lib64/ladspa", - "/usr/lib/ladspa", - "/Library/Audio/Plug-Ins/LADSPA", - "" - }; + } /* allow LADSPA_PATH to augment, not override standard locations */ /* Only add standard locations to ladspa_path if it doesn't * already contain them. Check for trailing G_DIR_SEPARATOR too. */ + + vector<string> ladspa_modules; - int i; - for (i = 0; standard_paths[i][0]; i++) { - size_t found = ladspa_path.find(standard_paths[i]); - if (found != ladspa_path.npos) { - switch (ladspa_path[found + strlen(standard_paths[i])]) { - case ':' : - case '\0': - continue; - case G_DIR_SEPARATOR : - if (ladspa_path[found + strlen(standard_paths[i]) + 1] == ':' || - ladspa_path[found + strlen(standard_paths[i]) + 1] == '\0') { - continue; - } - } - } - if (!ladspa_path.empty()) - ladspa_path += ":"; - - ladspa_path += standard_paths[i]; - - } - - DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_path)); - - ladspa_discover_from_path (ladspa_path); -} - - -int -PluginManager::add_ladspa_directory (string path) -{ - if (ladspa_discover_from_path (path) == 0) { - ladspa_path += ':'; - ladspa_path += path; - return 0; - } - return -1; -} - -static bool ladspa_filter (const string& str, void */*arg*/) -{ - /* Not a dotfile, has a prefix before a period, suffix is "so" */ + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string())); - return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3)); -} - -int -PluginManager::ladspa_discover_from_path (string /*path*/) -{ - PathScanner scanner; - vector<string *> *plugin_objects; - vector<string *>::iterator x; - int ret = 0; + Glib::PatternSpec so_extension_pattern("*.so"); + Glib::PatternSpec dylib_extension_pattern("*.dylib"); + Glib::PatternSpec dll_extension_pattern("*.dll"); - plugin_objects = scanner (ladspa_path, ladspa_filter, 0, false, true); + find_matching_files_in_search_path (ladspa_search_path (), + so_extension_pattern, ladspa_modules); - if (plugin_objects) { - for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { - ladspa_discover (**x); - } + find_matching_files_in_search_path (ladspa_search_path (), + dylib_extension_pattern, ladspa_modules); + + find_matching_files_in_search_path (ladspa_search_path (), + dll_extension_pattern, ladspa_modules); - vector_delete (plugin_objects); + for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) { + ladspa_discover (*i); } - - return ret; } static bool rdf_filter (const string &str, void* /*arg*/) @@ -315,7 +266,7 @@ PluginManager::add_lxvst_presets() void PluginManager::add_presets(string domain) { - +#ifdef HAVE_LRDF PathScanner scanner; vector<string *> *presets; vector<string *>::iterator x; @@ -338,11 +289,13 @@ PluginManager::add_presets(string domain) vector_delete (presets); } +#endif } void PluginManager::add_lrdf_data (const string &path) { +#ifdef HAVE_LRDF PathScanner scanner; vector<string *>* rdf_files; vector<string *>::iterator x; @@ -360,30 +313,36 @@ PluginManager::add_lrdf_data (const string &path) vector_delete (rdf_files); } +#endif } int PluginManager::ladspa_discover (string path) { - void *module; + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path)); + + Glib::Module module(path); const LADSPA_Descriptor *descriptor; LADSPA_Descriptor_Function dfunc; - const char *errstr; + void* func = 0; - if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { - error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg; + if (!module) { + error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"), + path, Glib::Module::get_last_error()) << endmsg; return -1; } - dfunc = (LADSPA_Descriptor_Function) dlsym (module, "ladspa_descriptor"); - if ((errstr = dlerror()) != 0) { + if (!module.get_symbol("ladspa_descriptor", func)) { error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg; - error << errstr << endmsg; - dlclose (module); + error << Glib::Module::get_last_error() << endmsg; return -1; } + dfunc = (LADSPA_Descriptor_Function)func; + + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path)); + for (uint32_t i = 0; ; ++i) { if ((descriptor = dfunc (i)) == 0) { break; @@ -437,6 +396,8 @@ PluginManager::ladspa_discover (string path) if(!found){ _ladspa_plugin_info->push_back (info); } + + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs)); } // GDB WILL NOT LIKE YOU IF YOU DO THIS @@ -448,6 +409,7 @@ PluginManager::ladspa_discover (string path) string PluginManager::get_ladspa_category (uint32_t plugin_id) { +#ifdef HAVE_LRDF char buf[256]; lrdf_statement pattern; @@ -505,6 +467,9 @@ PluginManager::get_ladspa_category (uint32_t plugin_id) } else { return label; } +#else + return ("Unknown"); +#endif } #ifdef LV2_SUPPORT diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index 3473b73617..0f28b31b57 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -21,7 +21,9 @@ #include "libardour-config.h" #endif +#ifndef PLATFORM_WINDOWS #include <jack/weakjack.h> // so that we can test for new functions at runtime +#endif #include "pbd/compose.h" #include "pbd/error.h" diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc index 411d8d1e19..b2758b2d57 100644 --- a/libs/ardour/port_insert.cc +++ b/libs/ardour/port_insert.cc @@ -250,7 +250,9 @@ PortInsert::signal_latency() const bool PortInsert::configure_io (ChanCount in, ChanCount out) { +#ifndef PLATFORM_WINDOWS assert (!AudioEngine::instance()->process_lock().trylock()); +#endif /* for an insert, processor input corresponds to IO output, and vice versa */ diff --git a/libs/ardour/port_set.cc b/libs/ardour/port_set.cc index 6096e356f5..c7f5e2e674 100644 --- a/libs/ardour/port_set.cc +++ b/libs/ardour/port_set.cc @@ -56,7 +56,7 @@ static bool sort_ports_by_name (boost::shared_ptr<Port> a, boost::shared_ptr<Por // if some of the names don't have a number as posfix, compare as strings - if (last_digit_position_a == aname.size() or last_digit_position_b == bname.size()) { + if (last_digit_position_a == aname.size() || last_digit_position_b == bname.size()) { return aname < bname; } diff --git a/libs/ardour/rc_configuration.cc b/libs/ardour/rc_configuration.cc index 8127267975..4733587654 100644 --- a/libs/ardour/rc_configuration.cc +++ b/libs/ardour/rc_configuration.cc @@ -77,7 +77,7 @@ int RCConfiguration::load_state () { std::string rcfile; - struct stat statbuf; + GStatBuf statbuf; /* load system configuration first */ diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc index 3e81524750..44f8c34ddd 100644 --- a/libs/ardour/region_factory.cc +++ b/libs/ardour/region_factory.cc @@ -564,7 +564,7 @@ RegionFactory::new_region_name (string old) uint32_t number; string::size_type len = old.length() + 64; string remainder; - char buf[len]; + std::vector<char> buf(len); if ((last_period = old.find_last_of ('.')) == string::npos) { @@ -603,8 +603,8 @@ RegionFactory::new_region_name (string old) number++; - snprintf (buf, len, "%s%" PRIu32 "%s", old.substr (0, last_period + 1).c_str(), number, remainder.c_str()); - sbuf = buf; + snprintf (&buf[0], len, "%s%" PRIu32 "%s", old.substr (0, last_period + 1).c_str(), number, remainder.c_str()); + sbuf = &buf[0]; if (region_name_map.find (sbuf) == region_name_map.end ()) { break; @@ -612,7 +612,7 @@ RegionFactory::new_region_name (string old) } if (number != (UINT_MAX-1)) { - return buf; + return &buf[0]; } error << string_compose (_("cannot create new name for region \"%1\""), old) << endmsg; diff --git a/libs/ardour/resampled_source.cc b/libs/ardour/resampled_source.cc index 6184e1a3d6..0a81319108 100644 --- a/libs/ardour/resampled_source.cc +++ b/libs/ardour/resampled_source.cc @@ -26,7 +26,11 @@ using namespace ARDOUR; using namespace PBD; +#ifdef PLATFORM_WINDOWS +const uint32_t ResampledImportableSource::blocksize = 524288U; +#else const uint32_t ResampledImportableSource::blocksize = 16384U; +#endif ResampledImportableSource::ResampledImportableSource (boost::shared_ptr<ImportableSource> src, framecnt_t rate, SrcQuality srcq) : source (src) diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 2e1517fe21..232f295df6 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -1616,7 +1616,9 @@ Route::reset_instrument_info () int Route::configure_processors (ProcessorStreams* err) { +#ifndef PLATFORM_WINDOWS assert (!AudioEngine::instance()->process_lock().trylock()); +#endif if (!_in_configure_processors) { Glib::Threads::RWLock::WriterLock lm (_processor_lock); @@ -1687,7 +1689,9 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err) int Route::configure_processors_unlocked (ProcessorStreams* err) { +#ifndef PLATFORM_WINDOWS assert (!AudioEngine::instance()->process_lock().trylock()); +#endif if (_in_configure_processors) { return 0; @@ -2850,7 +2854,7 @@ Route::feeds (boost::shared_ptr<Route> other, bool* via_sends_only) { const FedBy& fed_by (other->fed_by()); - for (FedBy::iterator f = fed_by.begin(); f != fed_by.end(); ++f) { + for (FedBy::const_iterator f = fed_by.begin(); f != fed_by.end(); ++f) { boost::shared_ptr<Route> sr = f->r.lock(); if (sr && (sr.get() == this)) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index ce82f79bb5..428a5e5274 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -44,8 +44,8 @@ #include "pbd/stacktrace.h" #include "pbd/file_utils.h" #include "pbd/convert.h" -#include "pbd/strsplit.h" #include "pbd/unwind.h" +#include "pbd/search_path.h" #include "ardour/amp.h" #include "ardour/analyser.h" @@ -4427,18 +4427,18 @@ Session::end_time_changed (framepos_t old) } } -string +std::vector<std::string> Session::source_search_path (DataType type) const { - vector<string> s; + Searchpath sp; if (session_dirs.size() == 1) { switch (type) { case DataType::AUDIO: - s.push_back (_session_dir->sound_path()); + sp.push_back (_session_dir->sound_path()); break; case DataType::MIDI: - s.push_back (_session_dir->midi_path()); + sp.push_back (_session_dir->midi_path()); break; } } else { @@ -4446,10 +4446,10 @@ Session::source_search_path (DataType type) const SessionDirectory sdir (i->path); switch (type) { case DataType::AUDIO: - s.push_back (sdir.sound_path()); + sp.push_back (sdir.sound_path()); break; case DataType::MIDI: - s.push_back (sdir.midi_path()); + sp.push_back (sdir.midi_path()); break; } } @@ -4458,49 +4458,30 @@ Session::source_search_path (DataType type) const if (type == DataType::AUDIO) { const string sound_path_2X = _session_dir->sound_path_2X(); if (Glib::file_test (sound_path_2X, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) { - if (find (s.begin(), s.end(), sound_path_2X) == s.end()) { - s.push_back (sound_path_2X); + if (find (sp.begin(), sp.end(), sound_path_2X) == sp.end()) { + sp.push_back (sound_path_2X); } } } - /* now check the explicit (possibly user-specified) search path - */ - - vector<string> dirs; + // now check the explicit (possibly user-specified) search path switch (type) { case DataType::AUDIO: - split (config.get_audio_search_path (), dirs, ':'); + sp += Searchpath(config.get_audio_search_path ()); break; case DataType::MIDI: - split (config.get_midi_search_path (), dirs, ':'); + sp += Searchpath(config.get_midi_search_path ()); break; } - for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) { - if (find (s.begin(), s.end(), *i) == s.end()) { - s.push_back (*i); - } - } - - string search_path; - - for (vector<string>::iterator si = s.begin(); si != s.end(); ++si) { - if (!search_path.empty()) { - search_path += ':'; - } - search_path += *si; - } - - return search_path; + return sp; } void Session::ensure_search_path_includes (const string& path, DataType type) { - string search_path; - vector<string> dirs; + Searchpath sp; if (path == ".") { return; @@ -4508,16 +4489,14 @@ Session::ensure_search_path_includes (const string& path, DataType type) switch (type) { case DataType::AUDIO: - search_path = config.get_audio_search_path (); + sp += Searchpath(config.get_audio_search_path ()); break; case DataType::MIDI: - search_path = config.get_midi_search_path (); + sp += Searchpath (config.get_midi_search_path ()); break; } - split (search_path, dirs, ':'); - - for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) { + for (vector<std::string>::iterator i = sp.begin(); i != sp.end(); ++i) { /* No need to add this new directory if it has the same inode as an existing one; checking inode rather than name prevents duplicated directories when we are using symlinks. @@ -4529,18 +4508,14 @@ Session::ensure_search_path_includes (const string& path, DataType type) } } - if (!search_path.empty()) { - search_path += ':'; - } - - search_path += path; + sp += path; switch (type) { case DataType::AUDIO: - config.set_audio_search_path (search_path); + config.set_audio_search_path (sp.to_string()); break; case DataType::MIDI: - config.set_midi_search_path (search_path); + config.set_midi_search_path (sp.to_string()); break; } } diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index 1d235b051a..3e7c2226cc 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -17,16 +17,6 @@ */ -#include <algorithm> -#include <string> -#include <cmath> -#include <cerrno> -#include <unistd.h> -#include <fcntl.h> -#include <poll.h> - -#include <glibmm/threads.h> - #include "pbd/error.h" #include "pbd/pthread_utils.h" #include "pbd/stacktrace.h" diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc index 6c828ac6f0..19034da247 100644 --- a/libs/ardour/session_events.cc +++ b/libs/ardour/session_events.cc @@ -23,6 +23,7 @@ #include "pbd/error.h" #include "pbd/enumwriter.h" #include "pbd/stacktrace.h" +#include "pbd/pthread_utils.h" #include "ardour/debug.h" #include "ardour/session_event.h" @@ -56,7 +57,7 @@ SessionEvent::operator new (size_t) { CrossThreadPool* p = pool->per_thread_pool (); SessionEvent* ev = static_cast<SessionEvent*> (p->alloc ()); - DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("%1 Allocating SessionEvent from %2 ev @ %3\n", pthread_self(), p->name(), ev)); + DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("%1 Allocating SessionEvent from %2 ev @ %3\n", pthread_name(), p->name(), ev)); #ifndef NDEBUG if (DEBUG::SessionEvents & PBD::debug_bits) { stacktrace (cerr, 40); @@ -74,7 +75,7 @@ SessionEvent::operator delete (void *ptr, size_t /*size*/) DEBUG_TRACE (DEBUG::SessionEvents, string_compose ( "%1 Deleting SessionEvent @ %2 ev thread pool = %3 ev pool = %4\n", - pthread_self(), ev, p->name(), ev->own_pool->name() + pthread_name(), ev, p->name(), ev->own_pool->name() )); #ifndef NDEBUG diff --git a/libs/ardour/session_ltc.cc b/libs/ardour/session_ltc.cc index d6cc201a5c..2671bfccf4 100644 --- a/libs/ardour/session_ltc.cc +++ b/libs/ardour/session_ltc.cc @@ -31,7 +31,6 @@ using namespace std; using namespace ARDOUR; -using namespace MIDI; using namespace PBD; using namespace Timecode; diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index d137e5167c..9a7ca5b734 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -22,8 +22,6 @@ #include <cerrno> #include <cassert> #include <unistd.h> -#include <fcntl.h> -#include <poll.h> #include <boost/shared_ptr.hpp> @@ -35,6 +33,7 @@ #include "pbd/error.h" #include "pbd/pthread_utils.h" +#include "pbd/timersub.h" #include "timecode/time.h" @@ -441,7 +440,7 @@ Session::send_full_time_code (framepos_t const t) * earlier already this cycle by send_full_time_code) */ int -Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_frame, pframes_t nframes) +Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_frame, ARDOUR::pframes_t nframes) { if (_engine.freewheeling() || !_send_qf_mtc || transmitting_timecode_time.negative || (next_quarter_frame_to_send < 0)) { // cerr << "(MTC) Not sending MTC\n"; @@ -513,7 +512,7 @@ Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_f assert (msg_time < end_frame); /* convert from session frames back to JACK frames using the transport speed */ - pframes_t const out_stamp = (msg_time - start_frame) / _transport_speed; + ARDOUR::pframes_t const out_stamp = (msg_time - start_frame) / _transport_speed; assert (out_stamp < nframes); if (MIDI::Manager::instance()->mtc_output_port()->midimsg (mtc_msg, 2, out_stamp)) { @@ -588,7 +587,7 @@ Session::mmc_step_timeout () void -Session::send_song_position_pointer (framepos_t t) +Session::send_song_position_pointer (framepos_t) { if (midi_clock) { /* Do nothing for the moment */ diff --git a/libs/ardour/session_playlists.cc b/libs/ardour/session_playlists.cc index b2c4640880..b586ab196e 100644 --- a/libs/ardour/session_playlists.cc +++ b/libs/ardour/session_playlists.cc @@ -221,11 +221,11 @@ SessionPlaylists::get (vector<boost::shared_ptr<Playlist> >& s) const { Glib::Threads::Mutex::Lock lm (lock); - for (List::iterator i = playlists.begin(); i != playlists.end(); ++i) { + for (List::const_iterator i = playlists.begin(); i != playlists.end(); ++i) { s.push_back (*i); } - for (List::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { + for (List::const_iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { s.push_back (*i); } } @@ -448,11 +448,11 @@ SessionPlaylists::region_use_count (boost::shared_ptr<Region> region) const Glib::Threads::Mutex::Lock lm (lock); uint32_t cnt = 0; - for (List::iterator i = playlists.begin(); i != playlists.end(); ++i) { + for (List::const_iterator i = playlists.begin(); i != playlists.end(); ++i) { cnt += (*i)->region_use_count (region); } - for (List::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { + for (List::const_iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { cnt += (*i)->region_use_count (region); } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 49a0eed559..9699a7c37f 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -33,15 +33,14 @@ #include <unistd.h> #include <sys/stat.h> #include <climits> -#include <fcntl.h> -#include <poll.h> #include <signal.h> -#include <sys/mman.h> #include <sys/time.h> #ifdef HAVE_SYS_VFS_H #include <sys/vfs.h> -#else +#endif + +#ifdef __APPLE__ #include <sys/param.h> #include <sys/mount.h> #endif @@ -70,11 +69,13 @@ #include "pbd/enumwriter.h" #include "pbd/error.h" #include "pbd/file_utils.h" +#include "pbd/pathexpand.h" #include "pbd/pathscanner.h" #include "pbd/pthread_utils.h" #include "pbd/stacktrace.h" #include "pbd/convert.h" #include "pbd/clear_dir.h" +#include "pbd/localtime_r.h" #include "ardour/amp.h" #include "ardour/audio_diskstream.h" @@ -134,14 +135,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) throw failed_constructor(); } - char buf[PATH_MAX+1]; - if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) { - error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg; - destroy (); - throw failed_constructor(); - } - - _path = string(buf); + _path = canonical_path (fullpath); if (_path[_path.length()-1] != G_DIR_SEPARATOR) { _path += G_DIR_SEPARATOR; @@ -390,7 +384,7 @@ Session::second_stage_init () string Session::raid_path () const { - SearchPath raid_search_path; + Searchpath raid_search_path; for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) { raid_search_path += (*i).path; @@ -411,11 +405,11 @@ Session::setup_raid_path (string path) session_dirs.clear (); - SearchPath search_path(path); - SearchPath sound_search_path; - SearchPath midi_search_path; + Searchpath search_path(path); + Searchpath sound_search_path; + Searchpath midi_search_path; - for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) { + for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) { sp.path = *i; sp.blocks = 0; // not needed session_dirs.push_back (sp); @@ -818,9 +812,9 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot } else { - if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) { - error << string_compose (_("could not rename temporary session file %1 to %2"), - tmp_path, xml_path) << endmsg; + if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) { + error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"), + tmp_path, xml_path, g_strerror(errno)) << endmsg; if (g_remove (tmp_path.c_str()) != 0) { error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"), tmp_path, g_strerror (errno)) << endmsg; @@ -2125,6 +2119,54 @@ Session::refresh_disk_space () _total_free_4k_blocks_uncertain = true; } } +#elif defined (COMPILER_MSVC) + vector<string> scanned_volumes; + vector<string>::iterator j; + vector<space_and_path>::iterator i; + DWORD nSectorsPerCluster, nBytesPerSector, + nFreeClusters, nTotalClusters; + char disk_drive[4]; + bool volume_found; + + _total_free_4k_blocks = 0; + + for (i = session_dirs.begin(); i != session_dirs.end(); i++) { + strncpy (disk_drive, (*i).path.c_str(), 3); + disk_drive[3] = 0; + strupr(disk_drive); + + volume_found = false; + if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters))) + { + int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster; + int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters; + i->blocks = (uint32_t)(nFreeBytes / 4096); + + for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) { + if (0 == j->compare(disk_drive)) { + volume_found = true; + break; + } + } + + if (!volume_found) { + scanned_volumes.push_back(disk_drive); + _total_free_4k_blocks += i->blocks; + } + } + } + + if (0 == _total_free_4k_blocks) { + strncpy (disk_drive, path().c_str(), 3); + disk_drive[3] = 0; + + if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters))) + { + int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster; + int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters; + _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096); + } + } #endif } @@ -2311,7 +2353,7 @@ Session::auto_save() } static bool -state_file_filter (const string &str, void */*arg*/) +state_file_filter (const string &str, void* /*arg*/) { return (str.length() > strlen(statefile_suffix) && str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix))); @@ -2488,7 +2530,7 @@ Session::commit_reversible_command (Command *cmd) } static bool -accept_all_audio_files (const string& path, void */*arg*/) +accept_all_audio_files (const string& path, void* /*arg*/) { if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) { return false; @@ -2502,7 +2544,7 @@ accept_all_audio_files (const string& path, void */*arg*/) } static bool -accept_all_midi_files (const string& path, void */*arg*/) +accept_all_midi_files (const string& path, void* /*arg*/) { if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) { return false; @@ -2514,7 +2556,7 @@ accept_all_midi_files (const string& path, void */*arg*/) } static bool -accept_all_state_files (const string& path, void */*arg*/) +accept_all_state_files (const string& path, void* /*arg*/) { if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) { return false; @@ -2670,6 +2712,8 @@ Session::cleanup_sources (CleanupReport& rep) bool used; string spath; int ret = -1; + string tmppath1; + string tmppath2; _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup); @@ -2794,9 +2838,6 @@ Session::cleanup_sources (CleanupReport& rep) i = tmp; } - char tmppath1[PATH_MAX+1]; - char tmppath2[PATH_MAX+1]; - if (candidates) { for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) { @@ -2805,19 +2846,10 @@ Session::cleanup_sources (CleanupReport& rep) for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) { - if (realpath(spath.c_str(), tmppath1) == 0) { - error << string_compose (_("Cannot expand path %1 (%2)"), - spath, strerror (errno)) << endmsg; - continue; - } - - if (realpath((*i).c_str(), tmppath2) == 0) { - error << string_compose (_("Cannot expand path %1 (%2)"), - (*i), strerror (errno)) << endmsg; - continue; - } + tmppath1 = canonical_path (spath); + tmppath2 = canonical_path ((*i)); - if (strcmp(tmppath1, tmppath2) == 0) { + if (tmppath1 == tmppath2) { used = true; break; } @@ -2921,7 +2953,7 @@ Session::cleanup_sources (CleanupReport& rep) string peakpath = peak_path (base); if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) { - if (::unlink (peakpath.c_str()) != 0) { + if (::g_unlink (peakpath.c_str()) != 0) { error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"), peakpath, _path, strerror (errno)) << endmsg; diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc index 644fb19ffb..06a6b80e99 100644 --- a/libs/ardour/session_vst.cc +++ b/libs/ardour/session_vst.cc @@ -17,7 +17,9 @@ */ +#ifndef COMPILER_MSVC #include <stdbool.h> +#endif #include <cstdio> #include "ardour/session.h" @@ -59,11 +61,19 @@ intptr_t Session::vst_callback ( if (effect && effect->user) { plug = (VSTPlugin *) (effect->user); session = &plug->session(); +#ifdef COMPILER_MSVC + SHOW_CALLBACK ("am callback 0x%x, opcode = %d, plugin = \"%s\" ", (int) pthread_self().p, opcode, plug->name()); +#else SHOW_CALLBACK ("am callback 0x%x, opcode = %d, plugin = \"%s\" ", (int) pthread_self(), opcode, plug->name()); +#endif } else { plug = 0; session = 0; +#ifdef COMPILER_MSVC + SHOW_CALLBACK ("am callback 0x%x, opcode = %d", (int) pthread_self().p, opcode); +#else SHOW_CALLBACK ("am callback 0x%x, opcode = %d", (int) pthread_self(), opcode); +#endif } switch(opcode){ diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 830fd75fdf..d915bba845 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -30,6 +30,7 @@ #include "pbd/stl_delete.h" #include "pbd/strsplit.h" +#include <glib/gstdio.h> #include <glibmm/miscutils.h> #include "evoral/Control.hpp" @@ -96,7 +97,7 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist) SMFSource::~SMFSource () { if (removable()) { - unlink (_path.c_str()); + ::g_unlink (_path.c_str()); } } diff --git a/libs/ardour/sndfile_helpers.cc b/libs/ardour/sndfile_helpers.cc index 459890e829..2e618e043b 100644 --- a/libs/ardour/sndfile_helpers.cc +++ b/libs/ardour/sndfile_helpers.cc @@ -17,7 +17,9 @@ */ +#ifndef COMPILER_MSVC #include <strings.h> +#endif #include <map> #include <sndfile.h> diff --git a/libs/ardour/sndfileimportable.cc b/libs/ardour/sndfileimportable.cc index c9f6c4014f..ceb88eddc9 100644 --- a/libs/ardour/sndfileimportable.cc +++ b/libs/ardour/sndfileimportable.cc @@ -51,7 +51,7 @@ SndFileImportableSource::read (Sample* buffer, framecnt_t nframes) return per_channel * sf_info.channels; } -uint +uint32_t SndFileImportableSource::channels () const { return sf_info.channels; diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index cf75cffba3..1c3144f164 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -26,10 +26,11 @@ #include <climits> #include <cstdarg> -#include <pwd.h> -#include <sys/utsname.h> #include <sys/stat.h> +#ifdef PLATFORM_WINDOWS +#include <glibmm/convert.h> +#endif #include <glibmm/miscutils.h> #include "ardour/sndfilesource.h" @@ -184,22 +185,30 @@ SndFileSource::init_sndfile () int SndFileSource::open () { - _descriptor = new SndFileDescriptor (_path, writable(), &_info); + string path_to_open; + +#ifdef PLATFORM_WINDOWS + path_to_open = Glib::locale_from_utf8(_path); +#else + path_to_open = _path; +#endif + + _descriptor = new SndFileDescriptor (path_to_open.c_str(), writable(), &_info); _descriptor->Closed.connect_same_thread (file_manager_connection, boost::bind (&SndFileSource::file_closed, this)); SNDFILE* sf = _descriptor->allocate (); if (sf == 0) { - char errbuf[256]; + char errbuf[1024]; sf_error_str (0, errbuf, sizeof (errbuf) - 1); #ifndef HAVE_COREAUDIO /* if we have CoreAudio, we will be falling back to that if libsndfile fails, so we don't want to see this message. */ - cerr << "failed to open " << _path << " with name " << _name << endl; + cerr << "failed to open " << path_to_open << " with name " << _name << endl; error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"), - _path, (writable() ? "read+write" : "reading"), errbuf) << endmsg; + path_to_open, (writable() ? "read+write" : "reading"), errbuf) << endmsg; #endif return -1; } @@ -253,7 +262,7 @@ SndFileSource::open () if (!_broadcast_info->write_to_file (sf)) { error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"), - _path, _broadcast_info->get_error()) + path_to_open, _broadcast_info->get_error()) << endmsg; _flags = Flag (_flags & ~Broadcast); delete _broadcast_info; @@ -541,6 +550,30 @@ SndFileSource::flush_header () return r; } +void +SndFileSource::flush () +{ + if (!_open) { + warning << string_compose (_("attempt to flush an un-opened audio file source (%1)"), _path) << endmsg; + return; + } + + if (!writable()) { + warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg; + return; + } + + SNDFILE* sf = _descriptor->allocate (); + if (sf == 0) { + error << string_compose (_("could not allocate file %1 to flush contents"), _path) << endmsg; + return; + } + + // Hopefully everything OK + sf_write_sync (sf); + _descriptor->release (); +} + int SndFileSource::setup_broadcast_info (framepos_t /*when*/, struct tm& now, time_t /*tnow*/) { @@ -768,12 +801,12 @@ SndFileSource::crossfade (Sample* data, framecnt_t cnt, int fade_in) } else if (xfade < xfade_frames) { - gain_t in[xfade]; - gain_t out[xfade]; + std::vector<gain_t> in(xfade); + std::vector<gain_t> out(xfade); /* short xfade, compute custom curve */ - compute_equal_power_fades (xfade, in, out); + compute_equal_power_fades (xfade, &in[0], &out[0]); for (framecnt_t n = 0; n < xfade; ++n) { xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]); diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 618dddc70b..03039fea5b 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -19,8 +19,6 @@ #include <sys/stat.h> #include <unistd.h> -#include <fcntl.h> -#include <poll.h> #include <float.h> #include <cerrno> #include <ctime> diff --git a/libs/ardour/sse_functions_xmm.cc b/libs/ardour/sse_functions_xmm.cc index 48212ea8e1..f8a53cc6f8 100644 --- a/libs/ardour/sse_functions_xmm.cc +++ b/libs/ardour/sse_functions_xmm.cc @@ -45,8 +45,11 @@ x86_sse_find_peaks(const ARDOUR::Sample* buf, ARDOUR::pframes_t nframes, float * // use 64 byte prefetch for quadruple quads while (nframes >= 16) { +#ifdef COMPILER_MSVC + _mm_prefetch(((char*)buf+64), 0); // A total guess! Assumed to be eqivalent to +#else // the line below but waiting to be tested !! __builtin_prefetch(buf+64,0,0); - +#endif work = _mm_load_ps(buf); current_min = _mm_min_ps(current_min, work); current_max = _mm_max_ps(current_max, work); diff --git a/libs/ardour/template_utils.cc b/libs/ardour/template_utils.cc index 05007b0ade..b912fdc446 100644 --- a/libs/ardour/template_utils.cc +++ b/libs/ardour/template_utils.cc @@ -37,18 +37,18 @@ using namespace PBD; namespace ARDOUR { -SearchPath +Searchpath template_search_path () { - SearchPath spath (ardour_data_search_path()); + Searchpath spath (ardour_data_search_path()); spath.add_subdirectory_to_paths(templates_dir_name); return spath; } -SearchPath +Searchpath route_template_search_path () { - SearchPath spath (ardour_data_search_path()); + Searchpath spath (ardour_data_search_path()); spath.add_subdirectory_to_paths(route_templates_dir_name); return spath; } @@ -66,7 +66,7 @@ user_route_template_directory () } static bool -template_filter (const string &str, void */*arg*/) +template_filter (const string &str, void* /*arg*/) { if (!Glib::file_test (str, Glib::FILE_TEST_IS_DIR)) { return false; @@ -76,7 +76,7 @@ template_filter (const string &str, void */*arg*/) } static bool -route_template_filter (const string &str, void */*arg*/) +route_template_filter (const string &str, void* /*arg*/) { if (str.find (template_suffix) == str.length() - strlen (template_suffix)) { return true; @@ -97,7 +97,7 @@ find_session_templates (vector<TemplateInfo>& template_names) { vector<string *> *templates; PathScanner scanner; - SearchPath spath (template_search_path()); + Searchpath spath (template_search_path()); templates = scanner (spath.to_string(), template_filter, 0, true, true); @@ -133,7 +133,7 @@ find_route_templates (vector<TemplateInfo>& template_names) { vector<string *> *templates; PathScanner scanner; - SearchPath spath (route_template_search_path()); + Searchpath spath (route_template_search_path()); templates = scanner (spath.to_string(), route_template_filter, 0, false, true); diff --git a/libs/ardour/test/jack_utils_test.cc b/libs/ardour/test/jack_utils_test.cc new file mode 100644 index 0000000000..7645df6ff3 --- /dev/null +++ b/libs/ardour/test/jack_utils_test.cc @@ -0,0 +1,290 @@ + +#include <stdexcept> + +#ifdef PLATFORM_WINDOWS +#include <windows.h> // only for Sleep +#endif + +#include <glibmm/miscutils.h> + +#include "ardour/jack_utils.h" + +#include "jack_utils_test.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (JackUtilsTest); + +using namespace std; +using namespace ARDOUR; + +void +JackUtilsTest::test_driver_names () +{ + vector<string> driver_names; + + get_jack_audio_driver_names (driver_names); + + CPPUNIT_ASSERT(!driver_names.empty()); + + cout << endl; + cout << "Number of possible JACK Audio drivers found on this system: " << driver_names.size () << endl; + + for (vector<string>::const_iterator i = driver_names.begin(); i != driver_names.end(); ++i) { + cout << "JACK Audio driver found: " << *i << endl; + } + + string default_audio_driver; + get_jack_default_audio_driver_name (default_audio_driver); + + cout << "The default audio driver on this system is: " << default_audio_driver << endl; + + driver_names.clear(); + + get_jack_midi_system_names (default_audio_driver, driver_names); + + CPPUNIT_ASSERT(!driver_names.empty()); + + cout << "Number of possible JACK MIDI drivers found on this system for default audio driver: " << driver_names.size () << endl; + + for (vector<string>::const_iterator i = driver_names.begin(); i != driver_names.end(); ++i) { + cout << "JACK MIDI driver found: " << *i << endl; + } + + string default_midi_driver; + get_jack_default_midi_system_name (default_audio_driver, default_midi_driver); + + cout << "The default midi driver on this system is: " << default_midi_driver << endl; +} + +string +devices_string (const vector<string>& devices) +{ + std::string str; + for (vector<string>::const_iterator i = devices.begin(); i != devices.end();) { + str += *i; + if (++i != devices.end()) str += ", "; + } + return str; +} + +void +JackUtilsTest::test_device_names () +{ + vector<string> driver_names; + + get_jack_audio_driver_names (driver_names); + + CPPUNIT_ASSERT(!driver_names.empty()); + + cout << endl; + + for (vector<string>::const_iterator i = driver_names.begin(); i != driver_names.end(); ++i) { + string devices = devices_string (get_jack_device_names_for_audio_driver (*i)); + cout << "JACK Audio driver found: " << *i << " with devices: " << devices << endl; + } +} + +void +JackUtilsTest::test_samplerates () +{ + vector<string> samplerates; + + get_jack_sample_rate_strings (samplerates); + cout << endl; + cout << "Number of possible Samplerates supported by JACK: " << samplerates.size () << endl; + + for (vector<string>::const_iterator i = samplerates.begin(); i != samplerates.end(); ++i) { + cout << "Samplerate: " << *i << endl; + } +} + +void +JackUtilsTest::test_period_sizes () +{ + vector<string> period_sizes; + + get_jack_period_size_strings (period_sizes); + cout << endl; + cout << "Number of possible Period sizes supported by JACK: " << period_sizes.size () << endl; + + for (vector<string>::const_iterator i = period_sizes.begin(); i != period_sizes.end(); ++i) { + cout << "Period size: " << *i << endl; + } +} + +void +JackUtilsTest::test_dither_modes () +{ + vector<string> driver_names; + + get_jack_audio_driver_names (driver_names); + + CPPUNIT_ASSERT(!driver_names.empty()); + + cout << endl; + + for (vector<string>::const_iterator i = driver_names.begin(); i != driver_names.end(); ++i) { + vector<string> dither_modes; + + get_jack_dither_mode_strings (*i, dither_modes); + cout << "Number of possible Dither Modes supported by JACK driver " << *i << + ": " << dither_modes.size () << endl; + for (vector<string>::const_iterator j = dither_modes.begin(); j != dither_modes.end(); ++j) { + cout << "Dither Mode: " << *j << endl; + } + cout << endl; + } + +} + +void +JackUtilsTest::test_connect_server () +{ + cout << endl; + if (jack_server_running ()) { + cout << "Jack server running " << endl; + } else { + cout << "Jack server not running " << endl; + } +} + +void +JackUtilsTest::test_set_jack_path_env () +{ + cout << endl; + + bool path_env_set = false; + + string path_env = Glib::getenv ("PATH", path_env_set); + + if (path_env_set) { + cout << "PATH env set to: " << path_env << endl; + } else { + cout << "PATH env not set" << endl; + } + vector<string> server_dirs; + get_jack_server_dir_paths (server_dirs); + set_path_env_for_jack_autostart (server_dirs); + + path_env_set = false; + + path_env = Glib::getenv ("PATH", path_env_set); + + CPPUNIT_ASSERT (path_env_set); + + cout << "After set_jack_path_env PATH env set to: " << path_env << endl; +} + +void +JackUtilsTest::test_server_paths () +{ + cout << endl; + + vector<std::string> server_dirs; + + CPPUNIT_ASSERT (get_jack_server_dir_paths (server_dirs)); + + cout << "Number of Directories that may contain JACK servers: " << server_dirs.size () << endl; + + for (vector<std::string>::const_iterator i = server_dirs.begin(); i != server_dirs.end(); ++i) { + cout << "JACK server directory path: " << *i << endl; + } + + vector<string> server_names; + + CPPUNIT_ASSERT (get_jack_server_application_names (server_names)); + + cout << "Number of possible JACK server names on this system: " << server_names.size () << endl; + + for (vector<string>::const_iterator i = server_names.begin(); i != server_names.end(); ++i) { + cout << "JACK server name: " << *i << endl; + } + + vector<std::string> server_paths; + + CPPUNIT_ASSERT (get_jack_server_paths (server_dirs, server_names, server_paths)); + + cout << "Number of JACK servers on this system: " << server_paths.size () << endl; + + for (vector<std::string>::const_iterator i = server_paths.begin(); i != server_paths.end(); ++i) { + cout << "JACK server path: " << *i << endl; + } + + vector<std::string> server_paths2; + + CPPUNIT_ASSERT (get_jack_server_paths (server_paths2)); + + CPPUNIT_ASSERT (server_paths.size () == server_paths2.size ()); + + std::string default_server_path; + + CPPUNIT_ASSERT (get_jack_default_server_path (default_server_path)); + + cout << "The default JACK server on this system: " << default_server_path << endl; +} + +bool +get_default_jack_command_line (std::string& command_line) +{ + cout << endl; + + JackCommandLineOptions options; + + CPPUNIT_ASSERT (get_jack_default_server_path (options.server_path)); + + get_jack_default_audio_driver_name (options.driver); + + + // should fail, haven't set any device yet + CPPUNIT_ASSERT (!get_jack_command_line_string (options, command_line)); + + vector<string> devices = get_jack_device_names_for_audio_driver (options.driver); + + if (!devices.empty()) { + options.input_device = devices.front (); + options.output_device = devices.front (); + } else { + cout << "No audio devices available using default JACK driver using Dummy driver" << endl; + options.driver = dummy_driver_name; + devices = get_jack_device_names_for_audio_driver (options.driver); + CPPUNIT_ASSERT (!devices.empty ()); + options.input_device = devices.front (); + options.output_device = devices.front (); + } + + options.input_device = devices.front (); + options.output_device = devices.front (); + + string midi_driver; + + get_jack_default_midi_system_name (options.driver, options.midi_driver); + // + // this at least should create a valid jack command line + return get_jack_command_line_string (options, command_line); + +} + +void +JackUtilsTest::test_config () +{ + std::string config_path(get_jack_server_user_config_file_path()); + + cout << "Jack server config file path: " << config_path << endl; + + std::string command_line; + + CPPUNIT_ASSERT (get_default_jack_command_line (command_line)); + + CPPUNIT_ASSERT (write_jack_config_file (config_path, command_line)); +} + + +void +JackUtilsTest::test_command_line () +{ + string command_line; + + // this at least should create a valid jack command line + CPPUNIT_ASSERT (get_default_jack_command_line (command_line)); + + cout << "Default JACK command line: " << command_line << endl; +} diff --git a/libs/ardour/test/jack_utils_test.h b/libs/ardour/test/jack_utils_test.h new file mode 100644 index 0000000000..08fad2fc36 --- /dev/null +++ b/libs/ardour/test/jack_utils_test.h @@ -0,0 +1,31 @@ + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +class JackUtilsTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE (JackUtilsTest); + CPPUNIT_TEST (test_driver_names); + CPPUNIT_TEST (test_device_names); + CPPUNIT_TEST (test_samplerates); + CPPUNIT_TEST (test_period_sizes); + CPPUNIT_TEST (test_dither_modes); + CPPUNIT_TEST (test_connect_server); + CPPUNIT_TEST (test_set_jack_path_env); + CPPUNIT_TEST (test_server_paths); + CPPUNIT_TEST (test_config); + CPPUNIT_TEST (test_command_line); + CPPUNIT_TEST_SUITE_END (); + +public: + void test_driver_names (); + void test_device_names (); + void test_samplerates (); + void test_period_sizes (); + void test_dither_modes (); + void test_connect_server (); + void test_set_jack_path_env (); + void test_server_paths (); + void test_config (); + void test_command_line (); +}; diff --git a/libs/ardour/test/midi_clock_slave_test.cc b/libs/ardour/test/midi_clock_slave_test.cc index dcb159cb2c..4349df22eb 100644 --- a/libs/ardour/test/midi_clock_slave_test.cc +++ b/libs/ardour/test/midi_clock_slave_test.cc @@ -27,7 +27,7 @@ MIDIClock_SlaveTest::testStepResponse () for (framecnt_t i = 1; i<= 100 * period_size; i++) { // simulate jitter - framecnt_t input_delta = framecnt_t (one_ppqn_in_frames + 0.1 * (double(random()) / double (RAND_MAX)) * one_ppqn_in_frames); + framecnt_t input_delta = framecnt_t (one_ppqn_in_frames + 0.1 * (double(g_random_int()) / double (RAND_MAX)) * one_ppqn_in_frames); if (i % input_delta == 0) { update_midi_clock (*parser, start_time + i); diff --git a/libs/ardour/test/plugins_test.cc b/libs/ardour/test/plugins_test.cc new file mode 100644 index 0000000000..0e4bddcda6 --- /dev/null +++ b/libs/ardour/test/plugins_test.cc @@ -0,0 +1,54 @@ +#include <iostream> + +#include "ardour/plugin_manager.h" +#include "ardour/ladspa_search_path.h" + +#include "plugins_test.h" +#include "test_common.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (PluginsTest); + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + +void +print_plugin_info (PluginInfoPtr pp) +{ + cout << "LADSPA Plugin, name " << pp->name + << ", category " << pp->category + << ", creator " << pp->creator + << ", path " << pp->path + << ", n_inputs " << pp->n_inputs.n_audio () + << ", n_outputs " << pp->n_outputs.n_audio () + << endl; + +} + +void +PluginsTest::test () +{ + PluginManager& pm = PluginManager::instance (); + + pm.refresh (); + + Searchpath ladspa_paths(ladspa_search_path ()); + + cout << "Number of Ladspa paths found: " << ladspa_paths.size () << endl; + + for (vector<std::string>::iterator i = ladspa_paths.begin (); i != ladspa_paths.end(); ++i) + { + cout << "LADSPA search path includes: " << *i << endl; + } + + PluginInfoList& ladspa_list = pm.ladspa_plugin_info (); + + cout << "Number of Ladspa plugins found: " << ladspa_list.size () << endl; + + for (PluginInfoList::iterator i = ladspa_list.begin (); i != ladspa_list.end(); ++i) + { + print_plugin_info (*i); + } + + +} diff --git a/libs/ardour/test/plugins_test.h b/libs/ardour/test/plugins_test.h new file mode 100644 index 0000000000..1503b2bde2 --- /dev/null +++ b/libs/ardour/test/plugins_test.h @@ -0,0 +1,12 @@ +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +class PluginsTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE (PluginsTest); + CPPUNIT_TEST (test); + CPPUNIT_TEST_SUITE_END (); + +public: + void test (); +}; diff --git a/libs/ardour/test/resampled_source_test.cc b/libs/ardour/test/resampled_source_test.cc index 5aaf71b7aa..c8ef0f4a95 100644 --- a/libs/ardour/test/resampled_source_test.cc +++ b/libs/ardour/test/resampled_source_test.cc @@ -1,4 +1,4 @@ -// this is included first to avoid SearchPath definition on windows +// this is included first to avoid Searchpath definition on windows #include "test_common.h" #include "pbd/file_utils.h" diff --git a/libs/ardour/test/test_common.cc b/libs/ardour/test/test_common.cc index 8364d91be1..5f802fbf5a 100644 --- a/libs/ardour/test/test_common.cc +++ b/libs/ardour/test/test_common.cc @@ -25,10 +25,10 @@ using namespace std; -PBD::SearchPath +PBD::Searchpath test_search_path () { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS std::string wsp(g_win32_get_package_installation_directory_of_module(NULL)); return Glib::build_filename (wsp, "ardour_testdata"); #else diff --git a/libs/ardour/test/test_common.h b/libs/ardour/test/test_common.h index 9e15458781..10bfdbc694 100644 --- a/libs/ardour/test/test_common.h +++ b/libs/ardour/test/test_common.h @@ -21,7 +21,7 @@ #include "pbd/search_path.h" -PBD::SearchPath test_search_path (); +PBD::Searchpath test_search_path (); std::string new_test_output_dir (); diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index e7b7648149..f23f1332b8 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -36,7 +36,9 @@ #include <sys/stat.h> #include <sys/time.h> #include <fcntl.h> +#ifndef COMPILER_MSVC #include <dirent.h> +#endif #include <errno.h> #include <regex.h> diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index b80a594495..5eafe7a612 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -528,8 +528,9 @@ VSTPlugin::connect_and_run (BufferSet& bufs, { Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset); - float *ins[_plugin->numInputs]; - float *outs[_plugin->numOutputs]; + // VC++ doesn't support this C99 extension. Use alloca instead of dynamic array (rather than std::vector which allocs on the heap) + float** ins = (float**)alloca(_plugin->numInputs*sizeof(float*)); + float** outs = (float**)alloca(_plugin->numInputs*sizeof(float*)); int32_t i; const uint32_t nbufs = bufs.count().n_audio(); @@ -552,7 +553,7 @@ VSTPlugin::connect_and_run (BufferSet& bufs, } /* we already know it can support processReplacing */ - _plugin->processReplacing (_plugin, ins, outs, nframes); + _plugin->processReplacing (_plugin, &ins[0], &outs[0], nframes); return 0; } diff --git a/libs/ardour/worker.cc b/libs/ardour/worker.cc index b13398c69d..d5238adb60 100644 --- a/libs/ardour/worker.cc +++ b/libs/ardour/worker.cc @@ -23,6 +23,8 @@ #include "ardour/worker.h" #include "pbd/error.h" +#include <glibmm/timer.h> + namespace ARDOUR { Worker::Worker(Workee* workee, uint32_t ring_size) @@ -128,7 +130,7 @@ Worker::run() continue; } while (!verify_message_completeness(_requests)) { - ::usleep(2000); + Glib::usleep(2000); if (_exit) { return; } diff --git a/libs/ardour/wscript b/libs/ardour/wscript index ea08636ea8..87dce06a2a 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -2,6 +2,7 @@ from waflib.extras import autowaf as autowaf from waflib import Options import os +import sys import re import subprocess @@ -101,8 +102,10 @@ libardour_sources = [ 'io.cc', 'io_processor.cc', 'jack_slave.cc', + 'jack_utils.cc', 'kmeterdsp.cc', 'ladspa_plugin.cc', + 'ladspa_search_path.cc', 'location.cc', 'location_importer.cc', 'ltc_slave.cc', @@ -238,13 +241,20 @@ def configure(conf): path_prefix + 'version.cc', 'libardour3', conf.env['MAJOR'], conf.env['MINOR'], 0) autowaf.configure(conf) - autowaf.check_pkg(conf, 'aubio', uselib_store='AUBIO', - atleast_version='0.3.2') autowaf.check_pkg(conf, 'jack', uselib_store='JACK', atleast_version='0.118.2') + if Options.options.dist_target == 'auto': + if re.search ("linux", sys.platform) != None: + autowaf.check_pkg(conf, 'alsa', uselib_store='ALSA') + if Options.options.dist_target == 'mingw': + autowaf.check_pkg(conf, 'portaudio-2.0', uselib_store='PORTAUDIO', + atleast_version='19') autowaf.check_pkg(conf, 'libxml-2.0', uselib_store='XML') - autowaf.check_pkg(conf, 'lrdf', uselib_store='LRDF', - atleast_version='0.4.0') + if Options.options.dist_target != 'mingw': + autowaf.check_pkg(conf, 'lrdf', uselib_store='LRDF', + atleast_version='0.4.0') + autowaf.check_pkg(conf, 'aubio', uselib_store='AUBIO', + atleast_version='0.3.2') autowaf.check_pkg(conf, 'samplerate', uselib_store='SAMPLERATE', atleast_version='0.1.0') autowaf.check_pkg(conf, 'sigc++-2.0', uselib_store='SIGCPP', @@ -381,8 +391,8 @@ def build(bld): obj.name = 'ardour' obj.target = 'ardour' obj.uselib = ['GLIBMM','GTHREAD','AUBIO','SIGCPP','XML','UUID', - 'JACK','SNDFILE','SAMPLERATE','LRDF','AUDIOUNITS', - 'OSX','BOOST','CURL','DL'] + 'JACK', 'ALSA', 'PORTAUDIO', 'SNDFILE','SAMPLERATE','LRDF', + 'AUDIOUNITS', 'OSX','BOOST','CURL','DL'] obj.use = ['libpbd','libmidipp','libevoral','libvamphost', 'libvampplugin','libtaglib','librubberband', 'libaudiographer','libltc'] @@ -481,8 +491,10 @@ def build(bld): create_ardour_test_program(bld, obj.includes, 'framewalk_to_beats', 'test_framewalk_to_beats', ['test/framewalk_to_beats_test.cc']) create_ardour_test_program(bld, obj.includes, 'framepos_plus_beats', 'test_framepos_plus_beats', ['test/framepos_plus_beats_test.cc']) create_ardour_test_program(bld, obj.includes, 'framepos_minus_beats', 'test_framepos_minus_beats', ['test/framepos_minus_beats_test.cc']) + create_ardour_test_program(bld, obj.includes, 'jack_utils', 'test_jack_utils', ['test/jack_utils_test.cc']) create_ardour_test_program(bld, obj.includes, 'playlist_equivalent_regions', 'test_playlist_equivalent_regions', ['test/playlist_equivalent_regions_test.cc']) create_ardour_test_program(bld, obj.includes, 'playlist_layering', 'test_playlist_layering', ['test/playlist_layering_test.cc']) + create_ardour_test_program(bld, obj.includes, 'plugins_test', 'test_plugins', ['test/plugins_test.cc']) create_ardour_test_program(bld, obj.includes, 'region_naming', 'test_region_naming', ['test/region_naming_test.cc']) create_ardour_test_program(bld, obj.includes, 'control_surface', 'test_control_surfaces', ['test/control_surfaces_test.cc']) create_ardour_test_program(bld, obj.includes, 'mtdm_test', 'test_mtdm', ['test/mtdm_test.cc']) @@ -498,8 +510,10 @@ def build(bld): test/framewalk_to_beats_test.cc test/framepos_plus_beats_test.cc test/framepos_minus_beats_test.cc + test/jack_utils_test.cc test/playlist_equivalent_regions_test.cc test/playlist_layering_test.cc + test/plugins_test.cc test/region_naming_test.cc test/control_surfaces_test.cc test/mtdm_test.cc |