diff options
Diffstat (limited to 'libs')
248 files changed, 6862 insertions, 913 deletions
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 165ad6744f..10400c41d7 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 WIN32 #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/butler.h b/libs/ardour/ardour/butler.h index cdd48c3e3a..97020bed66 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 WIN32 +#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 WIN32 + 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 WIN32 + 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/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_profile_manager.h b/libs/ardour/ardour/export_profile_manager.h index 424e0fe163..114fb09647 100644 --- a/libs/ardour/ardour/export_profile_manager.h +++ b/libs/ardour/ardour/export_profile_manager.h @@ -38,6 +38,10 @@ #include "ardour/types.h" #include "ardour/export_handler.h" +#ifdef SearchPath +#undef SearchPath +#endif + namespace ARDOUR { 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..7c817e86a1 100644 --- a/libs/ardour/ardour/filesystem_paths.h +++ b/libs/ardour/ardour/filesystem_paths.h @@ -22,6 +22,10 @@ #include "pbd/search_path.h" +#ifdef SearchPath +#undef SearchPath +#endif + 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..353724f079 --- /dev/null +++ b/libs/ardour/ardour/jack_utils.h @@ -0,0 +1,261 @@ +/* + 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); + + /** + * Temporary for WIN32 only as jack_client_open doesn't start the server on that platform + * + * @return true if server was able to be started + */ + bool start_jack_server (const std::string& command_line); + +} 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..791bba9188 --- /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/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/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/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 8012970133..1044d9a2dc 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/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index c302e06681..7bfc9426cd 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" 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_unit.cc b/libs/ardour/audio_unit.cc index e43033eb67..3636ebf941 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -2453,7 +2453,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..583ed1ae82 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(WIN32) + 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) { 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..65540d4e3d 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -20,7 +20,6 @@ #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> -#include <poll.h> #include <float.h> #include <utime.h> #include <cerrno> @@ -31,6 +30,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 +47,8 @@ #include "i18n.h" +#include "ardour/debug.h" + using namespace std; using namespace ARDOUR; using namespace PBD; @@ -175,7 +182,7 @@ AudioSource::touch_peakfile () { struct stat 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 +191,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 +202,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; } @@ -213,13 +220,15 @@ AudioSource::initialize_peakfile (string audio_path) 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 +236,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 +245,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 +257,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 +326,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 +350,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 +368,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 - - 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; + DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n"); + + 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 +404,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 +412,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 +426,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 +447,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 +457,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 +508,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 +526,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 +551,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 +590,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 +618,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 +652,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 +699,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 +728,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 +763,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 +785,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 +842,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 +876,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 +893,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..4e5f64bd32 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 ((useconds_t) floor (Config->get_automation_interval_msecs() * 1000)); timer (); } } diff --git a/libs/ardour/broadcast_info.cc b/libs/ardour/broadcast_info.cc index a7fa41aaf9..78c6132f85 100644 --- a/libs/ardour/broadcast_info.cc +++ b/libs/ardour/broadcast_info.cc @@ -84,7 +84,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 db1b316368..2998314443 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 WIN32 #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 WIN32 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 WIN32 + 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 WIN32 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 WIN32 + 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 WIN32 + 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*/ } } } @@ -340,18 +385,28 @@ Butler::schedule_transport_work () } void -Butler::summon () +Butler::queue_request (Request::Type r) { - char c = Request::Run; +#ifndef WIN32 + 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); } @@ -359,8 +414,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..3ccc1f134b 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,14 @@ #include "ardour/debug.h" #include "ardour/control_protocol_manager.h" + +#ifdef SearchPath +#undef SearchPath +#endif + #include "ardour/control_protocol_search_path.h" + using namespace ARDOUR; using namespace std; using namespace PBD; @@ -179,7 +185,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 +270,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 +279,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/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/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..6ef4327343 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> 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..c7b03cbdb7 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 WIN32 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..4c7e996e46 100644 --- a/libs/ardour/filesystem_paths.cc +++ b/libs/ardour/filesystem_paths.cc @@ -86,14 +86,30 @@ user_config_directory () std::string ardour_dll_directory () { +#ifdef WIN32 + 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 WIN32 +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 ardour_config_search_path () { @@ -101,7 +117,9 @@ ardour_config_search_path () if (search_path.empty()) { search_path += user_config_directory(); - +#ifdef WIN32 + 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"); @@ -109,6 +127,7 @@ ardour_config_search_path () } search_path += SearchPath (s); +#endif } return search_path; @@ -121,7 +140,9 @@ ardour_data_search_path () if (search_path.empty()) { search_path += user_config_directory(); - +#ifdef WIN32 + 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"); @@ -129,6 +150,7 @@ ardour_data_search_path () } 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 4c91956ffd..fe07332d85 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -25,7 +25,9 @@ #include <sys/stat.h> #include <sys/types.h> #include <sys/time.h> +#ifndef WIN32 #include <sys/resource.h> +#endif #include <unistd.h> #include <fcntl.h> #include <errno.h> @@ -55,7 +57,9 @@ #include <glibmm/fileutils.h> #include <glibmm/miscutils.h> +#ifdef HAVE_LRDF #include <lrdf.h> +#endif #include "pbd/cpus.h" #include "pbd/error.h" @@ -193,6 +197,7 @@ setup_hardware_optimization (bool try_optimization) static void lotsa_files_please () { +#ifndef WIN32 struct rlimit rl; if (getrlimit (RLIMIT_NOFILE, &rl) == 0) { @@ -213,6 +218,7 @@ lotsa_files_please () } else { error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg; } +#endif } int @@ -261,7 +267,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")); @@ -356,7 +364,9 @@ int ARDOUR::cleanup () { delete Library; +#ifdef HAVE_LRDF lrdf_cleanup (); +#endif delete &ControlProtocolManager::instance(); #ifdef WINDOWS_VST_SUPPORT fst_exit (); diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc index cb0fa1b21a..12752c158e 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 WIN32 for (list<pthread_t>::const_iterator i = _thread_list.begin (); i != _thread_list.end(); ++i) { if (*i == pthread_self()) { return true; } } return false; +#endif } diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc index 047b46f553..9be72a9966 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,13 +325,13 @@ 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) { break; @@ -464,7 +465,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 +480,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..1349d49a0c 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -395,7 +395,9 @@ IO::disconnect (void* src) int IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed) { +#ifndef WIN32 assert (!AudioEngine::instance()->process_lock().trylock()); +#endif boost::shared_ptr<Port> port; @@ -466,7 +468,9 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed) int IO::ensure_ports (ChanCount count, bool clear, void* src) { +#ifndef WIN32 assert (!AudioEngine::instance()->process_lock().trylock()); +#endif bool changed = false; @@ -501,7 +505,9 @@ IO::ensure_ports (ChanCount count, bool clear, void* src) int IO::ensure_io (ChanCount count, bool clear, void* src) { +#ifndef WIN32 assert (!AudioEngine::instance()->process_lock().trylock()); +#endif return ensure_ports (count, clear, src); } diff --git a/libs/ardour/jack_utils.cc b/libs/ardour/jack_utils.cc new file mode 100644 index 0000000000..29f7ca4f3e --- /dev/null +++ b/libs/ardour/jack_utils.cc @@ -0,0 +1,947 @@ +/* + 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 WIN32 + 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 WIN32 + midi_system_names.push_back (winmme_midi_driver_name); +#elif __APPLE__ + midi_system_names.push_back (coreaudio_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); + } + } +#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; + } +#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(); +#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 WIN32 + 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(), 1); +#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 WIN32 + 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) { + find_matching_files_in_directories (server_dir_paths, Glib::PatternSpec(*i), 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 WIN32 + // 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 WIN32 + 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();) { +#ifdef WIN32 + oss << quote_string (*i); +#else + oss << *i; +#endif + 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; +} + +bool +ARDOUR::start_jack_server (const string& command_line) +{ +#ifdef WIN32 + STARTUPINFO si; + PROCESS_INFORMATION pi; + char * cmdline = g_strdup (command_line.c_str()); + + memset (&si, 0, sizeof (si)); + si.cb = sizeof (&si); + memset (&pi, 0, sizeof (pi)); + + if (!CreateProcess ( + NULL, // No module name, use command line + cmdline, + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // set handle inheritance to false + 0, // No creation flags + NULL, // Use parents environment block + NULL, // Use parents starting directory + &si, + &pi)) + { + error << string_compose ("cannot start JACK server: %s", g_win32_error_message (GetLastError ())) << endmsg; + } + + g_free (cmdline); + + // wait for 2 seconds for server to start + for (int i = 0; i < 8; ++i) { + Sleep (250); // 1/4 second + if (jack_server_running ()) return true; + } +#endif + return false; +} diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 5a6e577f2d..38d0d8b944 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> @@ -29,7 +33,9 @@ #include <sys/stat.h> #include <cerrno> +#ifdef HAVE_LRDF #include <lrdf.h> +#endif #include "pbd/compose.h" #include "pbd/error.h" @@ -52,16 +58,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 +76,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 +155,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 +641,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 +658,7 @@ LadspaPlugin::get_scale_points(uint32_t port_index) const } lrdf_free_setting_values(points); +#endif return ret; } @@ -710,17 +724,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 +743,7 @@ LadspaPluginInfo::LadspaPluginInfo() void LadspaPlugin::find_presets () { +#ifdef HAVE_LRDF uint32_t id; std::string unique (unique_id()); @@ -759,12 +764,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 +784,7 @@ LadspaPlugin::load_preset (PresetRecord r) } Plugin::load_preset (r); +#endif return true; } @@ -784,6 +792,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 +826,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 +848,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 +871,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 +892,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) { @@ -927,6 +944,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..6ecc1557a3 --- /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 WIN32 + 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 (expand_path ("~/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..e9be71d98e 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" @@ -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; diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index c56b3ffc2f..d44f9351c4 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> @@ -1090,7 +1091,7 @@ LV2Plugin::do_remove_preset(string name) name + ".ttl" ) ); - unlink(preset_file.c_str()); + ::g_unlink(preset_file.c_str()); } bool diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc index 6f54d17d02..8906ddb6c4 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" diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 9c11e818ac..d27c2fa9c7 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..f3541a2e62 100644 --- a/libs/ardour/midi_patch_manager.cc +++ b/libs/ardour/midi_patch_manager.cc @@ -28,6 +28,11 @@ #include "ardour/session.h" #include "ardour/session_directory.h" #include "ardour/midi_patch_manager.h" + +#ifdef SearchPath +#undef SearchPath +#endif + #include "ardour/midi_patch_search_path.h" #include "i18n.h" 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 90b866ca92..415ae6210f 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" @@ -507,7 +506,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: diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc index 78da32e427..82261b58ec 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 WIN32 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/mtc_slave.cc b/libs/ardour/mtc_slave.cc index 8ce0722d8b..db98664292 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" @@ -306,7 +306,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 +422,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 +486,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..4e4ad7fe4d 100644 --- a/libs/ardour/panner_manager.cc +++ b/libs/ardour/panner_manager.cc @@ -28,6 +28,11 @@ #include "ardour/debug.h" #include "ardour/panner_manager.h" + +#ifdef SearchPath +#undef SearchPath +#endif + #include "ardour/panner_search_path.h" #include "i18n.h" @@ -66,6 +71,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 +79,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 +115,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/plugin.cc b/libs/ardour/plugin.cc index 9b2170c349..5e0e020bd1 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -32,7 +32,9 @@ #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..8d4e625876 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,12 @@ #include "ardour/plugin_manager.h" #include "ardour/rc_configuration.h" +#ifdef SearchPath +#undef SearchPath +#endif + +#include "ardour/ladspa_search_path.h" + #ifdef LV2_SUPPORT #include "ardour/lv2_plugin.h" #endif @@ -77,6 +87,8 @@ #include "i18n.h" +#include "ardour/debug.h" + using namespace ARDOUR; using namespace PBD; using namespace std; @@ -126,10 +138,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 +206,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)); -} + Glib::PatternSpec so_extension_pattern("*.so"); + Glib::PatternSpec dylib_extension_pattern("*.dylib"); + Glib::PatternSpec dll_extension_pattern("*.dll"); -int -PluginManager::ladspa_discover_from_path (string /*path*/) -{ - PathScanner scanner; - vector<string *> *plugin_objects; - vector<string *>::iterator x; - int ret = 0; + find_matching_files_in_search_path (ladspa_search_path (), + so_extension_pattern, ladspa_modules); - plugin_objects = scanner (ladspa_path, ladspa_filter, 0, false, true); + 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); - if (plugin_objects) { - for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) { - ladspa_discover (**x); - } - - 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 +270,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 +293,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 +317,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 +400,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 +413,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 +471,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..a1eacca96e 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -21,7 +21,9 @@ #include "libardour-config.h" #endif +#ifndef WIN32 #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 c13927449a..cf33f1b932 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 WIN32 assert (!AudioEngine::instance()->process_lock().trylock()); +#endif /* for an insert, processor input corresponds to IO output, and vice versa */ diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index a394c73d20..671a00319d 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -1615,7 +1615,9 @@ Route::reset_instrument_info () int Route::configure_processors (ProcessorStreams* err) { +#ifndef WIN32 assert (!AudioEngine::instance()->process_lock().trylock()); +#endif if (!_in_configure_processors) { Glib::Threads::RWLock::WriterLock lm (_processor_lock); @@ -1685,7 +1687,9 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err) int Route::configure_processors_unlocked (ProcessorStreams* err) { +#ifndef WIN32 assert (!AudioEngine::instance()->process_lock().trylock()); +#endif if (_in_configure_processors) { return 0; diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index ce82f79bb5..9817f17069 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" @@ -94,6 +94,10 @@ #include "i18n.h" +#ifdef SearchPath +#undef SearchPath +#endif + namespace ARDOUR { class MidiSource; class Processor; @@ -4427,18 +4431,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 +4450,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 +4462,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 +4493,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 +4512,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_midi.cc b/libs/ardour/session_midi.cc index bc7e12a729..e4fd58dedc 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" diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 49a0eed559..62edaa3911 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -33,17 +33,11 @@ #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 -#include <sys/param.h> -#include <sys/mount.h> #endif #ifdef HAVE_SYS_STATVFS_H @@ -70,11 +64,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 +130,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; @@ -818,9 +807,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; @@ -2670,6 +2659,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 +2785,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 +2793,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 +2900,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/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/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..f29682aeaa 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -26,8 +26,6 @@ #include <climits> #include <cstdarg> -#include <pwd.h> -#include <sys/utsname.h> #include <sys/stat.h> #include <glibmm/miscutils.h> 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/template_utils.cc b/libs/ardour/template_utils.cc index 05007b0ade..c57f2400ac 100644 --- a/libs/ardour/template_utils.cc +++ b/libs/ardour/template_utils.cc @@ -32,6 +32,10 @@ #include "ardour/filename_extensions.h" #include "ardour/io.h" +#ifdef SearchPath +#undef SearchPath +#endif + using namespace std; using namespace PBD; diff --git a/libs/ardour/test/jack_utils_test.cc b/libs/ardour/test/jack_utils_test.cc new file mode 100644 index 0000000000..ed80237f78 --- /dev/null +++ b/libs/ardour/test/jack_utils_test.cc @@ -0,0 +1,315 @@ + +#include <stdexcept> + +#ifdef WIN32 +#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; +} + +void +JackUtilsTest::test_config () +{ + +} + +void +JackUtilsTest::test_command_line () +{ + cout << endl; + + JackCommandLineOptions options; + + CPPUNIT_ASSERT (get_jack_default_server_path (options.server_path)); + + get_jack_default_audio_driver_name (options.driver); + + string command_line; + + // 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 + CPPUNIT_ASSERT (get_jack_command_line_string (options, command_line)); + + cout << "Default JACK command line: " << command_line << endl; +} + +void +JackUtilsTest::test_start_server () +{ +#ifdef WIN32 + cout << endl; + + JackCommandLineOptions options; + + CPPUNIT_ASSERT (get_jack_default_server_path (options.server_path)); + + cout << "Starting JACK server at path: " << options.server_path << endl; + + get_jack_default_audio_driver_name (options.driver); + + 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 (); + } + + string command_line; + // this at least should create a valid jack command line + CPPUNIT_ASSERT (get_jack_command_line_string (options, command_line)); + + cout << "Calling start_jack_server with command line: " << command_line << endl; + + CPPUNIT_ASSERT (start_jack_server (command_line)); + + // sleep for 10 seconds + Sleep (10*1000); + + CPPUNIT_ASSERT (jack_server_running ()); +#endif +} diff --git a/libs/ardour/test/jack_utils_test.h b/libs/ardour/test/jack_utils_test.h new file mode 100644 index 0000000000..6a42d1d015 --- /dev/null +++ b/libs/ardour/test/jack_utils_test.h @@ -0,0 +1,33 @@ + +#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 (test_start_server); + 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 (); + void test_start_server (); +}; 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..362a56df7f --- /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/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 diff --git a/libs/audiographer/audiographer/broadcast_info.h b/libs/audiographer/audiographer/broadcast_info.h index c111156c82..819978f8c6 100644 --- a/libs/audiographer/audiographer/broadcast_info.h +++ b/libs/audiographer/audiographer/broadcast_info.h @@ -21,6 +21,8 @@ #ifndef AUDIOGRAPHER_BROADCAST_INFO_H #define AUDIOGRAPHER_BROADCAST_INFO_H +#include <stdint.h> + #include <string> #include <ctime> diff --git a/libs/audiographer/audiographer/debug_utils.h b/libs/audiographer/audiographer/debug_utils.h index a1dad22eaf..693c50064c 100644 --- a/libs/audiographer/audiographer/debug_utils.h +++ b/libs/audiographer/audiographer/debug_utils.h @@ -8,6 +8,7 @@ #ifdef __GNUC__ #include <cxxabi.h> +#include <cstdlib> #endif namespace AudioGrapher diff --git a/libs/audiographer/audiographer/sndfile/tmp_file.h b/libs/audiographer/audiographer/sndfile/tmp_file.h index 8655fd7191..facb872abf 100644 --- a/libs/audiographer/audiographer/sndfile/tmp_file.h +++ b/libs/audiographer/audiographer/sndfile/tmp_file.h @@ -4,6 +4,9 @@ #include <cstdio> #include <string> +#include <glib.h> +#include <glib/gstdio.h> + #include "sndfile_writer.h" #include "sndfile_reader.h" @@ -18,7 +21,7 @@ class TmpFile : public SndfileWriter<T>, public SndfileReader<T> /// \a filename_template must match the requirements for mkstemp, i.e. end in "XXXXXX" TmpFile (char * filename_template, int format, ChannelCount channels, framecnt_t samplerate) - : SndfileHandle (mkstemp(filename_template), true, SndfileBase::ReadWrite, format, channels, samplerate) + : SndfileHandle (g_mkstemp(filename_template), true, SndfileBase::ReadWrite, format, channels, samplerate) , filename (filename_template) {} diff --git a/libs/audiographer/private/gdither/gdither.cc b/libs/audiographer/private/gdither/gdither.cc index fe9ecc655a..d2a237eb74 100644 --- a/libs/audiographer/private/gdither/gdither.cc +++ b/libs/audiographer/private/gdither/gdither.cc @@ -226,7 +226,7 @@ inline static void gdither_innner_loop(const GDitherType dt, switch (bit_depth) { case GDither8bit: - o8[i] = (u_int8_t) (clamped * post_scale); + o8[i] = (uint8_t) (clamped * post_scale); break; case GDither16bit: o16[i] = (int16_t) (clamped * post_scale); diff --git a/libs/audiographer/tests/sndfile/tmp_file_test.cc b/libs/audiographer/tests/sndfile/tmp_file_test.cc index 94647cc1a6..9ce8af7a5c 100644 --- a/libs/audiographer/tests/sndfile/tmp_file_test.cc +++ b/libs/audiographer/tests/sndfile/tmp_file_test.cc @@ -23,7 +23,7 @@ class TmpFileTest : public CppUnit::TestFixture void testProcess() { - uint channels = 2; + uint32_t channels = 2; file.reset (new TmpFile<float>(SF_FORMAT_WAV | SF_FORMAT_FLOAT, channels, 44100)); AllocatingProcessContext<float> c (random_data, frames, channels); c.set_flag (ProcessContext<float>::EndOfInput); diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index e2e92385aa..dbc04d619b 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -179,7 +179,7 @@ public: OverlapPitchResolution overlap_pitch_resolution() const { return _overlap_pitch_resolution; } void set_overlap_pitch_resolution(OverlapPitchResolution opr); - void set_notes (const Sequence<Time>::Notes& n); + void set_notes (const typename Sequence<Time>::Notes& n); typedef boost::shared_ptr< Event<Time> > SysExPtr; typedef boost::shared_ptr<const Event<Time> > constSysExPtr; @@ -269,10 +269,16 @@ public: const const_iterator& end() const { return _end_iter; } + // CONST iterator implementations (x3) typename Notes::const_iterator note_lower_bound (Time t) const; typename PatchChanges::const_iterator patch_change_lower_bound (Time t) const; typename SysExes::const_iterator sysex_lower_bound (Time t) const; + // NON-CONST iterator implementations (x3) + typename Notes::iterator note_lower_bound (Time t); + typename PatchChanges::iterator patch_change_lower_bound (Time t); + typename SysExes::iterator sysex_lower_bound (Time t); + bool control_to_midi_event(boost::shared_ptr< Event<Time> >& ev, const ControlIterator& iter) const; diff --git a/libs/evoral/evoral/midi_util.h b/libs/evoral/evoral/midi_util.h index e1ae7f4620..e4480b347e 100644 --- a/libs/evoral/evoral/midi_util.h +++ b/libs/evoral/evoral/midi_util.h @@ -22,7 +22,6 @@ #include <iostream> #include <stdint.h> -#include <stdbool.h> #include <string> #include <sys/types.h> #include <assert.h> diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index a095daa135..ff624809e8 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -812,7 +812,7 @@ ControlList::modify (iterator iter, double when, double val) (*iter)->when = when; (*iter)->value = val; - if (std::isnan (val)) { + if (::isnan (val)) { abort (); } diff --git a/libs/evoral/src/Curve.cpp b/libs/evoral/src/Curve.cpp index 6f3532fdcb..44fc48f728 100644 --- a/libs/evoral/src/Curve.cpp +++ b/libs/evoral/src/Curve.cpp @@ -22,6 +22,7 @@ #include <climits> #include <cfloat> #include <cmath> +#include <vector> #include <glibmm/threads.h> @@ -56,8 +57,8 @@ Curve::solve () (www.korf.co.uk/spline.pdf) for more details. */ - double x[npoints]; - double y[npoints]; + vector<double> x(npoints); + vector<double> y(npoints); uint32_t i; ControlList::EventList::const_iterator xx; diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp index 204ef58f33..7084a90491 100644 --- a/libs/evoral/src/Sequence.cpp +++ b/libs/evoral/src/Sequence.cpp @@ -1201,11 +1201,13 @@ Sequence<Time>::overlaps_unlocked (const NotePtr& note, const NotePtr& without) template<typename Time> void -Sequence<Time>::set_notes (const Sequence<Time>::Notes& n) +Sequence<Time>::set_notes (const typename Sequence<Time>::Notes& n) { _notes = n; } +// CONST iterator implementations (x3) + /** Return the earliest note with time >= t */ template<typename Time> typename Sequence<Time>::Notes::const_iterator @@ -1239,6 +1241,41 @@ Sequence<Time>::sysex_lower_bound (Time t) const return i; } +// NON-CONST iterator implementations (x3) + +/** Return the earliest note with time >= t */ +template<typename Time> +typename Sequence<Time>::Notes::iterator +Sequence<Time>::note_lower_bound (Time t) +{ + NotePtr search_note(new Note<Time>(0, t, 0, 0, 0)); + typename Sequence<Time>::Notes::iterator i = _notes.lower_bound(search_note); + assert(i == _notes.end() || (*i)->time() >= t); + return i; +} + +/** Return the earliest patch change with time >= t */ +template<typename Time> +typename Sequence<Time>::PatchChanges::iterator +Sequence<Time>::patch_change_lower_bound (Time t) +{ + PatchChangePtr search (new PatchChange<Time> (t, 0, 0, 0)); + typename Sequence<Time>::PatchChanges::iterator i = _patch_changes.lower_bound (search); + assert (i == _patch_changes.end() || musical_time_greater_or_equal_to ((*i)->time(), t)); + return i; +} + +/** Return the earliest sysex with time >= t */ +template<typename Time> +typename Sequence<Time>::SysExes::iterator +Sequence<Time>::sysex_lower_bound (Time t) +{ + SysExPtr search (new Event<Time> (0, t)); + typename Sequence<Time>::SysExes::iterator i = _sysexes.lower_bound (search); + assert (i == _sysexes.end() || (*i)->time() >= t); + return i; +} + template<typename Time> void Sequence<Time>::get_notes (Notes& n, NoteOperator op, uint8_t val, int chan_mask) const @@ -1393,4 +1430,3 @@ Sequence<Time>::dump (ostream& str) const template class Sequence<Evoral::MusicalTime>; } // namespace Evoral - diff --git a/libs/evoral/src/libsmf/smf.c b/libs/evoral/src/libsmf/smf.c index b79d7543b6..ba805e0b04 100644 --- a/libs/evoral/src/libsmf/smf.c +++ b/libs/evoral/src/libsmf/smf.c @@ -39,7 +39,11 @@ #include <assert.h> #include <math.h> #include <errno.h> +#ifdef PLATFORM_WINDOWS +#include <winsock2.h> +#else #include <arpa/inet.h> +#endif #include "smf.h" #include "smf_private.h" @@ -52,7 +56,7 @@ smf_new(void) { int cantfail; - smf_t *smf = malloc(sizeof(smf_t)); + smf_t *smf = (smf_t*)malloc(sizeof(smf_t)); if (smf == NULL) { g_critical("Cannot allocate smf_t structure: %s", strerror(errno)); return (NULL); @@ -85,7 +89,7 @@ smf_delete(smf_t *smf) { /* Remove all the tracks, from last to first. */ while (smf->tracks_array->len > 0) - smf_track_delete(g_ptr_array_index(smf->tracks_array, smf->tracks_array->len - 1)); + smf_track_delete((smf_track_t*)g_ptr_array_index(smf->tracks_array, smf->tracks_array->len - 1)); smf_fini_tempo(smf); @@ -105,7 +109,7 @@ smf_delete(smf_t *smf) smf_track_t * smf_track_new(void) { - smf_track_t *track = malloc(sizeof(smf_track_t)); + smf_track_t *track = (smf_track_t*)malloc(sizeof(smf_track_t)); if (track == NULL) { g_critical("Cannot allocate smf_track_t structure: %s", strerror(errno)); return (NULL); @@ -131,7 +135,7 @@ smf_track_delete(smf_track_t *track) /* Remove all the events, from last to first. */ while (track->events_array->len > 0) - smf_event_delete(g_ptr_array_index(track->events_array, track->events_array->len - 1)); + smf_event_delete((smf_event_t*)g_ptr_array_index(track->events_array, track->events_array->len - 1)); if (track->smf) smf_track_remove_from_smf(track); @@ -213,7 +217,7 @@ smf_track_remove_from_smf(smf_track_t *track) smf_event_t * smf_event_new(void) { - smf_event_t *event = malloc(sizeof(smf_event_t)); + smf_event_t *event = (smf_event_t*)malloc(sizeof(smf_event_t)); if (event == NULL) { g_critical("Cannot allocate smf_event_t structure: %s", strerror(errno)); return (NULL); @@ -246,7 +250,7 @@ smf_event_new_from_pointer(const void *midi_data, size_t len) return (NULL); event->midi_buffer_length = len; - event->midi_buffer = malloc(event->midi_buffer_length); + event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); smf_event_delete(event); @@ -336,7 +340,7 @@ smf_event_new_from_bytes(int first_byte, int second_byte, int third_byte) } event->midi_buffer_length = len; - event->midi_buffer = malloc(event->midi_buffer_length); + event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); smf_event_delete(event); @@ -773,7 +777,7 @@ smf_track_get_event_by_number(const smf_track_t *track, size_t event_number) if (event_number > track->number_of_events) return (NULL); - event = g_ptr_array_index(track->events_array, event_number - 1); + event = (smf_event_t*)g_ptr_array_index(track->events_array, event_number - 1); assert(event); diff --git a/libs/evoral/src/libsmf/smf_decode.c b/libs/evoral/src/libsmf/smf_decode.c index 0951a6e2f8..7a64a15d0d 100644 --- a/libs/evoral/src/libsmf/smf_decode.c +++ b/libs/evoral/src/libsmf/smf_decode.c @@ -37,7 +37,11 @@ #include <assert.h> #include <math.h> #include <errno.h> +#ifdef PLATFORM_WINDOWS +#include <winsock2.h> +#else #include <arpa/inet.h> +#endif #include <stdint.h> #include "smf.h" #include "smf_private.h" @@ -114,7 +118,7 @@ smf_event_decode_textual(const smf_event_t *event, const char *name) int off = 0; char *buf, *extracted; - buf = malloc(BUFFER_SIZE); + buf = (char*)malloc(BUFFER_SIZE); if (buf == NULL) { g_critical("smf_event_decode_textual: malloc failed."); return (NULL); @@ -177,7 +181,7 @@ smf_event_decode_metadata(const smf_event_t *event) break; } - buf = malloc(BUFFER_SIZE); + buf = (char*)malloc(BUFFER_SIZE); if (buf == NULL) { g_critical("smf_event_decode_metadata: malloc failed."); return (NULL); @@ -235,7 +239,7 @@ smf_event_decode_metadata(const smf_event_t *event) off += snprintf(buf + off, BUFFER_SIZE - off, "Time Signature: %d/%d, %d clocks per click, %d notated 32nd notes per quarter note", - event->midi_buffer[3], (int)pow(2, event->midi_buffer[4]), event->midi_buffer[5], + event->midi_buffer[3], (int)pow((double)2, event->midi_buffer[4]), event->midi_buffer[5], event->midi_buffer[6]); break; @@ -302,7 +306,7 @@ smf_event_decode_system_realtime(const smf_event_t *event) return (NULL); } - buf = malloc(BUFFER_SIZE); + buf = (char*)malloc(BUFFER_SIZE); if (buf == NULL) { g_critical("smf_event_decode_system_realtime: malloc failed."); return (NULL); @@ -354,7 +358,7 @@ smf_event_decode_sysex(const smf_event_t *event) return (NULL); } - buf = malloc(BUFFER_SIZE); + buf = (char*)malloc(BUFFER_SIZE); if (buf == NULL) { g_critical("smf_event_decode_sysex: malloc failed."); return (NULL); @@ -455,7 +459,7 @@ smf_event_decode_system_common(const smf_event_t *event) if (smf_event_is_sysex(event)) return (smf_event_decode_sysex(event)); - buf = malloc(BUFFER_SIZE); + buf = (char*)malloc(BUFFER_SIZE); if (buf == NULL) { g_critical("smf_event_decode_system_realtime: malloc failed."); return (NULL); @@ -526,7 +530,7 @@ smf_event_decode(const smf_event_t *event) return (NULL); } - buf = malloc(BUFFER_SIZE); + buf = (char*)malloc(BUFFER_SIZE); if (buf == NULL) { g_critical("smf_event_decode: malloc failed."); return (NULL); @@ -596,7 +600,7 @@ smf_decode(const smf_t *smf) int off = 0; char *buf; - buf = malloc(BUFFER_SIZE); + buf = (char*)malloc(BUFFER_SIZE); if (buf == NULL) { g_critical("smf_event_decode: malloc failed."); return (NULL); diff --git a/libs/evoral/src/libsmf/smf_load.c b/libs/evoral/src/libsmf/smf_load.c index 6da6036ea0..fed4d28bb7 100644 --- a/libs/evoral/src/libsmf/smf_load.c +++ b/libs/evoral/src/libsmf/smf_load.c @@ -40,7 +40,11 @@ #include <math.h> #include <errno.h> #include <ctype.h> +#ifdef PLATFORM_WINDOWS +#include <winsock2.h> +#else #include <arpa/inet.h> +#endif #include "smf.h" #include "smf_private.h" @@ -119,7 +123,7 @@ parse_mthd_header(smf_t *smf) return (-1); } - tmp_mthd = smf->file_buffer; + tmp_mthd = (struct chunk_header_struct*)smf->file_buffer; if (!chunk_signature_matches(tmp_mthd, "MThd")) { g_critical("SMF error: MThd signature not found, is that a MIDI file?"); @@ -405,7 +409,7 @@ extract_sysex_event(const unsigned char *buf, const size_t buffer_length, smf_ev } event->midi_buffer_length = message_length; - event->midi_buffer = malloc(event->midi_buffer_length); + event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate memory in extract_sysex_event(): %s", strerror(errno)); return (-4); @@ -448,7 +452,7 @@ extract_escaped_event(const unsigned char *buf, const size_t buffer_length, smf_ } event->midi_buffer_length = message_length; - event->midi_buffer = malloc(event->midi_buffer_length); + event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate memory in extract_escaped_event(): %s", strerror(errno)); return (-4); @@ -518,7 +522,7 @@ extract_midi_event(const unsigned char *buf, const size_t buffer_length, smf_eve } event->midi_buffer_length = message_length; - event->midi_buffer = malloc(event->midi_buffer_length); + event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate memory in extract_midi_event(): %s", strerror(errno)); return (-4); @@ -607,7 +611,7 @@ make_string(const unsigned char *buf, const size_t buffer_length, uint32_t len) len = buffer_length; } - str = malloc(len + 1); + str = (char*)malloc(len + 1); if (str == NULL) { g_critical("Cannot allocate memory in make_string()."); return (NULL); @@ -658,14 +662,14 @@ smf_event_extract_text(const smf_event_t *event) return (NULL); } - smf_extract_vlq((void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length); + smf_extract_vlq((const unsigned char*)(void *)&(event->midi_buffer[2]), event->midi_buffer_length - 2, &string_length, &length_length); if (string_length <= 0) { g_critical("smf_event_extract_text: truncated MIDI message."); return (NULL); } - return (make_string((void *)(&event->midi_buffer[2] + length_length), event->midi_buffer_length - 2 - length_length, string_length)); + return (make_string((const unsigned char*)(void *)(&event->midi_buffer[2] + length_length), event->midi_buffer_length - 2 - length_length, string_length)); } /** diff --git a/libs/evoral/src/libsmf/smf_save.c b/libs/evoral/src/libsmf/smf_save.c index b99af75461..3b313cff5a 100644 --- a/libs/evoral/src/libsmf/smf_save.c +++ b/libs/evoral/src/libsmf/smf_save.c @@ -39,7 +39,11 @@ #include <assert.h> #include <math.h> #include <errno.h> +#ifdef PLATFORM_WINDOWS +#include <winsock2.h> +#else #include <arpa/inet.h> +#endif #include "smf.h" #include "smf_private.h" @@ -54,7 +58,7 @@ static void * smf_extend(smf_t *smf, const int length) { int i, previous_file_buffer_length = smf->file_buffer_length; - char *previous_file_buffer = smf->file_buffer; + char *previous_file_buffer = (char*)smf->file_buffer; /* XXX: Not terribly efficient. */ smf->file_buffer_length += length; @@ -201,7 +205,7 @@ smf_event_new_textual(int type, const char *text) /* "2 +" is for leading 0xFF 0xtype. */ event->midi_buffer_length = 2 + text_length + MAX_VLQ_LENGTH; - event->midi_buffer = malloc(event->midi_buffer_length); + event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length); if (event->midi_buffer == NULL) { g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno)); smf_event_delete(event); @@ -541,7 +545,7 @@ assert_smf_event_is_identical(const smf_event_t *a, const smf_event_t *b) { assert(a->event_number == b->event_number); assert(a->delta_time_pulses == b->delta_time_pulses); - assert(abs(a->time_pulses - b->time_pulses) <= 2); + assert(abs((long)(a->time_pulses - b->time_pulses)) <= 2); assert(fabs(a->time_seconds - b->time_seconds) <= 0.01); assert(a->track_number == b->track_number); assert(a->midi_buffer_length == b->midi_buffer_length); diff --git a/libs/evoral/src/libsmf/smf_tempo.c b/libs/evoral/src/libsmf/smf_tempo.c index c24e7460c1..6620cd405c 100644 --- a/libs/evoral/src/libsmf/smf_tempo.c +++ b/libs/evoral/src/libsmf/smf_tempo.c @@ -59,7 +59,7 @@ new_tempo(smf_t *smf, size_t pulses) return (previous_tempo); } - tempo = malloc(sizeof(smf_tempo_t)); + tempo = (smf_tempo_t*)malloc(sizeof(smf_tempo_t)); if (tempo == NULL) { g_critical("Cannot allocate smf_tempo_t."); return (NULL); @@ -152,7 +152,7 @@ maybe_add_to_tempo_map(smf_event_t *event) } numerator = event->midi_buffer[3]; - denominator = (int)pow(2, event->midi_buffer[4]); + denominator = (int)pow((double)2, event->midi_buffer[4]); clocks_per_click = event->midi_buffer[5]; notes_per_note = event->midi_buffer[6]; @@ -259,7 +259,7 @@ smf_get_tempo_by_number(const smf_t *smf, size_t number) if (number >= smf->tempo_array->len) return (NULL); - return (g_ptr_array_index(smf->tempo_array, number)); + return ((smf_tempo_t*)g_ptr_array_index(smf->tempo_array, number)); } /** @@ -341,7 +341,7 @@ smf_fini_tempo(smf_t *smf) smf_tempo_t *tempo; while (smf->tempo_array->len > 0) { - tempo = g_ptr_array_index(smf->tempo_array, smf->tempo_array->len - 1); + tempo = (smf_tempo_t*)g_ptr_array_index(smf->tempo_array, smf->tempo_array->len - 1); assert(tempo); memset(tempo, 0, sizeof(smf_tempo_t)); diff --git a/libs/evoral/test/SMFTest.cpp b/libs/evoral/test/SMFTest.cpp index d4b2a28aff..fe9efa479f 100644 --- a/libs/evoral/test/SMFTest.cpp +++ b/libs/evoral/test/SMFTest.cpp @@ -1,5 +1,9 @@ #include "SMFTest.hpp" +#ifdef WIN32 +#include <io.h> // for R_OK +#endif + using namespace std; CPPUNIT_TEST_SUITE_REGISTRATION( SMFTest ); diff --git a/libs/gtkmm2ext/bindings.cc b/libs/gtkmm2ext/bindings.cc index e049cd8d57..f96bd586d9 100644 --- a/libs/gtkmm2ext/bindings.cc +++ b/libs/gtkmm2ext/bindings.cc @@ -19,6 +19,8 @@ #include <iostream> +#include <glib/gstdio.h> + #include "pbd/xml++.h" #include "pbd/convert.h" @@ -389,7 +391,7 @@ Bindings::save (const string& path) save (*root); if (!tree.write (path)) { - ::unlink (path.c_str()); + ::g_unlink (path.c_str()); return false; } diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc index 6e466f5c9f..831fa7e38f 100644 --- a/libs/gtkmm2ext/gtk_ui.cc +++ b/libs/gtkmm2ext/gtk_ui.cc @@ -94,7 +94,7 @@ UI::UI (string namestr, int *argc, char ***argv) /* attach our request source to the default main context */ - request_channel.ios()->attach (MainContext::get_default()); + attach_request_source (); errors = new TextViewer (800,600); errors->text().set_editable (false); diff --git a/libs/gtkmm2ext/gtkmm2ext/auto_spin.h b/libs/gtkmm2ext/gtkmm2ext/auto_spin.h index b692a7ccdc..4eab2dae98 100644 --- a/libs/gtkmm2ext/gtkmm2ext/auto_spin.h +++ b/libs/gtkmm2ext/gtkmm2ext/auto_spin.h @@ -20,6 +20,10 @@ #ifndef __gtkmm2ext_auto_spin_h__ #define __gtkmm2ext_auto_spin_h__ +#ifdef interface +#undef interface +#endif + #include <gtkmm.h> namespace Gtkmm2ext { diff --git a/libs/gtkmm2ext/gtkmm2ext/click_box.h b/libs/gtkmm2ext/gtkmm2ext/click_box.h index 8f9655e2bf..ea0041e540 100644 --- a/libs/gtkmm2ext/gtkmm2ext/click_box.h +++ b/libs/gtkmm2ext/gtkmm2ext/click_box.h @@ -20,6 +20,10 @@ #ifndef __gtkmm2ext_click_box_h__ #define __gtkmm2ext_click_box_h__ +#ifdef interface +#undef interface +#endif + #include <string> #include <gtkmm.h> diff --git a/libs/gtkmm2ext/gtkmm2ext/doi.h b/libs/gtkmm2ext/gtkmm2ext/doi.h index 6ad1f7dd94..f61127dd74 100644 --- a/libs/gtkmm2ext/gtkmm2ext/doi.h +++ b/libs/gtkmm2ext/gtkmm2ext/doi.h @@ -20,6 +20,10 @@ #ifndef __ardour_gtk_doi_h__ #define __ardour_gtk_doi_h__ +#ifdef interface +#undef interface +#endif + #include <gtkmm.h> /* XXX g++ 2.95 can't compile this as pair of member function templates */ diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h index 64176232f0..a758ad78f4 100644 --- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h +++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h @@ -27,6 +27,10 @@ #include <setjmp.h> #include <pthread.h> +#ifdef interface +#undef interface +#endif + #include <glibmm/thread.h> #include <gtkmm/widget.h> diff --git a/libs/gtkmm2ext/gtkmm2ext/popup.h b/libs/gtkmm2ext/gtkmm2ext/popup.h index 1db357341d..994932e733 100644 --- a/libs/gtkmm2ext/gtkmm2ext/popup.h +++ b/libs/gtkmm2ext/gtkmm2ext/popup.h @@ -20,6 +20,10 @@ #ifndef __qui_popup_h__ #define __qui_popup_h__ +#ifdef interface +#undef interface +#endif + #include <string> #include <gtkmm.h> diff --git a/libs/gtkmm2ext/gtkmm2ext/selector.h b/libs/gtkmm2ext/gtkmm2ext/selector.h index 841742db03..56e075a242 100644 --- a/libs/gtkmm2ext/gtkmm2ext/selector.h +++ b/libs/gtkmm2ext/gtkmm2ext/selector.h @@ -19,6 +19,10 @@ #ifndef __gtkselector_h__ #define __gtkselector_h__ +#ifdef interface +#undef interface +#endif + #include <string> #include <vector> diff --git a/libs/gtkmm2ext/gtkmm2ext/slider_controller.h b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h index 4c6a5cb41d..42ed05a761 100644 --- a/libs/gtkmm2ext/gtkmm2ext/slider_controller.h +++ b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h @@ -19,6 +19,10 @@ #ifndef __gtkmm2ext_slider_controller_h__ #define __gtkmm2ext_slider_controller_h__ +#ifdef interface +#undef interface +#endif + #include <gtkmm.h> #include <gtkmm2ext/popup.h> #include <gtkmm2ext/pixfader.h> diff --git a/libs/gtkmm2ext/idle_adjustment.cc b/libs/gtkmm2ext/idle_adjustment.cc index 3e3a3da566..f74a3a9701 100644 --- a/libs/gtkmm2ext/idle_adjustment.cc +++ b/libs/gtkmm2ext/idle_adjustment.cc @@ -22,6 +22,8 @@ #include <gtkmm/main.h> #include <iostream> +#include "pbd/timersub.h" + using namespace Gtk; using namespace sigc; using namespace Gtkmm2ext; diff --git a/libs/gtkmm2ext/motionfeedback.cc b/libs/gtkmm2ext/motionfeedback.cc index 44fb3e5f47..221a8b0bd6 100644 --- a/libs/gtkmm2ext/motionfeedback.cc +++ b/libs/gtkmm2ext/motionfeedback.cc @@ -25,6 +25,8 @@ #include <unistd.h> #include <stdio.h> /* for snprintf, grrr */ +#include <glib/gstdio.h> + #include <gdk/gdkkeysyms.h> #include <gtkmm.h> @@ -468,14 +470,18 @@ Glib::RefPtr<Gdk::Pixbuf> MotionFeedback::render_pixbuf (int size) { Glib::RefPtr<Gdk::Pixbuf> pixbuf; - char path[32]; + char *path; int fd; + GError *error = NULL; - snprintf (path, sizeof (path), "/tmp/mfimg%dXXXXXX", size); - - if ((fd = mkstemp (path)) < 0) { + fd = g_file_open_tmp ("mfimgXXXXXX", &path, &error); + close (fd); + + if(error) { + g_critical("failed to open a temporary file for writing: %s.", error->message); + g_error_free (error); return pixbuf; - } + } GdkColor col2 = {0,0,0,0}; GdkColor col3 = {0,0,0,0}; @@ -512,15 +518,17 @@ MotionFeedback::render_pixbuf (int size) pixbuf = Gdk::Pixbuf::create_from_file (path); } catch (const Gdk::PixbufError &e) { std::cerr << "Caught PixbufError: " << e.what() << std::endl; - unlink (path); + ::g_unlink (path); throw; } catch (...) { - unlink (path); + ::g_unlink (path); g_message("Caught ... "); throw; } - unlink (path); + ::g_unlink (path); + + g_free(path); return pixbuf; } diff --git a/libs/midi++2/channel.cc b/libs/midi++2/channel.cc index 66ce5ed71c..ed8f4da5bc 100644 --- a/libs/midi++2/channel.cc +++ b/libs/midi++2/channel.cc @@ -25,7 +25,7 @@ using namespace MIDI; -Channel::Channel (byte channelnum, Port &p) +Channel::Channel (MIDI::byte channelnum, Port &p) : _port (p) { _channel_number = channelnum; @@ -182,13 +182,13 @@ Channel::process_controller (Parser & /*parser*/, EventTwoBytes *tb) } void -Channel::process_program_change (Parser & /*parser*/, byte val) +Channel::process_program_change (Parser & /*parser*/, MIDI::byte val) { _program_number = val; } void -Channel::process_chanpress (Parser & /*parser*/, byte val) +Channel::process_chanpress (Parser & /*parser*/, MIDI::byte val) { _chanpress = val; } @@ -215,7 +215,7 @@ Channel::process_reset (Parser & /*parser*/) * \return true if success */ bool -Channel::channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp) +Channel::channel_msg (MIDI::byte id, MIDI::byte val1, MIDI::byte val2, timestamp_t timestamp) { unsigned char msg[3]; int len = 0; diff --git a/libs/midi++2/ipmidi_port.cc b/libs/midi++2/ipmidi_port.cc index c90a3dbe6f..4c0282f1f7 100644 --- a/libs/midi++2/ipmidi_port.cc +++ b/libs/midi++2/ipmidi_port.cc @@ -25,9 +25,17 @@ #include <errno.h> #include <stdlib.h> #include <string.h> +#ifdef COMPILER_MSVC +#undef O_NONBLOCK +#define O_NONBLOCK 0 +#endif +#if defined(PLATFORM_WINDOWS) +#include <winsock2.h> +#else #include <netdb.h> +#endif -#if defined(WIN32) +#if defined(PLATFORM_WINDOWS) static WSADATA g_wsaData; typedef int socklen_t; #else @@ -112,7 +120,7 @@ get_address (int sock, struct in_addr *inaddr, const string& ifname ) { // Get interface address from supplied name. -#if !defined(WIN32) +#if !defined(PLATFORM_WINDOWS) struct ifreq ifr; ::strncpy(ifr.ifr_name, ifname.c_str(), sizeof(ifr.ifr_name)); @@ -141,12 +149,13 @@ get_address (int sock, struct in_addr *inaddr, const string& ifname ) return false; -#endif // !WIN32 +#endif // !PLATFORM_WINDOWS' } bool IPMIDIPort::open_sockets (int base_port, const string& ifname) { +#if !defined(PLATFORM_WINDOWS) int protonum = 0; struct protoent *proto = ::getprotobyname("IP"); @@ -243,10 +252,13 @@ IPMIDIPort::open_sockets (int base_port, const string& ifname) } return true; +#else + return false; +#endif // !PLATFORM_WINDOWS' } int -IPMIDIPort::write (const byte* msg, size_t msglen, timestamp_t /* ignored */) { +IPMIDIPort::write (const MIDI::byte* msg, size_t msglen, timestamp_t /* ignored */) { if (sockout) { Glib::Threads::Mutex::Lock lm (write_lock); @@ -260,7 +272,7 @@ IPMIDIPort::write (const byte* msg, size_t msglen, timestamp_t /* ignored */) { } int -IPMIDIPort::read (byte* /*buf*/, size_t /*bufsize*/) +IPMIDIPort::read (MIDI::byte* /*buf*/, size_t /*bufsize*/) { /* nothing to do here - all handled by parse() */ return 0; diff --git a/libs/midi++2/jack_midi_port.cc b/libs/midi++2/jack_midi_port.cc index 05df3171fa..38ec4d35c7 100644 --- a/libs/midi++2/jack_midi_port.cc +++ b/libs/midi++2/jack_midi_port.cc @@ -19,6 +19,7 @@ */ #include <iostream> #include <cstdio> +#include <unistd.h> #include <fcntl.h> #include <errno.h> @@ -57,7 +58,9 @@ JackMIDIPort::JackMIDIPort (string const & name, Flags flags, jack_client_t* jac , _last_write_timestamp (0) , output_fifo (512) , input_fifo (1024) +#ifndef PLATFORM_WINDOWS , xthread (true) +#endif { assert (jack_client); init (name, flags); @@ -72,7 +75,9 @@ JackMIDIPort::JackMIDIPort (const XMLNode& node, jack_client_t* jack_client) , _last_write_timestamp (0) , output_fifo (512) , input_fifo (1024) +#ifndef PLATFORM_WINDOWS , xthread (true) +#endif { assert (jack_client); @@ -169,7 +174,9 @@ JackMIDIPort::cycle_start (pframes_t nframes) } if (event_count) { +#ifndef PLATFORM_WINDOWS xthread.wakeup (); +#endif } } } @@ -207,12 +214,12 @@ JackMIDIPort::drain (int check_interval_usecs) if (vec.len[0] + vec.len[1] >= output_fifo.bufsize() - 1) { break; } - usleep (check_interval_usecs); + g_usleep (check_interval_usecs); } } int -JackMIDIPort::write (const byte * msg, size_t msglen, timestamp_t timestamp) +JackMIDIPort::write (const MIDI::byte * msg, size_t msglen, timestamp_t timestamp) { int ret = 0; @@ -340,7 +347,7 @@ JackMIDIPort::flush (void* jack_port_buffer) } int -JackMIDIPort::read (byte *, size_t) +JackMIDIPort::read (MIDI::byte *, size_t) { if (!receives_input()) { return 0; @@ -349,9 +356,9 @@ JackMIDIPort::read (byte *, size_t) timestamp_t time; Evoral::EventType type; uint32_t size; - byte buffer[input_fifo.capacity()]; + vector<MIDI::byte> buffer(input_fifo.capacity()); - while (input_fifo.read (&time, &type, &size, buffer)) { + while (input_fifo.read (&time, &type, &size, &buffer[0])) { _parser->set_timestamp (time); for (uint32_t i = 0; i < size; ++i) { _parser->scanner (buffer[i]); @@ -458,7 +465,7 @@ JackMIDIPort::set_process_thread (pthread_t thr) bool JackMIDIPort::is_process_thread() { - return (pthread_self() == _process_thread); + return (pthread_equal(pthread_self(), _process_thread)); } void diff --git a/libs/midi++2/midi++/ipmidi_port.h b/libs/midi++2/midi++/ipmidi_port.h index c077170026..a4adb14cf4 100644 --- a/libs/midi++2/midi++/ipmidi_port.h +++ b/libs/midi++2/midi++/ipmidi_port.h @@ -21,7 +21,7 @@ #include <string> #include <iostream> -#if defined(WIN32) +#if defined(PLATFORM_WINDOWS) #include <winsock.h> #elif defined(__FREE_BSD__) #include <netinet/in.h> diff --git a/libs/midi++2/midi++/jack_midi_port.h b/libs/midi++2/midi++/jack_midi_port.h index a8859387a4..284df0ef2d 100644 --- a/libs/midi++2/midi++/jack_midi_port.h +++ b/libs/midi++2/midi++/jack_midi_port.h @@ -57,7 +57,13 @@ class JackMIDIPort : public Port { int write (const byte *msg, size_t msglen, timestamp_t timestamp); int read (byte *buf, size_t bufsize); void drain (int check_interval_usecs); - int selectable () const { return xthread.selectable(); } + int selectable () const { +#ifdef PLATFORM_WINDOWS + return false; +#else + return xthread.selectable(); +#endif + } pframes_t nframes_this_cycle() const { return _nframes_this_cycle; } @@ -80,7 +86,9 @@ private: RingBuffer< Evoral::Event<double> > output_fifo; Evoral::EventRingBuffer<timestamp_t> input_fifo; Glib::Threads::Mutex output_fifo_lock; +#ifndef PLATFORM_WINDOWS CrossThreadChannel xthread; +#endif int create_port (); diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h index 599fabaa87..153cfb0529 100644 --- a/libs/midi++2/midi++/port.h +++ b/libs/midi++2/midi++/port.h @@ -24,8 +24,12 @@ #include <jack/types.h> +#include <pthread.h> + #include "pbd/xml++.h" +#ifndef PLATFORM_WINDOWS #include "pbd/crossthread.h" +#endif #include "pbd/signals.h" #include "pbd/ringbuffer.h" diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc index bf22792f70..0498168843 100644 --- a/libs/midi++2/midnam_patch.cc +++ b/libs/midi++2/midnam_patch.cc @@ -371,7 +371,7 @@ operator<< (std::ostream& os, const ChannelNameSet& cns) << "List size " << cns._patch_list.size() << endl << "Patch list name = [" << cns._patch_list_name << ']' << endl << "Available channels : "; - for (set<uint8_t>::iterator x = cns._available_for_channels.begin(); x != cns._available_for_channels.end(); ++x) { + for (set<uint8_t>::const_iterator x = cns._available_for_channels.begin(); x != cns._available_for_channels.end(); ++x) { os << (int) (*x) << ' '; } os << endl; diff --git a/libs/midi++2/mmc.cc b/libs/midi++2/mmc.cc index 06eadb5b34..1b8de40358 100644 --- a/libs/midi++2/mmc.cc +++ b/libs/midi++2/mmc.cc @@ -29,6 +29,10 @@ #include "midi++/parser.h" #include "midi++/manager.h" +#ifndef __INT_MAX__ // 'ssize_t' won't be defined yet +typedef long ssize_t; +#endif + using namespace std; using namespace MIDI; using namespace PBD; @@ -213,19 +217,19 @@ MachineControl::MachineControl (Manager* m, jack_client_t* jack) } void -MachineControl::set_receive_device_id (byte id) +MachineControl::set_receive_device_id (MIDI::byte id) { _receive_device_id = id & 0x7f; } void -MachineControl::set_send_device_id (byte id) +MachineControl::set_send_device_id (MIDI::byte id) { _send_device_id = id & 0x7f; } bool -MachineControl::is_mmc (byte *sysex_buf, size_t len) +MachineControl::is_mmc (MIDI::byte *sysex_buf, size_t len) { if (len < 4 || len > 48) { return false; @@ -244,7 +248,7 @@ MachineControl::is_mmc (byte *sysex_buf, size_t len) } void -MachineControl::process_mmc_message (Parser &, byte *msg, size_t len) +MachineControl::process_mmc_message (Parser &, MIDI::byte *msg, size_t len) { size_t skiplen; byte *mmc_msg; @@ -451,7 +455,7 @@ MachineControl::process_mmc_message (Parser &, byte *msg, size_t len) } int -MachineControl::do_masked_write (byte *msg, size_t len) +MachineControl::do_masked_write (MIDI::byte *msg, size_t len) { /* return the number of bytes "consumed" */ @@ -477,7 +481,7 @@ MachineControl::do_masked_write (byte *msg, size_t len) } void -MachineControl::write_track_status (byte *msg, size_t /*len*/, byte reg) +MachineControl::write_track_status (MIDI::byte *msg, size_t /*len*/, MIDI::byte reg) { size_t n; ssize_t base_track; @@ -566,7 +570,7 @@ MachineControl::write_track_status (byte *msg, size_t /*len*/, byte reg) } int -MachineControl::do_locate (byte *msg, size_t /*msglen*/) +MachineControl::do_locate (MIDI::byte *msg, size_t /*msglen*/) { if (msg[2] == 0) { warning << "MIDI::MMC: locate [I/F] command not supported" @@ -581,7 +585,7 @@ MachineControl::do_locate (byte *msg, size_t /*msglen*/) } int -MachineControl::do_step (byte *msg, size_t /*msglen*/) +MachineControl::do_step (MIDI::byte *msg, size_t /*msglen*/) { int steps = msg[2] & 0x3f; @@ -594,7 +598,7 @@ MachineControl::do_step (byte *msg, size_t /*msglen*/) } int -MachineControl::do_shuttle (byte *msg, size_t /*msglen*/) +MachineControl::do_shuttle (MIDI::byte *msg, size_t /*msglen*/) { size_t forward; byte sh = msg[2]; diff --git a/libs/midi++2/mtc.cc b/libs/midi++2/mtc.cc index affe65ec68..3c58b6684f 100644 --- a/libs/midi++2/mtc.cc +++ b/libs/midi++2/mtc.cc @@ -36,7 +36,7 @@ using namespace MIDI; #undef DEBUG_MTC bool -Parser::possible_mtc (byte *sysex_buf, size_t msglen) +Parser::possible_mtc (MIDI::byte *sysex_buf, size_t msglen) { byte fake_mtc_time[5]; @@ -91,7 +91,7 @@ Parser::reset_mtc_state () } void -Parser::process_mtc_quarter_frame (byte *msg) +Parser::process_mtc_quarter_frame (MIDI::byte *msg) { int which_quarter_frame = (msg[1] & 0xf0) >> 4; diff --git a/libs/midi++2/parser.cc b/libs/midi++2/parser.cc index 8e3af64504..94daef7871 100644 --- a/libs/midi++2/parser.cc +++ b/libs/midi++2/parser.cc @@ -137,7 +137,7 @@ Parser::~Parser () } void -Parser::trace_event (Parser &, byte *msg, size_t len) +Parser::trace_event (Parser &, MIDI::byte *msg, size_t len) { eventType type; ostream *o; @@ -659,7 +659,7 @@ Parser::system_msg (unsigned char inbyte) } void -Parser::signal (byte *msg, size_t len) +Parser::signal (MIDI::byte *msg, size_t len) { channel_t chan = msg[0]&0xF; int chan_i = chan; @@ -762,7 +762,7 @@ Parser::signal (byte *msg, size_t len) } bool -Parser::possible_mmc (byte *msg, size_t msglen) +Parser::possible_mmc (MIDI::byte *msg, size_t msglen) { if (!MachineControl::is_mmc (msg, msglen)) { return false; diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc index a7e148c839..3a4257ebdd 100644 --- a/libs/pbd/base_ui.cc +++ b/libs/pbd/base_ui.cc @@ -19,7 +19,11 @@ #include <cstring> #include <stdint.h> +#ifdef COMPILER_MSVC +#include <io.h> // Microsoft's nearest equivalent to <unistd.h> +#else #include <unistd.h> +#endif #include <fcntl.h> #include <cerrno> #include <cstring> @@ -33,6 +37,8 @@ #include "i18n.h" +#include "pbd/debug.h" + using namespace std; using namespace PBD; using namespace Glib; @@ -42,13 +48,18 @@ BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type(); BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type(); BaseUI::BaseUI (const string& str) - : request_channel (true) + : m_context(MainContext::get_default()) , run_loop_thread (0) , _name (str) +#ifndef PLATFORM_WINDOWS + , request_channel (true) +#endif { base_ui_instance = this; +#ifndef PLATFORM_WINDOWS request_channel.ios()->connect (sigc::mem_fun (*this, &BaseUI::request_handler)); +#endif /* derived class must set _ok */ } @@ -73,7 +84,7 @@ BaseUI::new_request_type () void BaseUI::main_thread () { - DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", name(), pthread_self())); + DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", name(), pthread_name())); set_event_loop_for_thread (this); thread_init (); _main_loop->get_context()->signal_idle().connect (sigc::mem_fun (*this, &BaseUI::signal_running)); @@ -95,11 +106,9 @@ BaseUI::run () /* to be called by UI's that need/want their own distinct, self-created event loop thread. */ - _main_loop = MainLoop::create (MainContext::create()); - request_channel.ios()->attach (_main_loop->get_context()); - - /* glibmm hack - drop the refptr to the IOSource now before it can hurt */ - request_channel.drop_ios (); + m_context = MainContext::create(); + _main_loop = MainLoop::create (m_context); + attach_request_source (); Glib::Threads::Mutex::Lock lm (_run_lock); run_loop_thread = Glib::Threads::Thread::create (mem_fun (*this, &BaseUI::main_thread)); @@ -115,6 +124,24 @@ BaseUI::quit () } } +#ifdef PLATFORM_WINDOWS +gboolean +BaseUI::_request_handler (gpointer data) +{ + BaseUI* ui = static_cast<BaseUI*>(data); + return ui->request_handler (); +} + +bool +BaseUI::request_handler () +{ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n"); + handle_ui_requests (); + // keep calling indefinitely at the timeout interval + return true; +} + +#else bool BaseUI::request_handler (Glib::IOCondition ioc) { @@ -133,9 +160,39 @@ BaseUI::request_handler (Glib::IOCondition ioc) /* handle requests */ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n"); handle_ui_requests (); } return true; } - +#endif + +void +BaseUI::signal_new_request () +{ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::signal_new_request\n"); +#ifdef PLATFORM_WINDOWS + // handled in timeout, how to signal...? +#else + request_channel.wakeup (); +#endif +} + +/** + * This method relies on the caller having already set m_context + */ +void +BaseUI::attach_request_source () +{ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::attach_request_source\n"); +#ifdef PLATFORM_WINDOWS + GSource* request_source = g_timeout_source_new(200); + g_source_set_callback (request_source, &BaseUI::_request_handler, this, NULL); + g_source_attach (request_source, m_context->gobj()); +#else + request_channel.ios()->attach (m_context); + /* glibmm hack - drop the refptr to the IOSource now before it can hurt */ + request_channel.drop_ios (); +#endif +} diff --git a/libs/pbd/clear_dir.cc b/libs/pbd/clear_dir.cc index 29410d41e5..2f9c7b772d 100644 --- a/libs/pbd/clear_dir.cc +++ b/libs/pbd/clear_dir.cc @@ -17,13 +17,22 @@ */ -#include <string> +#ifdef COMPILER_MSVC +#include <io.h> // Microsoft's nearest equivalent to <unistd.h> +using PBD::readdir; +using PBD::opendir; +using PBD::closedir; +#else #include <dirent.h> #include <unistd.h> +#endif + +#include <string> #include <sys/stat.h> #include <errno.h> #include <string.h> +#include <glib/gstdio.h> #include <glibmm/miscutils.h> #include "pbd/error.h" @@ -66,7 +75,7 @@ PBD::clear_directory (const string& dir, size_t* size, vector<string>* paths) continue; } - if (::unlink (fullpath.c_str())) { + if (::g_unlink (fullpath.c_str())) { error << string_compose (_("cannot remove file %1 (%2)"), fullpath, strerror (errno)) << endmsg; ret = 1; diff --git a/libs/pbd/debug.cc b/libs/pbd/debug.cc index c86afbe87e..fba457c83e 100644 --- a/libs/pbd/debug.cc +++ b/libs/pbd/debug.cc @@ -24,6 +24,8 @@ #include <vector> #include <algorithm> +#include <boost/tokenizer.hpp> + #include "pbd/debug.h" #include "i18n.h" @@ -47,6 +49,7 @@ uint64_t PBD::DEBUG::FileManager = PBD::new_debug_bit ("filemanager"); uint64_t PBD::DEBUG::Pool = PBD::new_debug_bit ("pool"); uint64_t PBD::DEBUG::EventLoop = PBD::new_debug_bit ("eventloop"); uint64_t PBD::DEBUG::AbstractUI = PBD::new_debug_bit ("abstractui"); +uint64_t PBD::DEBUG::FileUtils = PBD::new_debug_bit ("fileutils"); uint64_t PBD::debug_bits = 0x0; @@ -75,36 +78,31 @@ PBD::set_debug_bits (uint64_t bits) int PBD::parse_debug_options (const char* str) { - char* p; - char* sp; + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep (","); + tokenizer tokens (string(str), sep); uint64_t bits = 0; - char* copy = strdup (str); - - p = strtok_r (copy, ",", &sp); - while (p) { - if (strcasecmp (p, "list") == 0) { + for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) { + if (*tok_iter == "list") { list_debug_options (); - free (copy); return 1; } - if (strcasecmp (p, "all") == 0) { + if (*tok_iter == "all") { PBD::set_debug_bits (~0ULL); - free (copy); return 0; } for (map<const char*,uint64_t>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) { - if (strncasecmp (p, i->first, strlen (p)) == 0) { + const char* cstr = (*tok_iter).c_str(); + + if (strncasecmp (cstr, i->first, strlen (cstr)) == 0) { bits |= i->second; } } - - p = strtok_r (0, ",", &sp); } - free (copy); PBD::set_debug_bits (bits); return 0; } diff --git a/libs/pbd/debug_rt_alloc.c b/libs/pbd/debug_rt_alloc.c index 81e640b66d..7e578a2367 100644 --- a/libs/pbd/debug_rt_alloc.c +++ b/libs/pbd/debug_rt_alloc.c @@ -22,9 +22,10 @@ #define _GNU_SOURCE #include <dlfcn.h> #include <stdio.h> -#include <pthread.h> #include <stdlib.h> +#include "pbd/pthread_utils.h" + int (*pbd_alloc_allowed) () = 0; /** Thread-local key whose value is set to 1 if malloc checking is disabled diff --git a/libs/pbd/epa.cc b/libs/pbd/epa.cc index 8b8a23491b..1a27a436a6 100644 --- a/libs/pbd/epa.cc +++ b/libs/pbd/epa.cc @@ -17,12 +17,19 @@ */ +#include <glib.h> + #include <cstdlib> #include "pbd/epa.h" #include "pbd/strsplit.h" +#ifdef COMPILER_MSVC +#define environ _environ +_CRTIMP extern char ** _environ; +#else extern char** environ; +#endif using namespace PBD; using namespace std; @@ -61,7 +68,7 @@ EnvironmentalProtectionAgency::save () /* fetch environment from named environment variable, rather than "environ" */ - const char* estr = getenv (_envname.c_str()); + const char* estr = g_getenv (_envname.c_str()); if (!estr) { return; @@ -117,7 +124,7 @@ EnvironmentalProtectionAgency::restore () const clear (); for (map<string,string>::const_iterator i = e.begin(); i != e.end(); ++i) { - setenv (i->first.c_str(), i->second.c_str(), 1); + g_setenv (i->first.c_str(), i->second.c_str(), 1); } } @@ -137,6 +144,6 @@ EnvironmentalProtectionAgency::clear () const } string before = estring.substr (0, equal); - unsetenv(before.c_str()); + g_unsetenv(before.c_str()); } } diff --git a/libs/pbd/fallback_folders.cc b/libs/pbd/fallback_folders.cc new file mode 100644 index 0000000000..deecd60d7a --- /dev/null +++ b/libs/pbd/fallback_folders.cc @@ -0,0 +1,591 @@ +/* + Copyright (C) 2008 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. + +*/ + +#include <pbd/fallback_folders.h> +#include <glib.h> +#include <glibmm.h> +#include <string.h> + + + +#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!! +#include <shlobj.h> +#include <winreg.h> + +//*************************************************************** +// +// get_win_special_folder() +// +// Gets the full path name that corresponds of one of the Windows +// special folders, such as "My Documents" and the like. The input +// parameter must be one of the corresponding CSIDL values, such +// as CSIDL_SYSTEM etc. +// +// Returns: +// +// On Success: A pointer to a newly allocated string containing +// the name of the special folder (must later be freed). +// On Failure: NULL +// +gchar * +get_win_special_folder (int csidl) +{ +wchar_t path[PATH_MAX+1]; +HRESULT hr; +LPITEMIDLIST pidl = 0; +gchar *retval = 0; + + if (S_OK == (hr = SHGetSpecialFolderLocation (0, csidl, &pidl))) + { + if (SHGetPathFromIDListW (pidl, path)) + retval = g_utf16_to_utf8 ((const gunichar2*)path, -1, 0, 0, 0); + CoTaskMemFree (pidl); + } + + return retval; +} +#endif // PLATFORM_WINDOWS + +namespace PBD { + +static gchar **fallback_folders = 0; + +//*************************************************************** +// +// get_platform_fallback_folders() +// +// Returns an array of folders to fall back to if the folders +// weren't named at build time and subsequently couldn't be found +// in the user's environment. This might not be needed any more +// because the function 'fixup_bundle_environment()' (in the +// gtk2_ardour branch) now explicitly sets up any environment +// paths that the program will need at run time. However, having +// the folders here might help us to simplify the above function +// which would be useful (currently, there are different versions +// of 'fixup_bundle_environment()' for each supported platform). +// Twelve fallback folders are currently catered for, corresponding to:- +// +// LOCALEDIR +// GTK_DIR +// CONFIG_DIR +// ARDOUR_DIR +// MODULE_DIR +// DATA_DIR +// ICONS_DIR +// PIXMAPS_DIR +// CONTROL_SURFACES_DIR +// VAMP_DIR +// LADSPA_PATH - note that there's only one entry in the path +// VST_PATH - note that there may only be one entry in the path +// +// Returns: +// +// On Success: A pointer to an array containing the above dirs. +// On Failure: NULL +// +#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!! + +static gchar** +get_platform_fallback_folders () +{ +gchar **fallback_dir_vector = 0; +const gchar *pUsrHome = 0; // Do not free !! + + if (!fallback_folders) + { + GArray *pFallbackDirs; + gchar *pAppData = 0; + gchar *pMyAppData = 0; + gchar *pExeRoot = 0; + gchar *pPersonal = 0; + + pFallbackDirs = g_array_new (TRUE, TRUE, sizeof (char *)); + + if (pFallbackDirs) + { + /* Get the path for the user's personal folder */ + gchar *pPersonalTemp = get_win_special_folder (CSIDL_PERSONAL); + + /* and the path for the user's personal application data */ + gchar *pMyAppDataTemp = get_win_special_folder (CSIDL_LOCAL_APPDATA); + + /* and the path for common application data ("Documents and Settings\All Users\Application Data") */ + gchar *pAppDataTemp = get_win_special_folder (CSIDL_COMMON_APPDATA); + + if (0 == pAppDataTemp) + pAppData = g_build_filename("C:\\", "Documents and Settings", "All Users", "Application Data", PROGRAM_NAME, "local", 0); + else + { + pAppData = g_build_filename(pAppDataTemp, PROGRAM_NAME, "local", 0); + g_free (pAppDataTemp); + } + + if (0 == pMyAppDataTemp) + { + pMyAppData = g_build_filename(g_get_home_dir(), "Application Data", "local", 0); + } + else + { + pMyAppData = g_build_filename(pMyAppDataTemp, 0); + g_free (pMyAppDataTemp); + } + + if (0 == pPersonalTemp) + pPersonal = g_build_filename(g_get_home_dir(), 0); + else + { + pPersonal = g_build_filename(pPersonalTemp, 0); + g_free (pPersonalTemp); + } + + /* Get the path to the running application */ + pExeRoot = g_win32_get_package_installation_directory_of_module (0); + + if (0 == pExeRoot) + { + pExeRoot = g_build_filename("C:\\", "Program Files", PROGRAM_NAME, 0); + } + + if ((pExeRoot) && (pAppData) && (pMyAppData) && (pPersonal)) + { + gchar tmp[PATH_MAX+1]; + gchar* p; + + // Build our LOCALEDIR entry + if (0 != (p = g_build_filename(pAppData, "share", "locale", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our GTK_DIR entry + if (0 != (p = g_build_filename(pPersonal, ".gtk-2.0", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONFIG_DIR entry + if (0 != (p = g_build_filename(pAppData, "etc", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ARDOUR_DIR entry + p = g_build_filename(pMyAppData, PROGRAM_NAME, 0); + + if (0 != p) + { + g_array_append_val (pFallbackDirs, p); + + // Build our MODULE_DIR entry + strcpy(tmp, pExeRoot); + if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR))) + { + *p = '\0'; + + if (0 != (p = g_build_filename(tmp, 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our DATA_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ICONS_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", "icons", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our PIXMAPS_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", "pixmaps", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONTROL_SURFACES_DIR entry + if (0 != (p = g_build_filename(pExeRoot, "bin", "surfaces", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our VAMP_DIR entry + p = g_build_filename(pExeRoot, "bin", "vamp", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + + // Next, build our LADSPA_PATH entry + p = g_build_filename(pExeRoot, "bin", "plugins", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + + // And finally, build our VST_PATH entry + DWORD dwType = REG_SZ; HKEY hKey; + DWORD dwSize = PATH_MAX; p = 0; + if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_CURRENT_USER, "Software\\VST", 0, KEY_READ, &hKey)) + { + // Look for the user's VST Registry entry + if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize)) + p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), 0); + + RegCloseKey (hKey); + } + + if (p == 0) + if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Software\\VST", 0, KEY_READ, &hKey)) + { + // Look for a global VST Registry entry + if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize)) + p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), 0); + + RegCloseKey (hKey); + } + + if (p == 0) + { + gchar *pVSTx86 = 0; + gchar *pProgFilesX86 = get_win_special_folder (CSIDL_PROGRAM_FILESX86); + + if (pProgFilesX86) + { + // Look for a VST folder under C:\Program Files (x86) + if (pVSTx86 = g_build_filename (pProgFilesX86, "Steinberg", "VSTPlugins", 0)) + { + if (Glib::file_test (pVSTx86, Glib::FILE_TEST_EXISTS)) + if (Glib::file_test (pVSTx86, Glib::FILE_TEST_IS_DIR)) + p = g_build_filename (pVSTx86, 0); + + g_free (pVSTx86); + } + + g_free (pProgFilesX86); + } + + if (p == 0) + { + // Look for a VST folder under C:\Program Files + gchar *pVST = 0; + gchar *pProgFiles = get_win_special_folder (CSIDL_PROGRAM_FILES); + + if (pProgFiles) + { + if (pVST = g_build_filename (pProgFiles, "Steinberg", "VSTPlugins", 0)) + { + if (Glib::file_test (pVST, Glib::FILE_TEST_EXISTS)) + if (Glib::file_test (pVST, Glib::FILE_TEST_IS_DIR)) + p = g_build_filename (pVST, 0); + + g_free (pVST); + } + + g_free (pProgFiles); + } + } + } + + if (p == 0) + { + // If all else failed, assume the plugins are under "My Documents" + pUsrHome = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + if (pUsrHome) + p = g_build_filename (pUsrHome, "Plugins", "VST", 0); + else + { + pUsrHome = g_build_filename(g_get_home_dir(), "My Documents", 0); + if (pUsrHome) + p = g_build_filename (pUsrHome, "Plugins", "VST", 0); + } + } + else + { + gchar* q = 0; + + // Concatenate the registry path with the user's personal path + pUsrHome = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + + if (pUsrHome) + { + q = p; + p = g_build_path (";", q, g_build_filename(pUsrHome, "Plugins", "VST", 0), 0); + } + else + { + pUsrHome = g_build_filename(g_get_home_dir(), "My Documents", 0); + if (pUsrHome) + { + q = p; + p = g_build_path (";", q, g_build_filename (pUsrHome, "Plugins", "VST", 0), 0); + } + } + } + + if (p) //VST + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + + // BUNDLED_LV2 + p = g_build_filename(pExeRoot, "bin", "lv2", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + } + } + } + } + } + } + } + } + } + } + + g_free (pAppData); + g_free (pMyAppData); + g_free (pExeRoot); + g_free (pPersonal); + } + + fallback_dir_vector = fallback_folders = (gchar **) g_array_free (pFallbackDirs, FALSE); + } + } + else + fallback_dir_vector = fallback_folders; + + return (fallback_dir_vector); +} + +#else +// Assume Linux, Cygwin or OS-X. Note that in all 3 cases we only +// need to cater for unbundled releases (those built by a user from +// source). Bundled releases of Ardour and Mixbus now specifically +// write their folders and paths to the user's environment at startup. +// See the function 'fixup_bundle_environment()'. + +static gchar** +get_platform_fallback_folders () +{ +gchar **fallback_dir_vector = 0; +gchar *pUsrHome = 0; + + if (!fallback_folders) + { + GArray *pFallbackDirs; + gchar *pAppData = 0; + gchar *pExeRoot = 0; + gchar *pPersonal = 0; + + pFallbackDirs = g_array_new (TRUE, TRUE, sizeof (char *)); + + if (pFallbackDirs) + { + pAppData = g_build_filename("/usr", "local", 0); + pExeRoot = g_build_filename("/usr", "local", "lib", "ardour2", 0); + pPersonal = g_build_filename(g_get_home_dir(), 0); + + if ((pExeRoot) && (pAppData) && (pPersonal)) + { + gchar tmp[PATH_MAX+1]; + gchar* p; + + // Build our LOCALEDIR entry + if (0 != (p = g_build_filename(pAppData, "share", "locale", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our GTK_DIR entry + if (0 != (p = g_build_filename(pPersonal, ".gtk-2.0", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONFIG_DIR entry + if (0 != (p = g_build_filename(pAppData, "etc", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ARDOUR_DIR entry + p = ""; // Empty string (temporary) + if (0 != p) + { + g_array_append_val (pFallbackDirs, p); + + // Build our MODULE_DIR entry + strcpy(tmp, pExeRoot); + if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR))) + { + *p = '\0'; + + if (0 != (p = g_build_filename(tmp, 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our DATA_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ICONS_DIR entry (re-use 'tmp') + strcpy(tmp, "/usr/local/share/ardour2"); + if (0 != (p = g_build_filename(tmp, "icons", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our PIXMAPS_DIR entry + if (0 != (p = g_build_filename(tmp, "pixmaps", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONTROL_SURFACES_DIR entry + if (0 != (p = g_build_filename(pExeRoot, "surfaces", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our VAMP_DIR entry + p = g_build_filename(pExeRoot, "vamp", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + + // Next, build our LADSPA_PATH entry + p = g_build_filename(Glib::path_get_dirname(pExeRoot).c_str(), "plugins", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + + // And finally, build our VST_PATH entry + if (g_getenv("HOME")) + p = g_build_filename(g_getenv("HOME"), "VST", "plugins", 0); + else + p = g_build_filename(g_get_home_dir(), "VST", "plugins", 0); + + if (p) + g_array_append_val (pFallbackDirs, p); + } + } + } + } + } + } + } + } + } + } + + g_free (pAppData); + g_free (pExeRoot); + g_free (pPersonal); + } + + fallback_dir_vector = fallback_folders = (gchar **) g_array_free (pFallbackDirs, FALSE); + } + } + else + fallback_dir_vector = fallback_folders; + + if (pUsrHome) + g_free (pUsrHome); + + return (fallback_dir_vector); +} +#endif + + +//*************************************************************** +// +// get_platform_fallback_folder() +// +// Returns a const gchar* which points to a string describing +// the full path to the Ardour fallback folder corresponding to +// the supplied index. See 'get_platform_fallback_folders()' for a +// complete list of the supported index enumerations. Calling this +// function will initialize the fallback folder array if it wasn't +// already initiaized. The array should then (eventually) be freed +// using 'free_platform_fallback_folders()'. +// +// Returns: +// +// On Success: A pointer to the path string contained at the +// relevant index. +// On Failure: NULL +// +PBD_API G_CONST_RETURN gchar* PBD_APICALLTYPE +get_platform_fallback_folder (PBD::fallback_folder_t index) +{ + if ((index >= 0) && (index < FALLBACK_FOLDER_MAX)) + return ((G_CONST_RETURN gchar *)get_platform_fallback_folders ()[index]); + else + return (G_CONST_RETURN gchar *) 0; +} + + +//*************************************************************** +// +// alloc_platform_fallback_folders() +// +// Calls 'get_platform_fallback_folders()' to ensure that memory +// for the fallback folder array is already allocated before the +// array gets used. It doesn't cause any problems if the array gets +// used prior to calling this function (since the memory will get +// allocated anyway, on fist usage). Either way however, the momory +// must later be freed using 'free_platform_fallback_folders()'. +// +// Returns: +// +// The value obtained from 'get_platform_fallback_folders()' +// +PBD_API G_CONST_RETURN gchar* G_CONST_RETURN * PBD_APICALLTYPE +alloc_platform_fallback_folders () +{ + return ((G_CONST_RETURN gchar* G_CONST_RETURN *)get_platform_fallback_folders ()); +} + + +//*************************************************************** +// +// free_platform_fallback_folders() +// +// Frees the memory that was previously allocated for the Ardour +// fallback folder array. +// +// Returns: +// +// NONE. +// +PBD_API void PBD_APICALLTYPE +free_platform_fallback_folders () +{ +int index = FOLDER_LOCALE; + + if (fallback_folders) + { + gchar *p = get_platform_fallback_folders()[(fallback_folder_t)index++]; + + while (index < (FALLBACK_FOLDER_MAX+1)) { + if (p) + g_free (p); + + if (index < FALLBACK_FOLDER_MAX) + p = get_platform_fallback_folders()[(fallback_folder_t)index++]; + else + break; + } + + fallback_folders = 0; + } +} + +} // namespace PBD + diff --git a/libs/pbd/ffs.cc b/libs/pbd/ffs.cc new file mode 100644 index 0000000000..557504f14e --- /dev/null +++ b/libs/pbd/ffs.cc @@ -0,0 +1,49 @@ +/* + Copyright (C) 2013 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 "pbd/ffs.h" + +#ifndef COMPILER_MSVC +#include <strings.h> +#endif + +namespace PBD { +int +ffs (int x) +{ +#if defined (COMPILER_MINGW) + return __builtin_ffs(x); +#elif defined (COMPILER_MSVC) + unsigned long index; +#ifdef WIN64 + if (0 != _BitScanForward64(&index, (__int64)x)) +#else + if (0 != _BitScanForward(&index, (unsigned long)x)) +#endif + index++; // Make the result 1-based + else + index = 0; // All bits were zero + + return (int)index; +#else + return ::ffs(x); +#endif +} + +} diff --git a/libs/pbd/file_manager.cc b/libs/pbd/file_manager.cc index a71ffca190..2cfa63ae39 100644 --- a/libs/pbd/file_manager.cc +++ b/libs/pbd/file_manager.cc @@ -18,19 +18,22 @@ */ #include <sys/time.h> -#include <sys/resource.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <cassert> #include <cstdio> +#include <glib.h> +#include <glib/gstdio.h> + #ifdef __APPLE__ #include <mach/mach_time.h> #endif #include "pbd/compose.h" #include "pbd/file_manager.h" +#include "pbd/resource.h" #include "pbd/debug.h" using namespace std; @@ -41,12 +44,11 @@ FileManager* FileDescriptor::_manager; FileManager::FileManager () : _open (0) { - struct rlimit rl; - int const r = getrlimit (RLIMIT_NOFILE, &rl); + struct ResourceLimit rl; /* XXX: this is a bit arbitrary */ - if (r == 0) { - _max_open = rl.rlim_cur - 64; + if (get_resource_limit (OpenFiles, rl)) { + _max_open = rl.current_limit - 64; } else { _max_open = 256; } @@ -116,10 +118,14 @@ FileManager::allocate (FileDescriptor* d) #ifdef __APPLE__ d->_last_used = mach_absolute_time(); -#else +#elif defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec t; clock_gettime (CLOCK_MONOTONIC, &t); d->_last_used = t.tv_sec + (double) t.tv_nsec / 10e9; +#else + struct timeval now; + gettimeofday (&now, NULL); + d->_last_used = now.tv_sec + (double) now.tv_usec / 10e6; #endif d->_refcount++; @@ -222,8 +228,19 @@ bool FdFileDescriptor::open () { /* we must have a lock on the FileManager's mutex */ - - _fd = ::open (_path.c_str(), _writeable ? (O_RDWR | O_CREAT) : O_RDONLY, _mode); + + /* files must be opened with O_BINARY flag on windows + * or it treats the file as a text stream and puts in + * line endings in etc + */ +#ifdef WIN32 +#define WRITE_FLAGS O_RDWR | O_CREAT | O_BINARY +#define READ_FLAGS O_RDONLY | O_BINARY +#else +#define WRITE_FLAGS O_RDWR | O_CREAT +#define READ_FLAGS O_RDONLY +#endif + _fd = ::g_open (_path.c_str(), _writeable ? WRITE_FLAGS : READ_FLAGS, _mode); return (_fd == -1); } diff --git a/libs/pbd/file_utils.cc b/libs/pbd/file_utils.cc index bb290fa6aa..50287149e1 100644 --- a/libs/pbd/file_utils.cc +++ b/libs/pbd/file_utils.cc @@ -23,6 +23,10 @@ #include <glib.h> #include <glib/gstdio.h> +#ifdef COMPILER_MINGW +#include <io.h> // For W_OK +#endif + #include <glibmm/fileutils.h> #include <glibmm/miscutils.h> #include <glibmm/pattern.h> @@ -31,6 +35,7 @@ #include "pbd/compose.h" #include "pbd/file_utils.h" +#include "pbd/debug.h" #include "pbd/error.h" #include "pbd/pathscanner.h" #include "pbd/stl_delete.h" @@ -76,6 +81,11 @@ find_matching_files_in_directory (const std::string& directory, std::string full_path(directory); full_path = Glib::build_filename (full_path, *file_iter); + DEBUG_TRACE ( + DEBUG::FileUtils, + string_compose("Found file %1\n", full_path) + ); + result.push_back(full_path); } } @@ -113,24 +123,28 @@ find_file_in_search_path(const SearchPath& search_path, if (tmp.size() == 0) { + DEBUG_TRACE ( + DEBUG::FileUtils, + string_compose("No file matching %1 found in Path: %2\n", filename, search_path.to_string()) + ); return false; } -#if 0 if (tmp.size() != 1) { - info << string_compose - ( - "Found more than one file matching %1 in search path %2", - filename, - search_path () - ) - << endmsg; + DEBUG_TRACE ( + DEBUG::FileUtils, + string_compose("Found more that one file matching %1 in Path: %2\n", filename, search_path.to_string()) + ); } -#endif result = tmp.front(); + DEBUG_TRACE ( + DEBUG::FileUtils, + string_compose("Found file %1 in Path: %2\n", filename, search_path.to_string()) + ); + return true; } @@ -188,9 +202,9 @@ get_absolute_path (const std::string & p) bool equivalent_paths (const std::string& a, const std::string& b) { - struct stat bA; + GStatBuf bA; int const rA = g_stat (a.c_str(), &bA); - struct stat bB; + GStatBuf bB; int const rB = g_stat (b.c_str(), &bB); return (rA == 0 && rB == 0 && bA.st_dev == bB.st_dev && bA.st_ino == bB.st_ino); @@ -221,7 +235,7 @@ exists_and_writable (const std::string & p) make us unwritable. */ - struct stat statbuf; + GStatBuf statbuf; if (g_stat (p.c_str(), &statbuf) != 0) { /* doesn't exist - not writable */ diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc index 40f8cca9d6..5d81cd2fd3 100644 --- a/libs/pbd/fpu.cc +++ b/libs/pbd/fpu.cc @@ -16,7 +16,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#ifndef COMPILER_MSVC #include "libpbd-config.h" #define _XOPEN_SOURCE 600 @@ -141,3 +141,7 @@ FPU::FPU () FPU::~FPU () { } + +#else // COMPILER_MSVC + const char* pbd_fpu = "pbd/msvc/fpu.cc takes precedence over this file"; +#endif // COMPILER_MSVC diff --git a/libs/pbd/glib_semaphore.cc b/libs/pbd/glib_semaphore.cc new file mode 100644 index 0000000000..7565e0c069 --- /dev/null +++ b/libs/pbd/glib_semaphore.cc @@ -0,0 +1,68 @@ +/* + Copyright (C) 2010 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 "pbd/glib_semaphore.h" + +namespace PBD { + +GlibSemaphore::GlibSemaphore (gint initial_val) + : + m_counter(initial_val) +{ } + +void +GlibSemaphore::wait () +{ + Glib::Threads::Mutex::Lock guard (m_mutex); + + while (m_counter.get() < 1) { + m_cond.wait(m_mutex); + } + + // this shouldn't need to be inside the lock + --m_counter; +} + +bool +GlibSemaphore::try_wait () +{ + if (!m_mutex.trylock()) + { + return false; + } + // lock successful + while (m_counter.get() < 1) { + m_cond.wait(m_mutex); + } + + // the order of these should not matter + --m_counter; + m_mutex.unlock(); + return true; +} + +void +GlibSemaphore::post () +{ + // atomic, no locking required + ++m_counter; + m_cond.signal(); +} + +} // namespace PBD diff --git a/libs/pbd/localeguard.cc b/libs/pbd/localeguard.cc new file mode 100644 index 0000000000..12093beeaa --- /dev/null +++ b/libs/pbd/localeguard.cc @@ -0,0 +1,34 @@ +#include <cstring> +#include <locale.h> +#include <stdlib.h> + +#include "pbd/localeguard.h" + +// JE - added temporarily, to reduce the delay effects when calling +// setlocale() recursively in a Windows GUI thread (we should think +// about moving the caller(s) into a dedicated worker thread). +std::string PBD::LocaleGuard::current; + +PBD::LocaleGuard::LocaleGuard (const char* str) + : old(0) +{ + if (current != str) { + old = strdup (setlocale (LC_NUMERIC, NULL)); + if (strcmp (old, str)) { + if (setlocale (LC_NUMERIC, str)) + current = str; + } + } +} + +PBD::LocaleGuard::~LocaleGuard () +{ + if (old) { + if (setlocale (LC_NUMERIC, old)) + current = old; + + free ((char*)old); + } +} + + diff --git a/libs/pbd/localtime_r.cc b/libs/pbd/localtime_r.cc new file mode 100644 index 0000000000..c72e3eb458 --- /dev/null +++ b/libs/pbd/localtime_r.cc @@ -0,0 +1,41 @@ +#ifdef WAF_BUILD +#include "libpbd-config.h" +#endif + +#ifndef HAVE_LOCALTIME_R +#include <time.h> +#include <string.h> + +#include "pbd/pthread_utils.h" +#include "pbd/localtime_r.h" + +#ifdef localtime_r +#undef localtime_r +#endif + +struct tm * +localtime_r(const time_t *const timep, struct tm *p_tm) +{ + static pthread_mutex_t time_mutex; + static int time_mutex_inited = 0; + struct tm *tmp; + + if (!time_mutex_inited) + { + time_mutex_inited = 1; + pthread_mutex_init(&time_mutex, NULL); + } + + pthread_mutex_lock(&time_mutex); + tmp = localtime(timep); + if (tmp) + { + memcpy(p_tm, tmp, sizeof(struct tm)); + tmp = p_tm; + } + pthread_mutex_unlock(&time_mutex); + + return tmp; +} + +#endif diff --git a/libs/pbd/mountpoint.cc b/libs/pbd/mountpoint.cc index 46cea42e0a..65f011c745 100644 --- a/libs/pbd/mountpoint.cc +++ b/libs/pbd/mountpoint.cc @@ -17,7 +17,7 @@ $Id$ */ - +#ifndef COMPILER_MSVC #include <cstdio> #include <cstring> #include <string> @@ -94,6 +94,14 @@ mountpoint (string path) return best; } +#elif defined(PLATFORM_WINDOWS) + +string +mountpoint (string path) +{ + // TODO ... if needed +} + #else // !HAVE_GETMNTENT #include <sys/param.h> @@ -164,3 +172,7 @@ main (int argc, char *argv[]) } #endif // TEST_MOUNTPOINT + +#else // COMPILER_MSVC + const char* pbd_mountpoint = "pbd/msvc/mountpoint.cc takes precedence over this file"; +#endif // COMPILER_MSVC diff --git a/libs/pbd/msvc/fpu.cc b/libs/pbd/msvc/fpu.cc new file mode 100644 index 0000000000..6997405928 --- /dev/null +++ b/libs/pbd/msvc/fpu.cc @@ -0,0 +1,124 @@ +#ifdef COMPILER_MSVC // Added by JE - 05-12-2009. Inline assembler instructions + // have been changed to Intel format and (in the case of + // cpuid) was replaced by the equivalent VC++ system call). +#define _XOPEN_SOURCE 600 +#include <cstdlib> +#include <stdint.h> +#include <intrin.h> // Added by JE - 05-12-2009 + +#include <pbd/fpu.h> +#include <pbd/error.h> + +#include "i18n.h" + +using namespace PBD; +using namespace std; + +FPU::FPU () +{ + unsigned long cpuflags = 0; + + _flags = (Flags)0; + +#ifndef ARCH_X86 + return; + +#else + +#ifndef USE_X86_64_ASM +int cpuInfo[4]; + + __cpuid (cpuInfo, 1); + cpuflags = cpuInfo[3]; +/* + __asm { // This is how the original section would look if converted to Intel syntax. + // However, I have grave doubts about whether it's doing the right thing. + // It seems as if the intention was to retrieve feature information from + // the processor. However, feature information is returned in the ebx register + // (if you believe Wikipedia) or in edx (if you believe Microsoft). Unfortunately, + // both registers get ignored in the original code!! Confused?? Join the club!! + mov eax, 1 + push ebx + cpuid + mov edx, 0 + pop ebx + mov cpuflags, ecx // This can't be right, surely??? + }; */ +#else +// Note that this syntax is currently still in AT&T format ! + asm volatile ( + "pushq %%rbx\n" + "movq $1, %%rax\n" + "cpuid\n" + "movq %%rdx, %0\n" + "popq %%rbx\n" + : "=r" (cpuflags) + : + : "%rax", "%rcx", "%rdx", "memory" + ); + +#endif /* USE_X86_64_ASM */ + + if (cpuflags & (1<<25)) { + _flags = Flags (_flags | (HasSSE|HasFlushToZero)); + } + + if (cpuflags & (1<<26)) { + _flags = Flags (_flags | HasSSE2); + } + + if (cpuflags & (1 << 24)) { + bool aligned_malloc = false; // Added by JE - 05-12-2009 + char* fxbuf = 0; +// This section changed by JE - 05-12-2009 +#ifdef NO_POSIX_MEMALIGN +#if defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // All of these support '_aligned_malloc()' + fxbuf = (char *) _aligned_malloc(512, 16); // (note that they all need at least MSVC runtime 7.0) + aligned_malloc = true; +#else + fxbuf = (char *) malloc(512); +#endif +#else + fxbuf = posix_memalign ((void**)&fxbuf, 16, 512); +#endif + // Verify that fxbuf is correctly aligned + unsigned long buf_addr = (unsigned long)(void*)fxbuf; + if ((0 == buf_addr) || (buf_addr % 16)) + error << _("cannot allocate 16 byte aligned buffer for h/w feature detection") << endmsg; + else + { + memset(fxbuf, 0, 512); // Initialize the buffer !!! Added by JE - 12-12-2009 + + __asm { + mov eax, fxbuf + fxsave [eax] + }; + + uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]); + + /* if the mask is zero, set its default value (from intel specs) */ + + if (mxcsr_mask == 0) { + mxcsr_mask = 0xffbf; + } + + if (mxcsr_mask & (1<<6)) { + _flags = Flags (_flags | HasDenormalsAreZero); + } + + if (aligned_malloc) + _aligned_free (fxbuf); + else + free (fxbuf); + } + } +#endif // ARCH_X86 +} + +FPU::~FPU () +{ +} + +#else // !COMPILER_MSVC + const char* pbd_fpu = "original pbd/fpu.cc takes precedence over this file"; +#endif // COMPILER_MSVC diff --git a/libs/pbd/msvc/getopt.c b/libs/pbd/msvc/getopt.c new file mode 100644 index 0000000000..2f539a59cf --- /dev/null +++ b/libs/pbd/msvc/getopt.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef COMPILER_MSVC +#include "pbd/msvc_pbd.h" +#endif +#include "getopt.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +__BEGIN_DECLS // Added by JE - 31-01-2010 +// All 'GETOPT_API' declarations added by JE - 31-01-2010 +GETOPT_API int opterr = 1; /* if error message should be printed */ +GETOPT_API int optind = 1; /* index into parent argv vector */ +GETOPT_API int optopt; /* character checked for validity */ +GETOPT_API int optreset; /* reset getopt */ +GETOPT_API char *optarg; /* argument associated with option */ + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +getopt(int nargc, // Argument list ratified by JE - 03-01-2010 + char * const *nargv, + const char *ostr) +{ + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' || + !(oli = (char*)strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (optopt == (int)'-') + return (-1); + if (!*place) + ++optind; + if (opterr && *ostr != ':' && optopt != BADCH) + (void)fprintf(stderr, "%s: illegal option -- %c\n", + "progname", optopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } + else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + "progname", optopt); + return (BADCH); + } + else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return (optopt); /* dump back option letter */ +} +__END_DECLS // Added by JE - 31-01-2010 diff --git a/libs/pbd/msvc/getopt.h b/libs/pbd/msvc/getopt.h new file mode 100644 index 0000000000..233a0eefa6 --- /dev/null +++ b/libs/pbd/msvc/getopt.h @@ -0,0 +1,110 @@ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ +/* $FreeBSD: src/include/getopt.h,v 1.1 2002/09/29 04:14:30 eric Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +#ifdef PLATFORM_WINDOWS +/* from <sys/cdefs.h> */ +# ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +# else +# define __BEGIN_DECLS +# define __END_DECLS +# endif +# define __P(args) args +#endif + +/*#ifndef PLATFORM_WINDOWS +#include <sys/cdefs.h> +#include <unistd.h> +#endif*/ + +#ifdef PLATFORM_WINDOWS +# if !defined(GETOPT_API) +# define GETOPT_API __declspec(dllimport) +# endif +#endif + +/* + * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions + */ +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +__BEGIN_DECLS +GETOPT_API int getopt_long __P((int, char * const *, const char *, + const struct option *, int *)); +__END_DECLS +#endif + +#ifdef PLATFORM_WINDOWS +/* These are global getopt variables */ +__BEGIN_DECLS + +GETOPT_API extern int opterr, /* if error message should be printed */ + optind, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +GETOPT_API extern char* optarg; /* argument associated with option */ + +/* Original getopt */ +GETOPT_API int getopt __P((int, char * const *, const char *)); + +__END_DECLS +#endif + +#endif /* !_GETOPT_H_ */ diff --git a/libs/pbd/msvc/getopt_long.c b/libs/pbd/msvc/getopt_long.c new file mode 100644 index 0000000000..06c459ab84 --- /dev/null +++ b/libs/pbd/msvc/getopt_long.c @@ -0,0 +1,546 @@ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ +/* $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.2 2002/10/16 22:18:42 alfred Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <stdlib.h> +#include <string.h> + +#ifdef PLATFORM_WINDOWS +#ifdef COMPILER_MSVC +#include "pbd/msvc_pbd.h" // Defines 'GETOPT_API' +#endif +/* Windows needs warnx(). We change the definition though: + * 1. (another) global is defined, opterrmsg, which holds the error message + * 2. errors are always printed out on stderr w/o the program name + * Note that opterrmsg always gets set no matter what opterr is set to. The + * error message will not be printed if opterr is 0 as usual. + */ + +#include "getopt.h" +#include <stdio.h> +#include <stdarg.h> + +GETOPT_API extern char opterrmsg[128]; +char opterrmsg[128]; /* last error message is stored here */ + +static void warnx(int print_error, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) + _vsnprintf(opterrmsg, 128, fmt, ap); + else + opterrmsg[0]='\0'; + va_end(ap); + if (print_error) { + fprintf(stderr, opterrmsg); + fprintf(stderr, "\n"); + } +} + +#endif /*PLATFORM_WINDOWS*/ + +/* not part of the original file */ +#ifndef _DIAGASSERT +#define _DIAGASSERT(X) +#endif + +#if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND +#define REPLACE_GETOPT +#endif + +#ifdef REPLACE_GETOPT +#ifdef __weak_alias +__weak_alias(getopt,_getopt) +#endif +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET +static int optreset; +#endif + +#ifdef __weak_alias +__weak_alias(getopt_long,_getopt_long) +#endif + +#if !HAVE_GETOPT_LONG +#define IGNORE_FIRST (*options == '-' || *options == '+') +#define PRINT_ERROR ((opterr) && ((*options != ':') \ + || (IGNORE_FIRST && options[1] != ':'))) +#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) +#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) +/* XXX: GNU ignores PC if *options == '-' */ +#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((IGNORE_FIRST && options[1] == ':') \ + || (*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static int getopt_internal(int, char * const *, const char *); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return b; +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, + int panonopt_end, + int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + _DIAGASSERT(nargv != NULL); + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + * Returns -2 if -- is found (can be long option or end of options marker). + */ +static int +getopt_internal(int nargc, + char * const *nargv, + const char *options) +{ + char *oli; /* option letter list index */ + int optchar; + + _DIAGASSERT(nargv != NULL); + _DIAGASSERT(options != NULL); + + optarg = NULL; + + /* + * XXX Some programs (like rsyncd) expect to be able to + * XXX re-initialize optind to 0 and have getopt_long(3) + * XXX properly function again. Work around this braindamage. + */ + if (optind == 0) + optind = 1; + + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return -1; + } + if ((*(place = nargv[optind]) != '-') + || (place[1] == '\0')) { /* found non-option */ + place = EMSG; + if (IN_ORDER) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return INORDER; + } + if (!PERMUTE) { + /* + * if no permutation wanted, stop parsing + * at first non-option + */ + return -1; + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + if (place[1] && *++place == '-') { /* found "--" */ + place++; + return -2; + } + } + if ((optchar = (int)*place++) == (int)':' || + (oli = (char*)strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { + /* option letter unknown or ':' */ + if (!*place) + ++optind; +#ifndef PLATFORM_WINDOWS + if (PRINT_ERROR) + warnx(illoptchar, optchar); +#else + warnx(PRINT_ERROR, illoptchar, optchar); +#endif + optopt = optchar; + return BADCH; + } + if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ + /* XXX: what if no long options provided (called by getopt)? */ + if (*place) + return -2; + + if (++optind >= nargc) { /* no arg */ + place = EMSG; +#ifndef PLATFORM_WINDOWS + if (PRINT_ERROR) + warnx(recargchar, optchar); +#else + warnx(PRINT_ERROR, recargchar, optchar); +#endif + optopt = optchar; + return BADARG; + } else /* white space */ + place = nargv[optind]; + /* + * Handle -W arg the same as --arg (which causes getopt to + * stop parsing). + */ + return -2; + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + /* XXX: disable test for :: if PC? (GNU doesn't) */ + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; +#ifndef PLATFORM_WINDOWS + if (PRINT_ERROR) + warnx(recargchar, optchar); +#else + warnx(PRINT_ERROR, recargchar, optchar); +#endif + optopt = optchar; + return BADARG; + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return optchar; +} + +__BEGIN_DECLS // Added by JE - 31-01-2010 +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the real getopt] + */ +GETOPT_API int // 'GETOPT_API' declaration added by JE - 31-01-2010 +getopt(int nargc, + char * const *nargv, + const char *options) +{ + int retval; + + _DIAGASSERT(nargv != NULL); + _DIAGASSERT(options != NULL); + + if ((retval = getopt_internal(nargc, nargv, options)) == -2) { + ++optind; + /* + * We found an option (--), so if we skipped non-options, + * we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, + nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + retval = -1; + } + return retval; +} +#endif + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +GETOPT_API int // 'GETOPT_API' declaration added by JE - 31-01-2010 +getopt_long(int nargc, + char * const *nargv, + const char *options, + const struct option *long_options, + int *idx) +{ + int retval; + + _DIAGASSERT(nargv != NULL); + _DIAGASSERT(options != NULL); + _DIAGASSERT(long_options != NULL); + /* idx may be NULL */ + + if ((retval = getopt_internal(nargc, nargv, options)) == -2) { + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + place = EMSG; + + if (*current_argv == '\0') { /* found "--" */ + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return -1; + } + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == + (unsigned)current_argv_len) { + /* exact match */ + match = i; + break; + } + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ +#ifndef PLATFORM_WINDOWS + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); +#else + warnx(PRINT_ERROR, ambig, (int)current_argv_len, + current_argv); +#endif + optopt = 0; + return BADCH; + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { +#ifndef PLATFORM_WINDOWS + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); +#else + warnx(PRINT_ERROR, noarg, (int)current_argv_len, + current_argv); +#endif + /* + * XXX: GNU sets optopt to val regardless of + * flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return BADARG; + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use + * next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' + * indicates no error should be generated + */ +#ifndef PLATFORM_WINDOWS + if (PRINT_ERROR) + warnx(recargstring, current_argv); +#else + warnx(PRINT_ERROR, recargstring, current_argv); +#endif + /* + * XXX: GNU sets optopt to val regardless + * of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return BADARG; + } + } else { /* unknown option */ +#ifndef PLATFORM_WINDOWS + if (PRINT_ERROR) + warnx(illoptstring, current_argv); +#else + warnx(PRINT_ERROR, illoptstring, current_argv); +#endif + optopt = 0; + return BADCH; + } + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + retval = 0; + } else + retval = long_options[match].val; + if (idx) + *idx = match; + } + return retval; +} +__END_DECLS // Added by JE - 31-01-2010 + +#endif /* !GETOPT_LONG */ diff --git a/libs/pbd/msvc/mountpoint.cc b/libs/pbd/msvc/mountpoint.cc new file mode 100644 index 0000000000..d30b24462f --- /dev/null +++ b/libs/pbd/msvc/mountpoint.cc @@ -0,0 +1,166 @@ +/* + Copyright (C) 2002 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. + + $Id: mountpoint.cc 3920 2008-10-11 12:34:46Z paul $ +*/ + +#ifdef COMPILER_MSVC + +/* TODO - Still to be implemented */ + +#include <cstdio> +#include <cstring> +#include <string> +#include <cstring> +#include <limits.h> + +#include <pbd/mountpoint.h> + +using std::string; + +#if HAVE_GETMNTENT +#include <mntent.h> + +struct mntent_sorter { + bool operator() (const mntent *a, const mntent *b) { + return strcmp (a->mnt_dir, b->mnt_dir); + } +}; + +string +mountpoint (string path) +{ + FILE *mntf; + mntent *mnt; + unsigned int maxmatch = 0; + unsigned int matchlen; + const char *cpath = path.c_str(); + char best[PATH_MAX+1]; + + if ((mntf = setmntent ("/etc/mtab", "r")) == 0) { + return ""; + } + + best[0] = '\0'; + + while ((mnt = getmntent (mntf))) { + unsigned int n; + + n = 0; + matchlen = 0; + + /* note: strcmp's semantics are not + strict enough to use for this. + */ + + while (cpath[n] && mnt->mnt_dir[n]) { + if (cpath[n] != mnt->mnt_dir[n]) { + break; + } + matchlen++; + n++; + } + + if (cpath[matchlen] == '\0') { + + endmntent (mntf); + return mnt->mnt_dir; + + } else { + + if (matchlen > maxmatch) { + snprintf (best, sizeof(best), "%s", mnt->mnt_dir); + maxmatch = matchlen; + } + } + } + + endmntent (mntf); + + return best; +} + +#else // !HAVE_GETMNTENT + +string +mountpoint (string path) +{ +return ""; + +/* // The rest is commented out temporarily by JE - 30-11-2009 + // (I think this must be the implementation for MacOS). + struct statfs *mntbufp = 0; + int count; + unsigned int maxmatch = 0; + unsigned int matchlen; + const char *cpath = path.c_str(); + char best[PATH_MAX+1]; + + if ((count = getmntinfo(&mntbufp, MNT_NOWAIT)) == 0) { + free(mntbufp); + return "\0"; + } + + best[0] = '\0'; + + for (int i = 0; i < count; ++i) { + unsigned int n = 0; + matchlen = 0; + + // note: strcmp's semantics are not + // strict enough to use for this. + + while (cpath[n] && mntbufp[i].f_mntonname[n]) { + if (cpath[n] != mntbufp[i].f_mntonname[n]) { + break; + } + matchlen++; + n++; + } + + if (cpath[matchlen] == '\0') { + snprintf(best, sizeof(best), "%s", mntbufp[i].f_mntonname); + free(mntbufp); + return best; + + } else { + + if (matchlen > maxmatch) { + snprintf (best, sizeof(best), "%s", mntbufp[i].f_mntonname); + maxmatch = matchlen; + } + } + } + + return best; +*/ +} +#endif // HAVE_GETMNTENT + +#ifdef TEST_MOUNTPOINT + +main (int argc, char *argv[]) +{ + printf ("mp of %s = %s\n", argv[1], mountpoint (argv[1]).c_str()); + exit (0); +} + +#endif // TEST_MOUNTPOINT + +#else // !COMPILER_MSVC + const char* pbd_mountpoint = "original pbd/mountpoint.cc takes precedence over this file"; +#endif // COMPILER_MSVC diff --git a/libs/pbd/msvc/msvc_pbd.cc b/libs/pbd/msvc/msvc_pbd.cc new file mode 100644 index 0000000000..45137da0f3 --- /dev/null +++ b/libs/pbd/msvc/msvc_pbd.cc @@ -0,0 +1,895 @@ +/* + 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. + +*/ + +#ifdef COMPILER_MSVC + +#include <WTypes.h> + +extern "C" WINBASEAPI BOOL WINAPI +CreateHardLinkA( LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes ); // Needs kernel32.lib on anything higher than Win2K + +#include <algorithm> +#include <string> +#include <io.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <pbd/error.h> +#include <ardourext/misc.h> +#include <ardourext/pthread.h> // Should ensure that we include the right + // version - but we'll check anyway, later + +#include <glibmm.h> + +#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 + +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +PBD_API int PBD_APICALLTYPE +gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz) // Does this need to be exported ? +{ +FILETIME ft; +unsigned __int64 tmpres = 0; +static int tzflag = 0; + + if (NULL != tv) + { + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + /*converting file time to unix epoch*/ + tmpres /= 10; /*convert into microseconds*/ + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) + { + struct timezone *ptz = static_cast<struct timezone*> (tz); + if (!tzflag) + { + _tzset(); + tzflag++; + } + if (ptz) + { + ptz->tz_minuteswest = _timezone / 60; + ptz->tz_dsttime = _daylight; + } + } + + return 0; +} + +// Define the default comparison operators for Windows (ptw32) 'pthread_t' (not used +// by Ardour AFAIK but would be needed if an array of 'pthread_t' had to be sorted). +#ifndef PTHREAD_H // Defined by PTW32 (Linux and other versions define _PTHREAD_H) +#error "An incompatible version of 'pthread.h' is #included. Use only the Windows (ptw32) version!" +#else +bool operator> (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::greater<void*>()(lhs.p, rhs.p)); +} + +bool operator< (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::less<void*>()(lhs.p, rhs.p)); +} + +bool operator!= (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::not_equal_to<void*>()(lhs.p, rhs.p)); +} + +bool operator== (const pthread_t& lhs, const pthread_t& rhs) +{ + return (!(lhs != rhs)); +} +#endif + +// Functions supplied (later) to std::transform +//*************************************************************** +// +// invert_backslash() +// +// Examines a supplied ASCII character and (if the character is +// a backslash) converts it to a forward slash, +// +// Returns: +// +// The supplied character (converted, if it was a backslash) +// +char invert_backslash(char character) +{ + if ('\\' == character) + character = '/'; + + return (character); +} + +//*************************************************************** +// +// invert_forwardslash() +// +// Examines a supplied ASCII character and (if the character is +// a forward slash) converts it to a backslash, +// +// Returns: +// +// The supplied character (converted, if it was a fwd slash) +// +char invert_forwardslash(char character) +{ + if ('/' == character) + character = '\\'; + + return (character); +} + + +//*************************************************************** +// +// pread() +// +// Emulates pread() using _lseek()/_read()/_lseek(). +// +// Returns: +// +// On Success: The number of bytes read from the file +// On Failure: -1 +// +PBD_API ssize_t PBD_APICALLTYPE +pread(int handle, void *buf, size_t nbytes, off_t offset) +{ +int old_errno; +ssize_t ret; + + off_t old_offset = _tell(handle); + + if (0 > old_offset) + ret = (-1); + else + { + _lseek(handle, offset, SEEK_SET); + ret = _read(handle, buf, nbytes); + + old_errno = errno; + _lseek(handle, old_offset, SEEK_SET); + errno = old_errno; + } + + return (ret); +} + + +//*************************************************************** +// +// pwrite() +// +// Emulates pwrite() using _lseek()/_write()/_lseek(). +// +// Returns: +// +// On Success: The number of bytes written to the file +// On Failure: -1 +// +PBD_API ssize_t PBD_APICALLTYPE +pwrite(int handle, const void *buf, size_t nbytes, off_t offset) +{ +int old_errno; +ssize_t ret; + + off_t old_offset = _lseek(handle, offset, SEEK_SET); + + if (0 > old_offset) + ret = (-1); + else + { + ret = _write(handle, buf, nbytes); + + old_errno = errno; + _lseek(handle, old_offset, SEEK_SET); + errno = old_errno; + } + + return (ret); +} + +namespace PBD { + +//*************************************************************** +// +// TestForMinimumSpecOS() +// +// Tests the user's OS to see if it is Win2K or later (could be +// expanded quite easily to accommodate other OS's) +// +// Returns: +// +// On Success: TRUE (if the user's OS matches the minimum spec) +// On Failure: FALSE otherwise +// +PBD_API bool PBD_APICALLTYPE +TestForMinimumSpecOS(char *revision /* currently ignored */) +{ +bool bRet = true; +#ifdef PLATFORM_WINDOWS + bRet = false; + HINSTANCE hKernelDll = (HINSTANCE)dlopen("kernel32.dll", RTLD_NOW); + + if (hKernelDll) + { + // 'CreateHardLink()' is only available from Win2K onwards. + if (NULL != dlsym(hKernelDll, "CreateHardLinkA")) + bRet = true; + + dlclose(hKernelDll); + } +#endif + // Other OS's could be accommodated here + + return (bRet); +} + + +//*************************************************************** +// +// realpath() +// +// Emulates POSIX realpath() using Win32 _fullpath(). +// +// Returns: +// +// On Success: A pointer to the resolved (absolute) path +// On Failure: NULL +// +PBD_API char* PBD_APICALLTYPE +realpath (const char *original_path, char resolved_path[_MAX_PATH+1]) +{ +char *pRet = NULL; +bool bIsSymLink = 0; // We'll probably need to test the incoming path + // to find out if it points to a Windows shortcut + // (or a hard link) and set this appropriately. + if (bIsSymLink) + { + // At the moment I'm not sure if Windows '_fullpath()' is directly + // equivalent to POSIX 'realpath()' - in as much as the latter will + // resolve the supplied path if it happens to point to a symbolic + // link ('_fullpath()' probably DOESN'T do this but I'm not really + // sure if Ardour needs such functionality anyway). Therefore we'll + // possibly need to add that functionality here at a later date. + } + else + { + char temp[(MAX_PATH+1)*6]; // Allow for maximum length of a path in UTF8 characters + + // POSIX 'realpath()' requires that the buffer size is at + // least PATH_MAX+1, so assume that the user knew this !! + pRet = _fullpath(temp, Glib::locale_from_utf8(original_path).c_str(), _MAX_PATH); + if (NULL != pRet) + strcpy(resolved_path, Glib::locale_to_utf8(temp).c_str()); + } + + return (pRet); +} + + +//*************************************************************** +// +// opendir() +// +// Creates a pointer to a DIR structure, appropriately filled in +// and ready to begin a directory search iteration. +// +// Returns: +// +// On Success: Pointer to a (heap based) DIR structure +// On Failure: NULL +// +PBD_API DIR* PBD_APICALLTYPE +opendir (const char *szPath) +{ +wchar_t wpath[PATH_MAX+1]; +unsigned int rc; +DIR *pDir = 0; + + errno = 0; + + if (!szPath) + errno = EFAULT; + + if ((!errno) && ('\0' == szPath[0])) + errno = ENOTDIR; + + // Determine if the given path really is a directory + + if (!errno) + if (0 == MultiByteToWideChar (CP_UTF8, 0, (LPCSTR)szPath, -1, (LPWSTR)wpath, sizeof(wpath))) + errno = EFAULT; + + if ((!errno) && ((rc = GetFileAttributesW(wpath)) == -1)) + errno = ENOENT; + + if ((!errno) && (!(rc & FILE_ATTRIBUTE_DIRECTORY))) + // Error. Entry exists but not a directory. */ + errno = ENOTDIR; + + if (!errno) + { + // Allocate enough memory to store DIR structure, plus + // the complete directory path originally supplied. + pDir = (DIR *)malloc(sizeof(DIR) + strlen(szPath) + strlen("\\") + strlen ("*")); + + if (!pDir) + { + // Error - out of memory + errno = ENOMEM; + } + } + + if (!errno) + { + // Create the search expression + strcpy(pDir->dd_name, szPath); + + // Add a backslash if the path doesn't already end with one + if (pDir->dd_name[0] != '\0' && + pDir->dd_name[strlen(pDir->dd_name) - 1] != '/' && + pDir->dd_name[strlen(pDir->dd_name) - 1] != '\\') + { + strcat (pDir->dd_name, "\\"); + } + + // Add the search pattern + strcat(pDir->dd_name, "*"); + + // Initialize handle to -1 so that a premature closedir() + // doesn't try to call _findclose() on it. + pDir->dd_handle = (-1); + + // Initialize the status + pDir->dd_stat = 0; + + // Initialize the dirent structure. 'ino' and 'reclen' are invalid under Win32 + // and 'name' simply points at the appropriate part of the findfirst_t struct. + pDir->dd_dir.d_ino = 0; + pDir->dd_dir.d_reclen = 0; + pDir->dd_dir.d_namlen = 0; + strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name); + + return (pDir); // Succeeded + } + + if (pDir) + free (pDir); + return (DIR *) 0; // Failed +} + + +//*************************************************************** +// +// readdir() +// +// Return a pointer to a dirent struct, filled with information +// about the next entry in the directory. +// +// Returns: +// +// On Success: A pointer to the supplied DIR's 'dirent' struct +// On Failure: NULL +// +PBD_API struct dirent* PBD_APICALLTYPE +readdir (DIR* pDir) +{ +int old_errno = 0; +errno = 0; + + // Check for valid DIR struct + if (!pDir) + errno = EFAULT; + + if ((strcmp(pDir->dd_dir.d_name, pDir->dd_dta.name)) && (!errno)) + // The structure does not seem to be set up correctly + errno = EINVAL; + else + { + if (pDir->dd_stat < 0) + { + // We have already returned all files in this directory + // (or the structure has an invalid dd_stat). + return (struct dirent *)0; + } + else if (pDir->dd_stat == 0) + { + // We haven't started the search yet. + // Start the search + pDir->dd_handle = _findfirst (Glib::locale_from_utf8(pDir->dd_name).c_str(), &(pDir->dd_dta)); + + if (pDir->dd_handle == -1) + // The directory is empty + pDir->dd_stat = -1; + else + pDir->dd_stat = 1; + } + else + { + // Do not return ENOENT on last file in directory + old_errno = errno; + + // Get the next search entry + if (_findnext (pDir->dd_handle, &(pDir->dd_dta))) + { + // We are off the end or otherwise error + errno = old_errno; + _findclose (pDir->dd_handle); + pDir->dd_handle = -1; + pDir->dd_stat = -1; + } + else + // Update to indicate the correct status number + pDir->dd_stat++; + } + + if (pDir->dd_stat > 0) + { + // We successfully got an entry. Details about the file are + // already appropriately filled in except for the length of + // file name. + strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name); + pDir->dd_dir.d_namlen = strlen (pDir->dd_dir.d_name); + return (&pDir->dd_dir); // Succeeded + } + } + + return (struct dirent *) 0; // Failed +} + + +//*************************************************************** +// +// closedir() +// +// Frees the resources allocated by opendir(). +// +// Returns: +// +// On Success: 0 +// On Failure: -1 +// +PBD_API int PBD_APICALLTYPE +closedir (DIR *pDir) +{ +int rc = 0; + + errno = 0; + + if (!pDir) + errno = EFAULT; + else + { + if ((-1) != pDir->dd_handle) + rc = _findclose (pDir->dd_handle); + + // Free the DIR structure + free (pDir); + + return rc; // Succeeded + } + + return (-1); // Failed +} + +//*************************************************************** +// +// mkstemp() +// +// Emulates Linux mkstemp() using Win32 _mktemp() and _open() etc. +// +// Returns: +// +// On Success: A file descriptor for the opened file. +// On Failure: (-1) +// +PBD_API int PBD_APICALLTYPE +mkstemp (char *template_name) +{ +int ret = (-1); +char *szFileName; +char szTempPath[PATH_MAX+100]; // Just ensure we have plenty of buffer space + + if (NULL != (szFileName = _mktemp(template_name))) + { + if (0 != ::GetTempPathA(sizeof(szTempPath), szTempPath)) + { + strcat(szTempPath, szFileName); + ret = _open(szTempPath, (_O_CREAT|_O_BINARY|_O_TEMPORARY|_O_RDWR|_O_TRUNC), _S_IWRITE); + } + } + + return (ret); +} + + +//*************************************************************** +// +// ntfs_link() +// +// Emulates Linux link() using Win32 CreateHardLink()(NTFS only). +// +// Returns: +// +// On Success: Non-zero. +// On Failure: Zero (call 'GetLastError()' to retrieve info) +// +PBD_API int PBD_APICALLTYPE +ntfs_link (const char *existing_filepath, const char *link_filepath) +{ +int ret = 1; // 'ERROR_INVALID_FUNCTION' +bool bValidPath = false; + + // Make sure we've been sent a valid input string + if (existing_filepath && link_filepath) + { + std::string strRoot = existing_filepath; + + if ((1 < strRoot.length()) && ('\\' == existing_filepath[0]) && ('\\' == existing_filepath[1])) + { + int slashcnt = 0; + + // We've been sent a network path. Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + // Now, if there are less than four slashes, add a fourth one or abort + std::string::iterator iter = strRoot.begin(); + while ((slashcnt < 4) && (iter != strRoot.end())) + { + if ('/' == (*iter)) + slashcnt++; + + ++iter; + } + + if (slashcnt > 2) + { + // If only 3 slashes were counted, add a trailing slash + if (slashcnt == 3) + strRoot += '/'; + + // Now find the position of the fourth slash + iter = strRoot.begin(); + int charcnt = 0; + for (slashcnt=0; slashcnt<4;) + { + charcnt++; + + if ('/' == (*iter)) + slashcnt++; + + if (++iter == strRoot.end()) + break; + } + + strRoot.resize(charcnt); + bValidPath = true; + } + } + else + { + // Assume a standard Windows style path + if (1 < strRoot.length() && (':' == existing_filepath[1])) + { + // Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + if (2 == strRoot.length()) + strRoot += '/'; + + if ('/' == strRoot[2]) + { + strRoot.resize(3); + bValidPath = true; + } + } + } + + if (bValidPath) + { + char szFileSystemType[_MAX_PATH+1]; + + // Restore the original backslashes + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash); + + // Windows only supports hard links for the NTFS filing + // system, so let's make sure that's what we're using!! + if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1)) + { + std::string strRootFileSystemType = szFileSystemType; + std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper); +#if (_WIN32_WINNT >= 0x0500) + if (0 == strRootFileSystemType.compare("NTFS")) + { + if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards + if (0 == CreateHardLinkA(link_filepath, existing_filepath, NULL)) + { // Note that the above API call cannot create a link to a directory, so + // should we also be checking that the supplied path was actually a file? + ret = GetLastError(); + } + else + SetLastError(ret = 0); // 'NO_ERROR' + } + else + { + ret = 4300; // 'ERROR_INVALID_MEDIA' + } +#endif + } + } + else + ret = 123; // 'ERROR_INVALID_NAME' + } + else + ret = 161; // 'ERROR_BAD_PATHNAME' + + if (ret) + { + SetLastError(ret); + return (-1); + } + else + return (0); +} + + +//*************************************************************** +// +// ntfs_unlink() +// +// Emulates Linux unlink() using Win32 DeleteFile()(NTFS only). +// +// Returns: +// +// On Success: Non-zero. +// On Failure: Zero (call 'GetLastError()' to retrieve info) +// +PBD_API int PBD_APICALLTYPE +ntfs_unlink (const char *link_filepath) +{ +int ret = 1; // 'ERROR_INVALID_FUNCTION' +bool bValidPath = false; + + // Make sure we've been sent a valid input string + if (link_filepath) + { + std::string strRoot = link_filepath; + + if ((1 < strRoot.length()) && ('\\' == link_filepath[0]) && ('\\' == link_filepath[1])) + { + int slashcnt = 0; + + // We've been sent a network path. Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + // Now, if there are less than four slashes, add a fourth one or abort + std::string::iterator iter = strRoot.begin(); + while ((slashcnt < 4) && (iter != strRoot.end())) + { + if ('/' == (*iter)) + slashcnt++; + + ++iter; + } + + if (slashcnt > 2) + { + // If only 3 slashes were counted, add a trailing slash + if (slashcnt == 3) + strRoot += '/'; + + // Now find the position of the fourth slash + iter = strRoot.begin(); + int charcnt = 0; + for (slashcnt=0; slashcnt<4;) + { + charcnt++; + + if ('/' == (*iter)) + slashcnt++; + + if (++iter == strRoot.end()) + break; + } + + strRoot.resize(charcnt); + bValidPath = true; + } + } + else + { + // Assume a standard Windows style path + if (1 < strRoot.length() && (':' == link_filepath[1])) + { + // Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + if (2 == strRoot.length()) + strRoot += '/'; + + if ('/' == strRoot[2]) + { + strRoot.resize(3); + bValidPath = true; + } + } + } + + if (bValidPath) + { + char szFileSystemType[_MAX_PATH+1]; + + // Restore the original backslashes + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash); + + // Windows only supports hard links for the NTFS filing + // system, so let's make sure that's what we're using!! + if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1)) + { + std::string strRootFileSystemType = szFileSystemType; + std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper); +#if (_WIN32_WINNT >= 0x0500) + if (0 == strRootFileSystemType.compare("NTFS")) + if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards + if (0 == DeleteFileA(link_filepath)) + ret = GetLastError(); + else + ret = 0; // 'NO_ERROR' +#endif + } + } + else + ret = 123; // 'ERROR_INVALID_NAME' + } + else + ret = 161; // 'ERROR_BAD_PATHNAME' + + if (ret) + { + SetLastError(ret); + return (-1); + } + else + return (0); +} + +} // namespace PBD + + +//*************************************************************** +// +// dlopen() +// +// Emulates POSIX dlopen() using Win32 LoadLibrary(). +// +// Returns: +// +// On Success: A handle to the opened DLL +// On Failure: NULL +// +PBD_API void* PBD_APICALLTYPE +dlopen (const char *file_name, int mode) +{ + // Note that 'mode' is ignored in Win32 + return(::LoadLibraryA(Glib::locale_from_utf8(file_name).c_str())); +} + + +//*************************************************************** +// +// dlclose() +// +// Emulates POSIX dlclose() using Win32 FreeLibrary(). +// +// Returns: +// +// On Success: A non-zero number +// On Failure: 0 +// +PBD_API int PBD_APICALLTYPE +dlclose (void *handle) +{ + return (::FreeLibrary((HMODULE)handle)); +} + + +//*************************************************************** +// +// dlsym() +// +// Emulates POSIX dlsym() using Win32 GetProcAddress(). +// +// Returns: +// +// On Success: A pointer to the found function or symbol +// On Failure: NULL +// +PBD_API void* PBD_APICALLTYPE +dlsym (void *handle, const char *symbol_name) +{ + // First test for RTLD_DEFAULT and RTLD_NEXT + if ((handle == 0/*RTLD_DEFAULT*/) || (handle == ((void *) -1L)/*RTLD_NEXT*/)) + { + return 0; // Not yet supported for Win32 + } + else + return (::GetProcAddress((HMODULE)handle, symbol_name)); +} + +#define LOCAL_ERROR_BUF_SIZE 1024 +static char szLastWinError[LOCAL_ERROR_BUF_SIZE]; +//*************************************************************** +// +// dlerror() +// +// Emulates POSIX dlerror() using Win32 GetLastError(). +// +// Returns: +// +// On Success: The translated message corresponding to the +// last error +// On Failure: NULL (if the last error was ERROR_SUCCESS) +// +PBD_API char* PBD_APICALLTYPE +dlerror () +{ + DWORD dwLastErrorId = GetLastError(); + if (ERROR_SUCCESS == dwLastErrorId) + return 0; + else + { + if (0 == FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwLastErrorId, + 0, + szLastWinError, + LOCAL_ERROR_BUF_SIZE, + 0)) + { + sprintf(szLastWinError, "Could not decipher the previous error message"); + } + + // POSIX dlerror() seems to reset the + // error system, so emulate that here + SetLastError(ERROR_SUCCESS); + } + + return(szLastWinError); +} + +#endif // COMPILER_MSVC diff --git a/libs/pbd/msvc/msvc_poll.cc b/libs/pbd/msvc/msvc_poll.cc new file mode 100644 index 0000000000..e12ef2bbef --- /dev/null +++ b/libs/pbd/msvc/msvc_poll.cc @@ -0,0 +1,215 @@ +/* + 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. + +*/ + +#ifdef COMPILER_MSVC + +//#include <glib/gtimer.h> +#include "pbd/msvc_pbd.h" + +#ifndef _DWORD_DEFINED +#define _DWORD_DEFINED +typedef unsigned long DWORD; +#endif // !_DWORD_DEFINED + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Note that this entire strategy failed to work, at least for pipes. It turned * + * out that Windows 'tell()' always returns 0 when used on a pipe. This strategy * + * is now deprecated, having been replaced by a new pipe-like object, which I've * + * called 'PBD::pipex'. This polling functionality is included here mostly so * + * that Ardour will build and launch under Windows. However, any module that * + * relies on polling a pipe will eventually need to use the new pipex object. * + * This code will allow it to compile and link successfully, although it won't * + * poll successfully at run time. Having said that, these functions might well * + * work for ports and/or other machanisms that get represented by a file handle. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int poll_input (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout) +{ +DWORD dwOldTickCount, + dwNewTickCount = GetTickCount(); +bool input = false, + error = false; +int ret = 0; + + if (NULL != fds) + { + nfds_t loop; + short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND); + + errno = NO_ERROR; + + do + { + dwOldTickCount = dwNewTickCount; + + for (loop=0; loop<nfds; loop++) + fds[loop].revents = 0; + + for (loop=0; (loop<nfds && !error); loop++) + { + if (!(fds[loop].events & ev_mask)) + { + long pos = _tell(fds[loop].fd); + + if (0 > pos) + { + // An error occured ('errno' should have been set by '_tell()') + ret = (-1); + fds[loop].revents = POLLERR; + if (fds[loop].events & POLLRDNORM) + fds[loop].revents |= POLLRDNORM; + if (fds[loop].events & POLLRDBAND) + fds[loop].revents |= POLLRDBAND; + if (fds[loop].events & POLLPRI) + fds[loop].revents |= POLLPRI; + + // Do we want to abort on error? + if (fds[loop].events & POLLERR) + error = true; + } + else if (pos > 0) + { + // Input characters were found for this fd + ret += 1; + if (fds[loop].events & POLLRDNORM) + fds[loop].revents |= POLLRDNORM; + if (fds[loop].events & POLLRDBAND) + fds[loop].revents |= POLLRDBAND; + if (fds[loop].events & POLLPRI) + fds[loop].revents |= POLLPRI; + + // Do we want to abort on input? + if ((fds[loop].events & POLLIN) || + (fds[loop].events & POLLPRI) || + (fds[loop].events & POLLRDNORM) || + (fds[loop].events & POLLRDBAND)) + input = true; + } + } + } + + if (input) + break; + + dwNewTickCount = GetTickCount(); + elapsed_time += (dwNewTickCount-dwOldTickCount); + // Note that the above will wrap round if the user leaves + // his computer powered up for more than about 50 days! + + // Sleep briefly because GetTickCount() only has an accuracy of 10mS + Sleep(10); // For some reason 'g_usleep()' craps over everything here. Different 'C' runtimes??? + + } while ((!error) && ((timeout == (-1)) || (elapsed_time < timeout))); + } + else + { + errno = ERROR_BAD_ARGUMENTS; + ret = (-1); + } + + return (ret); +} + +int poll_output (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout) +{ +int ret = 0; // This functionality is not yet implemented + + if (NULL != fds) + { + // Just flag whichever pollfd was specified for writing + short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND); + + errno = NO_ERROR; + elapsed_time = 0; + + for (nfds_t loop=0; loop<nfds; loop++) + { + if (fds[loop].events & ev_mask) + { + fds[loop].revents = POLLNVAL; + errno = ERROR_INVALID_ACCESS; + ret = (-1); + } + } + } + else + { + errno = ERROR_BAD_ARGUMENTS; + ret = (-1); + } + + return (ret); +} + +//*************************************************************** +// +// poll() +// +// Emulates POSIX poll() using Win32 _tell(). +// +// Returns: +// +// On Success: A positive integer indicating the total number +// of file descriptors that were available for +// writing or had data available for reading. +// On Failure: -1 (the actual error is saved in 'errno'). +// +PBD_API int PBD_APICALLTYPE +poll (struct pollfd *fds, nfds_t nfds, int timeout) +{ +int elapsed_time = 0; +int ret = (-1); + + // Note that this functionality is not fully implemented. + // At the time of writing, Ardour seems only to poll on + // read pipes. Therefore return an error if any write + // pipe seems to have been specified or if too many file + // descriptors were passed. + short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND); + + if ((nfds > OPEN_MAX) || (nfds > NPOLLFILE)) + { + errno = ERROR_TOO_MANY_OPEN_FILES; + } + else + { + ret = 0; + + for (nfds_t loop=0; loop<nfds; loop++) + { + if (fds[loop].events & ev_mask) + { + ret = poll_output(fds, nfds, elapsed_time, timeout); + break; + } + } + + if (0 == ret) + { + // Poll for input + ret = poll_input(fds, nfds, elapsed_time, timeout); + } + } + + return (ret); +} + +#endif //COMPILER_MSVC diff --git a/libs/pbd/pathexpand.cc b/libs/pbd/pathexpand.cc index 4911f12788..5784ec9428 100644 --- a/libs/pbd/pathexpand.cc +++ b/libs/pbd/pathexpand.cc @@ -18,8 +18,10 @@ */ #include <vector> -#include <climits> #include <iostream> +#include <climits> +#include <cerrno> +#include <cstdlib> #include <regex.h> @@ -32,6 +34,22 @@ using std::string; using std::vector; string +PBD::canonical_path (const std::string& path) +{ +#ifdef COMPILER_MINGW + return path; +#else + char buf[PATH_MAX+1]; + + if (!realpath (path.c_str(), buf) && (errno != ENOENT)) { + return path; + } + + return string (buf); +#endif +} + +string PBD::path_expand (string path) { if (path.empty()) { @@ -97,13 +115,7 @@ PBD::path_expand (string path) /* canonicalize */ - char buf[PATH_MAX+1]; - - if (realpath (path.c_str(), buf)) { - return buf; - } else { - return string(); - } + return canonical_path (path); } string diff --git a/libs/pbd/pathscanner.cc b/libs/pbd/pathscanner.cc index fac2dcfd96..b9b501a120 100644 --- a/libs/pbd/pathscanner.cc +++ b/libs/pbd/pathscanner.cc @@ -18,11 +18,19 @@ $Id$ */ +#ifdef COMPILER_MSVC +#include <stdlib.h> +#include <stdio.h> +using PBD::readdir; +using PBD::opendir; +using PBD::closedir; +#else +#include <dirent.h> #include <cstdlib> #include <cstdio> +#endif #include <cstring> #include <vector> -#include <dirent.h> #include <sys/types.h> #include <sys/stat.h> diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc index d43bc64f63..9c405745ac 100644 --- a/libs/pbd/pbd/abstract_ui.cc +++ b/libs/pbd/pbd/abstract_ui.cc @@ -28,6 +28,15 @@ #include "i18n.h" +#ifdef COMPILER_MSVC +#include <ardourext/misc.h> // Needed for 'DECLARE_DEFAULT_COMPARISONS'. Objects in an STL container can be + // searched and sorted. Thus, when instantiating the container, MSVC complains + // if the type of object being contained has no appropriate comparison operators + // defined (specifically, if operators '<' and '==' are undefined). This seems + // to be the case with ptw32 'pthread_t' which is a simple struct. +DECLARE_DEFAULT_COMPARISONS(pthread_t) +#endif + using namespace std; template<typename RequestBuffer> void @@ -146,7 +155,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt) return 0; } - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", name(), rt, pthread_self())); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", name(), rt, pthread_name())); vec.buf[0]->type = rt; vec.buf[0]->valid = true; @@ -158,7 +167,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt) * are not at work. */ - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", name(), rt, pthread_self())); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", name(), rt, pthread_name())); RequestObject* req = new RequestObject; req->type = rt; @@ -213,7 +222,7 @@ AbstractUI<RequestObject>::handle_ui_requests () for (i = request_buffers.begin(); i != request_buffers.end(); ) { if ((*i).second->dead) { DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 deleting dead per-thread request buffer for %3 @ %4\n", - name(), pthread_self(), i->first, i->second)); + name(), pthread_name(), i->second)); delete (*i).second; RequestBufferMapIterator tmp = i; ++tmp; @@ -241,7 +250,7 @@ AbstractUI<RequestObject>::handle_ui_requests () request_buffer_map_lock.lock (); if (!req->valid) { - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", name(), pthread_self(), req->type)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", name(), pthread_name(), req->type)); delete req; request_buffer_map_lock.unlock (); continue; @@ -253,7 +262,7 @@ AbstractUI<RequestObject>::handle_ui_requests () */ if (req->invalidation) { - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_self())); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_name())); /* after this call, if the object referenced by the * invalidation record is deleted, it will no longer @@ -281,7 +290,7 @@ AbstractUI<RequestObject>::handle_ui_requests () lm.release (); - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", name(), pthread_self(), req->type)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", name(), pthread_name(), req->type)); /* and lets do it ... this is a virtual call so that each * specific type of UI can have its own set of requests without @@ -290,7 +299,7 @@ AbstractUI<RequestObject>::handle_ui_requests () do_request (req); - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", name(), pthread_self(), req->type)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", name(), pthread_name(), req->type)); delete req; /* re-acquire the list lock so that we check again */ @@ -315,7 +324,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req) /* the thread that runs this UI's event loop is sending itself a request: we dispatch it immediately and inline. */ - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_self(), req->type)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_name(), req->type)); do_request (req); } else { @@ -334,13 +343,13 @@ AbstractUI<RequestObject>::send_request (RequestObject *req) RequestBuffer* rbuf = per_thread_request_buffer.get (); if (rbuf != 0) { - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", name(), pthread_self(), req->type)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", name(), pthread_name(), req->type)); rbuf->increment_write_ptr (1); } else { /* no per-thread buffer, so just use a list with a lock so that it remains single-reader/single-writer semantics */ - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", name(), pthread_self(), req->type)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", name(), pthread_name(), req->type)); Glib::Threads::Mutex::Lock lm (request_list_lock); request_list.push_back (req); } @@ -349,7 +358,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req) at the per-thread and generic request lists. */ - request_channel.wakeup (); + signal_new_request (); } } @@ -357,7 +366,7 @@ template<typename RequestObject> void AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const boost::function<void()>& f) { if (caller_is_self()) { - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", name(), pthread_self(), &f, invalidation)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation)); f (); return; } @@ -368,7 +377,7 @@ AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const bo return; } - DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", name(), pthread_self(), &f, invalidation)); + DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation)); /* copy semantics: copy the functor into the request object */ diff --git a/libs/pbd/pbd/abstract_ui.h b/libs/pbd/pbd/abstract_ui.h index fb09dee5c2..905074c474 100644 --- a/libs/pbd/pbd/abstract_ui.h +++ b/libs/pbd/pbd/abstract_ui.h @@ -56,8 +56,22 @@ class AbstractUI : public BaseUI , ui (uir) {} }; typedef typename RequestBuffer::rw_vector RequestBufferVector; + +#if defined(__MINGW32__) + + struct pthread_cmp + { + bool operator() (const ptw32_handle_t& thread1, const ptw32_handle_t& thread2) + { + return thread1.p < thread2.p; + } + }; + typedef typename std::map<pthread_t,RequestBuffer*, pthread_cmp>::iterator RequestBufferMapIterator; + typedef std::map<pthread_t,RequestBuffer*, pthread_cmp> RequestBufferMap; +#else typedef typename std::map<pthread_t,RequestBuffer*>::iterator RequestBufferMapIterator; typedef std::map<pthread_t,RequestBuffer*> RequestBufferMap; +#endif RequestBufferMap request_buffers; static Glib::Threads::Private<RequestBuffer> per_thread_request_buffer; diff --git a/libs/pbd/pbd/atomic_counter.h b/libs/pbd/pbd/atomic_counter.h new file mode 100644 index 0000000000..1e1998e1f1 --- /dev/null +++ b/libs/pbd/pbd/atomic_counter.h @@ -0,0 +1,99 @@ +/* + Copyright (C) 2010 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 PBD_ATOMIC_COUNTER_H +#define PBD_ATOMIC_COUNTER_H + +#include <glib.h> + +namespace PBD { + +class atomic_counter +{ + /** + * Prevent copying and assignment + */ + atomic_counter (const atomic_counter&); + atomic_counter& operator= (const atomic_counter&); + +public: + + atomic_counter (gint value = 0) + : + m_value(value) + { } + + gint get() const + { + return g_atomic_int_get (&m_value); + } + + void set (gint new_value) + { + g_atomic_int_set (&m_value, new_value); + } + + void increment () + { + g_atomic_int_inc (&m_value); + } + + void operator++ () + { + increment (); + } + + bool decrement_and_test () + { + return g_atomic_int_dec_and_test (&m_value); + } + + bool operator-- () + { + return decrement_and_test (); + } + + bool compare_and_exchange (gint old_value, gint new_value) + { + return g_atomic_int_compare_and_exchange + ( + &m_value, + old_value, + new_value + ); + } + + /** + * convenience method, \see compare_and_exchange + */ + bool cas (gint old_value, gint new_value) + { + return compare_and_exchange (old_value, new_value); + } + +private: + + // Has to be mutable when using the apple version of gcc. + mutable volatile gint m_value; + +}; + +} // namespace PBD + +#endif // PBD_ATOMIC_COUNTER_H diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h index 186a3c55a6..d947a06b34 100644 --- a/libs/pbd/pbd/base_ui.h +++ b/libs/pbd/pbd/base_ui.h @@ -71,13 +71,13 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop void quit (); protected: - CrossThreadChannel request_channel; bool _ok; Glib::RefPtr<Glib::MainLoop> _main_loop; - Glib::Threads::Thread* run_loop_thread; + Glib::RefPtr<Glib::MainContext> m_context; + Glib::Threads::Thread* run_loop_thread; Glib::Threads::Mutex _run_lock; - Glib::Threads::Cond _running; + Glib::Threads::Cond _running; /* this signals _running from within the event loop, from an idle callback @@ -92,9 +92,17 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop virtual void thread_init () {}; +#ifdef PLATFORM_WINDOWS + static gboolean _request_handler (gpointer); + bool request_handler (); +#else /** Called when there input ready on the request_channel */ bool request_handler (Glib::IOCondition); +#endif + + void signal_new_request (); + void attach_request_source (); /** Derived UI objects must implement this method, * which will be called whenever there are requests @@ -105,6 +113,10 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop private: std::string _name; BaseUI* base_ui_instance; + +#ifndef PLATFORM_WINDOWS + CrossThreadChannel request_channel; +#endif static uint64_t rt_bit; diff --git a/libs/pbd/pbd/debug.h b/libs/pbd/pbd/debug.h index 989cd42dd1..704c9d0dad 100644 --- a/libs/pbd/pbd/debug.h +++ b/libs/pbd/pbd/debug.h @@ -43,6 +43,7 @@ namespace PBD { extern uint64_t Pool; extern uint64_t EventLoop; extern uint64_t AbstractUI; + extern uint64_t FileUtils; } } diff --git a/libs/pbd/pbd/fallback_folders.h b/libs/pbd/pbd/fallback_folders.h new file mode 100644 index 0000000000..60935b4424 --- /dev/null +++ b/libs/pbd/pbd/fallback_folders.h @@ -0,0 +1,62 @@ +/* + 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 __platform_fallback_folders_h__ +#define __platform_fallback_folders_h__ + +#include <pbd/msvc_pbd.h> +#include <glib/gtypes.h> + +#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!! + PBD_API gchar* PBD_APICALLTYPE get_win_special_folder (int csidl); +#endif + +namespace PBD { + + typedef enum fallback_folder_t { + FOLDER_LOCALE, + FOLDER_GTK, + FOLDER_CONFIG, + FOLDER_ARDOUR, + FOLDER_MODULE, + FOLDER_DATA, + FOLDER_ICONS, + FOLDER_PIXMAPS, + FOLDER_CONTROL_SURFACES, + FOLDER_VAMP, + FOLDER_LADSPA, + FOLDER_VST, + FOLDER_BUNDLED_LV2, + FALLBACK_FOLDER_MAX + }; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + PBD_API G_CONST_RETURN gchar* PBD_APICALLTYPE get_platform_fallback_folder (PBD::fallback_folder_t index); + PBD_API G_CONST_RETURN gchar* G_CONST_RETURN * PBD_APICALLTYPE alloc_platform_fallback_folders (); + PBD_API void PBD_APICALLTYPE free_platform_fallback_folders (); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +} // namespace PBD + +#endif /* __platform_fallback_folders_h__ */ diff --git a/libs/pbd/pbd/ffs.h b/libs/pbd/pbd/ffs.h new file mode 100644 index 0000000000..3a2eadfae7 --- /dev/null +++ b/libs/pbd/pbd/ffs.h @@ -0,0 +1,27 @@ +/* + Copyright (C) 2013 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 __libpbd_ffs_h__ +#define __libpbd_ffs_h__ + +namespace PBD { + int ffs(int x); +} + +#endif /* __libpbd_ffs_h__ */ diff --git a/libs/pbd/pbd/floating.h b/libs/pbd/pbd/floating.h index 105a976637..6daef5d4aa 100644 --- a/libs/pbd/pbd/floating.h +++ b/libs/pbd/pbd/floating.h @@ -26,6 +26,8 @@ #ifndef __libpbd__floating_h__ #define __libpbd__floating_h__ +#include <stdint.h> + #include <cmath> namespace PBD { diff --git a/libs/pbd/pbd/glib_semaphore.h b/libs/pbd/pbd/glib_semaphore.h new file mode 100644 index 0000000000..c78226f737 --- /dev/null +++ b/libs/pbd/pbd/glib_semaphore.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2010 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 PBD_GLIB_SEMAPHORE_H +#define PBD_GLIB_SEMAPHORE_H + +#include <glibmm/threads.h> + +#include "atomic_counter.h" + +namespace PBD { + +class GlibSemaphore +{ + + // prevent copying and assignment + GlibSemaphore(const GlibSemaphore& sema); + GlibSemaphore& operator= (const GlibSemaphore& sema); + +public: + + GlibSemaphore (gint initial_val = 1); + + void wait (); + + bool try_wait (); + + void post (); + +private: + + atomic_counter m_counter; + Glib::Threads::Cond m_cond; + Glib::Threads::Mutex m_mutex; + +}; + +} // namespace PBD + +#endif // PBD_SEMAPHORE_H diff --git a/libs/pbd/uuid_boost.cc b/libs/pbd/pbd/localeguard.h index 1a988b9820..20899b5c80 100644 --- a/libs/pbd/uuid_boost.cc +++ b/libs/pbd/pbd/localeguard.h @@ -1,6 +1,5 @@ /* - Copyright (C) 2008 Paul Davis - Author: Sakari Bergen + Copyright (C) 1999-2010 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 @@ -18,20 +17,21 @@ */ -#include "pbd/uuid.h" +#ifndef __pbd_localeguard_h__ +#define __pbd_localeguard_h__ -using namespace PBD; +#include <string> -UUID& -UUID::operator= (std::string const & str) -{ - boost::uuids::string_generator gen; - *((boost::uuids::uuid*) this) = gen (str); - return *this; -} +namespace PBD { -std::string -UUID::to_s () const -{ - return std::string ((const char*) data, size()); -} +struct LocaleGuard { + LocaleGuard (const char*); + ~LocaleGuard (); + const char* old; + + /* JE - temporary !!!! */static std::string current; +}; + +}; // namespace + +#endif /* __pbd_localeguard_h__ */ diff --git a/libs/pbd/pbd/localtime_r.h b/libs/pbd/pbd/localtime_r.h new file mode 100644 index 0000000000..ad5b89d134 --- /dev/null +++ b/libs/pbd/pbd/localtime_r.h @@ -0,0 +1,13 @@ +#ifndef PBD_LOCALTIME_R +#define PBD_LOCALTIME_R +#include <time.h> + +#ifdef COMPILER_MSVC + #define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) +#else + extern struct tm *localtime_r(const time_t *const timep, struct tm *p_tm); +#endif + +#endif diff --git a/libs/pbd/pbd/msvc_pbd.h b/libs/pbd/pbd/msvc_pbd.h new file mode 100644 index 0000000000..8d157731bd --- /dev/null +++ b/libs/pbd/pbd/msvc_pbd.h @@ -0,0 +1,249 @@ +/* + 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_pbd_h_ +#define _msvc_pbd_h_ + +#ifdef PBD_IS_IN_WIN_STATIC_LIB // #define if your project uses libpbd (under Windows) as a static library +#define PBD_IS_IN_WINDLL 0 +#endif + +#ifndef COMPILER_MSVC +#include <sys/time.h> +#else +#include <ardourext/misc.h> +#include <ardourext/sys/time.h> +#endif + +#if !defined(PBD_IS_IN_WINDLL) + #if defined(COMPILER_MSVC) || defined(COMPILER_MINGW) + // If you need '__declspec' compatibility, add extra compilers to the above as necessary + #define PBD_IS_IN_WINDLL 1 + #else + #define PBD_IS_IN_WINDLL 0 + #endif +#endif + +#if PBD_IS_IN_WINDLL && !defined(PBD_API) + #if defined(BUILDING_PBD) + #define PBD_API __declspec(dllexport) + #define PBD_APICALLTYPE __stdcall + #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point + #define PBD_API __declspec(dllimport) + #define PBD_APICALLTYPE __stdcall + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#elif !defined(PBD_API) + // Other compilers / platforms could be accommodated here + #define PBD_API + #define PBD_APICALLTYPE + #define GETOPT_API + #define GETOPT_APICALLTYPE +#endif + +#ifndef GETOPT_API + #if defined(BUILDING_GETOPT) + #define GETOPT_API __declspec(dllexport) + #define GETOPT_APICALLTYPE __cdecl + #elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MINGW32__) + #define GETOPT_API __declspec(dllimport) + #define GETOPT_APICALLTYPE __cdecl + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#endif // GETOPT_API + +#ifndef _MAX_PATH +#define _MAX_PATH 260 +#endif +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// This function is (hopefully) temporary and is placed here +// because 'g_usleep()' doesn't seem to work very well for glib-win32 +void pbd_g_usleep (unsigned long microseconds); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#ifndef POLLIN +#define POLLIN 1 +#define POLLPRI 2 +#define POLLOUT 4 +#define POLLERR 8 +#define POLLHUP 16 +#define POLLNVAL 32 +#define NPOLLFILE 64 + +#define POLLRDNORM POLLIN +#define POLLRDBAND POLLIN +#define POLLWRNORM POLLOUT +#define POLLWRBAND POLLOUT +#endif + +#ifdef PLATFORM_WINDOWS + +#ifndef PBDEXTN_API + #if defined(BUILDING_PBDEXTN) + #define PBDEXTN_API __declspec(dllexport) + #define PBDEXTN_APICALLTYPE __cdecl + #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point + #define PBDEXTN_API __declspec(dllimport) + #define PBDEXTN_APICALLTYPE __cdecl + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#endif // PBDEXTN_API + +#ifndef CYGIMPORT_API + #define CYGIMPORT_API __declspec(dllimport) + #define CYGIMPORT_APICALLTYPE __cdecl +#endif // CYGIMPORT_API + +#ifndef __THROW +#define __THROW throw() +#endif + +#ifndef RTLD_DEFAULT +#define RTLD_DEFAULT ((void *) 0) +#define RTLD_NEXT ((void *) -1L) +#define RTLD_LAZY 0x00001 +#define RTLD_NOW 0x00002 +#define RTLD_BINDING_MASK 0x00003 +#define RTLD_NOLOAD 0x00004 +#define RTLD_GLOBAL 0x00004 +#define RTLD_DEEPBIND 0x00008 +#endif + +#ifndef OPEN_MAX +#define OPEN_MAX 32 +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +PBDEXTN_API int PBDEXTN_APICALLTYPE cyginit (unsigned int result); +PBD_API int PBD_APICALLTYPE dlclose (void *handle) __THROW; +PBD_API void* PBD_APICALLTYPE dlopen (const char *file_name, int mode) __THROW; +PBD_API void* PBD_APICALLTYPE dlsym (void *handle, const char *symbol_name) __THROW; +PBD_API char* PBD_APICALLTYPE dlerror () __THROW; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#ifndef __CYGWIN__ +#include <rpc.h> +#include <io.h> +#include <sys/types.h> + +typedef int (FAR PBDEXTN_APICALLTYPE *CYGINIT_API)(unsigned int); + +#ifndef FILENAME_MAX +#define FILENAME_MAX (260) +#endif + +#ifndef _SSIZE_T_ +#define _SSIZE_T_ +typedef long _ssize_t; + +#ifndef _NO_OLDNAMES +typedef _ssize_t ssize_t; +#endif +#endif /* ! _SSIZE_T_ */ + +struct dirent +{ + long d_ino; // Always zero + unsigned short d_reclen; // Always zero + unsigned short d_namlen; // Length of name in d_name + char d_name[FILENAME_MAX]; // File name +}; + +// This is an internal data structure. Do not use it +// except as an argument to one of the functions below. +typedef struct +{ + // Disk transfer area for this dir + struct _finddata_t dd_dta; + + // 'dirent' struct to return from dir (NOTE: this + // is not thread safe). + struct dirent dd_dir; + + // '_findnext()' handle + long dd_handle; + + // Current status of search: + // 0 = not started yet (next entry to read is first entry) + // -1 = off the end + // Otherwise - positive (0 based) index of next entry + int dd_stat; + + // Full path for dir with search pattern (struct will be extended) + char dd_name[1]; +} DIR; + +struct pollfd +{ + int fd; + short events; + short revents; +}; + +typedef unsigned int nfds_t; + +PBD_API int PBD_APICALLTYPE gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz); +PBD_API ssize_t PBD_APICALLTYPE pread(int handle, void *buf, size_t nbytes, off_t offset); +PBD_API ssize_t PBD_APICALLTYPE pwrite(int handle, const void *buf, size_t nbytes, off_t offset); +PBD_API int PBD_APICALLTYPE poll(struct pollfd *fds, nfds_t nfds, int timeout); + +namespace PBD { + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +PBD_API bool PBD_APICALLTYPE TestForMinimumSpecOS(char *revision="currently ignored"); +PBD_API char* PBD_APICALLTYPE realpath (const char *original_path, char resolved_path[_MAX_PATH+1]); +PBD_API int PBD_APICALLTYPE mkstemp (char *template_name); +PBD_API int PBD_APICALLTYPE ntfs_link (const char *existing_filepath, const char *link_filepath); +PBD_API int PBD_APICALLTYPE ntfs_unlink (const char *link_filepath); + +// These are used to replicate 'dirent.h' functionality +PBD_API DIR* PBD_APICALLTYPE opendir (const char *szPath); +PBD_API struct dirent* PBD_APICALLTYPE readdir (DIR *pDir); +PBD_API int PBD_APICALLTYPE closedir (DIR *pDir); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +} // namespace PBD + +#endif // !__CYGWIN__ +#endif // PLATFORM_WINDOWS +#endif // _msvc_pbd_h_ diff --git a/libs/pbd/pbd/pathexpand.h b/libs/pbd/pbd/pathexpand.h index a7b9f7557a..2b2639e07e 100644 --- a/libs/pbd/pbd/pathexpand.h +++ b/libs/pbd/pbd/pathexpand.h @@ -22,6 +22,7 @@ #include <string> namespace PBD { + std::string canonical_path (const std::string& path); std::string path_expand (std::string path); std::string search_path_expand (std::string path); } diff --git a/libs/pbd/pbd/pathscanner.h b/libs/pbd/pbd/pathscanner.h index 1b7ef58655..796648de0f 100644 --- a/libs/pbd/pbd/pathscanner.h +++ b/libs/pbd/pbd/pathscanner.h @@ -22,7 +22,11 @@ #include <vector> #include <string> +#ifdef COMPILER_MSVC +#include <ardourext/misc.h> +#else #include <regex.h> +#endif class PathScanner diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h index 793c3a1980..3d89d5581e 100644 --- a/libs/pbd/pbd/pthread_utils.h +++ b/libs/pbd/pbd/pthread_utils.h @@ -20,7 +20,11 @@ #ifndef __pbd_pthread_utils__ #define __pbd_pthread_utils__ +#ifdef COMPILER_MSVC +#include <ardourext/pthread.h> +#else #include <pthread.h> +#endif #include <signal.h> #include <string> #include <stdint.h> diff --git a/libs/pbd/pbd/resource.h b/libs/pbd/pbd/resource.h new file mode 100644 index 0000000000..ec826e4930 --- /dev/null +++ b/libs/pbd/pbd/resource.h @@ -0,0 +1,49 @@ +/* + 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> + +namespace PBD { + +typedef uint64_t rlimit_t; + +enum ResourceType { + OpenFiles +}; + +struct ResourceLimit +{ + rlimit_t current_limit; + rlimit_t max_limit; +}; + +/** + * @return true on success, false on error + */ +bool +get_resource_limit (ResourceType resource, ResourceLimit& limit); + +/** + * @return true on success, false on error + */ +bool +set_resource_limit (ResourceType resource, const ResourceLimit& limit); + + +} // namespace PBD diff --git a/libs/pbd/pbd/ringbuffer.h b/libs/pbd/pbd/ringbuffer.h index 652457b493..bb5485a8f3 100644 --- a/libs/pbd/pbd/ringbuffer.h +++ b/libs/pbd/pbd/ringbuffer.h @@ -198,7 +198,7 @@ RingBuffer<T>::write (T const *src, guint cnt) } template<class T> void -RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec) +RingBuffer<T>::get_read_vector (typename RingBuffer<T>::rw_vector *vec) { guint free_cnt; @@ -239,7 +239,7 @@ RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec) } template<class T> void -RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec) +RingBuffer<T>::get_write_vector (typename RingBuffer<T>::rw_vector *vec) { guint free_cnt; diff --git a/libs/pbd/pbd/ringbufferNPT.h b/libs/pbd/pbd/ringbufferNPT.h index e43f967592..b3890ba81b 100644 --- a/libs/pbd/pbd/ringbufferNPT.h +++ b/libs/pbd/pbd/ringbufferNPT.h @@ -197,7 +197,7 @@ RingBufferNPT<T>::write (const T *src, size_t cnt) } template<class T> void -RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec) +RingBufferNPT<T>::get_read_vector (typename RingBufferNPT<T>::rw_vector *vec) { size_t free_cnt; size_t cnt2; @@ -237,7 +237,7 @@ RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec) } template<class T> void -RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec) +RingBufferNPT<T>::get_write_vector (typename RingBufferNPT<T>::rw_vector *vec) { size_t free_cnt; size_t cnt2; diff --git a/libs/pbd/pbd/search_path.h b/libs/pbd/pbd/search_path.h index 5358d6e14c..cc53dbebac 100644 --- a/libs/pbd/pbd/search_path.h +++ b/libs/pbd/pbd/search_path.h @@ -20,6 +20,10 @@ #ifndef PBD_SEARCH_PATH_INCLUDED #define PBD_SEARCH_PATH_INCLUDED +#ifdef SearchPath +#undef SearchPath +#endif + #include <string> #include <vector> diff --git a/libs/pbd/pbd/semaphore.h b/libs/pbd/pbd/semaphore.h index e54063a15a..5f0a2df2c0 100644 --- a/libs/pbd/pbd/semaphore.h +++ b/libs/pbd/pbd/semaphore.h @@ -22,7 +22,7 @@ #ifdef __APPLE__ # include <mach/mach.h> -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) # include <windows.h> #else # include <semaphore.h> @@ -69,7 +69,7 @@ public: private: #if defined(__APPLE__) semaphore_t _sem; // sem_t is a worthless broken mess on OSX -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) HANDLE _sem; // types are overrated anyway #else sem_t _sem; @@ -114,7 +114,7 @@ Semaphore::try_wait() return semaphore_timedwait(_sem, zero) == KERN_SUCCESS; } -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) inline Semaphore::Semaphore(unsigned initial) @@ -151,7 +151,7 @@ Semaphore::try_wait() return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0; } -#else /* !defined(__APPLE__) && !defined(_WIN32) */ +#else /* !defined(__APPLE__) && !defined(PLATFORM_WINDOWS) */ Semaphore::Semaphore(unsigned initial) { diff --git a/libs/pbd/pbd/semutils.h b/libs/pbd/pbd/semutils.h index 6f5f0e9331..af5c201b85 100644 --- a/libs/pbd/pbd/semutils.h +++ b/libs/pbd/pbd/semutils.h @@ -19,13 +19,20 @@ #ifndef __pbd_semutils_h__ #define __pbd_semutils_h__ +#ifdef PLATFORM_WINDOWS +#include <windows.h> +#else #include <semaphore.h> +#endif namespace PBD { class ProcessSemaphore { private: -#ifdef __APPLE__ +#ifdef PLATFORM_WINDOWS + HANDLE _sem; + +#elif __APPLE__ sem_t* _sem; sem_t* ptr_to_sem() const { return _sem; } #else @@ -37,8 +44,15 @@ class ProcessSemaphore { ProcessSemaphore (const char* name, int val); ~ProcessSemaphore (); +#ifdef PLATFORM_WINDOWS + + int signal (); + int wait (); + +#else int signal () { return sem_post (ptr_to_sem()); } int wait () { return sem_wait (ptr_to_sem()); } +#endif }; } diff --git a/libs/pbd/pbd/timersub.h b/libs/pbd/pbd/timersub.h new file mode 100644 index 0000000000..6cb152414c --- /dev/null +++ b/libs/pbd/pbd/timersub.h @@ -0,0 +1,32 @@ +/* Copyright (C) 1991-1994,1996-2003,2005,2006,2009 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/time.h> + +#ifndef timersub +# define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif + diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h index 11ff2bf321..e9582a1b53 100644 --- a/libs/pbd/pbd/undo.h +++ b/libs/pbd/pbd/undo.h @@ -25,7 +25,11 @@ #include <map> #include <sigc++/slot.h> #include <sigc++/bind.h> +#ifndef COMPILER_MSVC #include <sys/time.h> +#else +#include <ardourext/misc.h> +#endif #include "pbd/command.h" diff --git a/libs/pbd/pbd/uuid.h b/libs/pbd/pbd/uuid.h index 16a67436b7..bf5abfc1ac 100644 --- a/libs/pbd/pbd/uuid.h +++ b/libs/pbd/pbd/uuid.h @@ -22,29 +22,35 @@ #define __pbd_uuid_h__ #include <string> -#include <uuid/uuid.h> +#include <boost/uuid/uuid.hpp> +#include <boost/uuid/uuid_generators.hpp> namespace PBD { -class UUID { +class UUID : public boost::uuids::uuid { public: - UUID () { uuid_generate (id); } - UUID (UUID const & other) { uuid_copy (id, other.id); } - UUID (std::string const & str) { uuid_parse (str.c_str(), id); } - - UUID& operator= (std::string const & str); - std::string to_s () const; - - bool operator== (UUID const & other) const { return !uuid_compare (id, other.id); } - bool operator!= (UUID const & other) const { return uuid_compare (id, other.id); } - bool operator< (UUID const & other) const { return uuid_compare (id, other.id) < 0; } - - operator bool() const { return !uuid_is_null (id); } - - private: - uuid_t id; + UUID () + : boost::uuids::uuid (boost::uuids::random_generator()()) {} + UUID (std::string const & str) + : boost::uuids::uuid (boost::uuids::string_generator()(str)) {} + explicit UUID (boost::uuids::uuid const& u) + : boost::uuids::uuid(u) + {} + + operator boost::uuids::uuid() { + return static_cast<boost::uuids::uuid&>(*this); + } + + operator boost::uuids::uuid() const { + return static_cast<boost::uuids::uuid const&>(*this); + } + + UUID& operator= (std::string const & str); + std::string to_s () const; + + operator bool() const { return !is_nil(); } }; } // namespace PBD diff --git a/libs/pbd/pbd/uuid_boost.h b/libs/pbd/pbd/uuid_boost.h deleted file mode 100644 index 275b72648a..0000000000 --- a/libs/pbd/pbd/uuid_boost.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright (C) 2008 Paul Davis - Author: Sakari Bergen - - 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 __pbd_uuid_h__ -#define __pbd_uuid_h__ - -#include <string> -#include <boost/uuid/uuid.hpp> -#include <boost/uuid/uuid_generators.hpp> - -namespace PBD { - -class UUID : public boost::uuids::uuid { - - public: - UUID () - : boost::uuids::uuid (boost::uuids::random_generator()()) {} - UUID (std::string const & str) - : boost::uuids::uuid (boost::uuids::string_generator()(str)) {} - - explicit UUID (boost::uuids::uuid const& u) - : boost::uuids::uuid(u) - {} - - operator boost::uuids::uuid() { - return static_cast<boost::uuids::uuid&>(*this); - } - - operator boost::uuids::uuid() const { - return static_cast<boost::uuids::uuid const&>(*this); - } - - UUID& operator= (std::string const & str); - std::string to_s () const; - - operator bool() const { return !is_nil(); } -}; - -} // namespace PBD - -#endif // __pbd_uuid_h__ diff --git a/libs/pbd/pool.cc b/libs/pbd/pool.cc index 7b24625727..cdcd9abdd7 100644 --- a/libs/pbd/pool.cc +++ b/libs/pbd/pool.cc @@ -24,6 +24,7 @@ #include <cassert> #include "pbd/pool.h" +#include "pbd/pthread_utils.h" #include "pbd/error.h" #include "pbd/debug.h" #include "pbd/compose.h" @@ -182,7 +183,7 @@ PerThreadPool::per_thread_pool () { CrossThreadPool* p = _key.get(); if (!p) { - fatal << "programming error: no per-thread pool \"" << _name << "\" for thread " << pthread_self() << endmsg; + fatal << "programming error: no per-thread pool \"" << _name << "\" for thread " << pthread_name() << endmsg; /*NOTREACHED*/ } return p; @@ -226,9 +227,9 @@ CrossThreadPool::alloc () { void* ptr; - DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 has %3 pending free entries waiting\n", pthread_self(), name(), pending.read_space())); + DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 has %3 pending free entries waiting\n", pthread_name(), name(), pending.read_space())); while (pending.read (&ptr, 1) == 1) { - DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 pushes back a pending free list entry before allocating\n", pthread_self(), name())); + DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 pushes back a pending free list entry before allocating\n", pthread_name(), name())); free_list.write (&ptr, 1); } return Pool::alloc (); diff --git a/libs/pbd/pthread_utils.cc b/libs/pbd/pthread_utils.cc index e8b5e2690d..91d93ec4f8 100644 --- a/libs/pbd/pthread_utils.cc +++ b/libs/pbd/pthread_utils.cc @@ -28,9 +28,17 @@ #include <fst.h> #endif +#ifdef COMPILER_MSVC +DECLARE_DEFAULT_COMPARISONS(pthread_t) // Needed for 'DECLARE_DEFAULT_COMPARISONS'. Objects in an STL container can be + // searched and sorted. Thus, when instantiating the container, MSVC complains + // if the type of object being contained has no appropriate comparison operators + // defined (specifically, if operators '<' and '==' are undefined). This seems + // to be the case with ptw32 'pthread_t' which is a simple struct. +#endif + using namespace std; -typedef std::set<pthread_t> ThreadMap; +typedef std::list<pthread_t> ThreadMap; static ThreadMap all_threads; static pthread_mutex_t thread_map_lock = PTHREAD_MUTEX_INITIALIZER; static Glib::Threads::Private<char> thread_name (free); @@ -94,7 +102,7 @@ pthread_create_and_store (string name, pthread_t *thread, void * (*start_routin if ((ret = thread_creator (thread, &default_attr, fake_thread_start, ts)) == 0) { pthread_mutex_lock (&thread_map_lock); - all_threads.insert (*thread); + all_threads.push_back (*thread); pthread_mutex_unlock (&thread_map_lock); } @@ -127,7 +135,7 @@ pthread_kill_all (int signum) { pthread_mutex_lock (&thread_map_lock); for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) { - if ((*i) != pthread_self()) { + if (!pthread_equal ((*i), pthread_self())) { pthread_kill ((*i), signum); } } @@ -140,7 +148,7 @@ pthread_cancel_all () { pthread_mutex_lock (&thread_map_lock); for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) { - if ((*i) != pthread_self()) { + if (!pthread_equal ((*i), pthread_self())) { pthread_cancel ((*i)); } } @@ -153,7 +161,7 @@ pthread_cancel_one (pthread_t thread) { pthread_mutex_lock (&thread_map_lock); for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) { - if ((*i) == thread) { + if (pthread_equal ((*i), thread)) { all_threads.erase (i); break; } @@ -170,7 +178,7 @@ pthread_exit_pbd (void* status) pthread_mutex_lock (&thread_map_lock); for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) { - if ((*i) == thread) { + if (pthread_equal ((*i), thread)) { all_threads.erase (i); break; } diff --git a/libs/pbd/resource.cc b/libs/pbd/resource.cc new file mode 100644 index 0000000000..9d6f8b1746 --- /dev/null +++ b/libs/pbd/resource.cc @@ -0,0 +1,77 @@ +/* + 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 PLATFORM_WINDOWS +#include <stdio.h> +#else +#include <sys/time.h> +#include <sys/resource.h> +#endif + +#include "pbd/resource.h" + +namespace PBD { + +bool +get_resource_limit (ResourceType resource, ResourceLimit& limit) +{ + if (resource == OpenFiles) + { +#ifdef PLATFORM_WINDOWS + limit.current_limit = _getmaxstdio(); + limit.max_limit = 2048; + return true; +#else + struct rlimit rl; + if (getrlimit (RLIMIT_NOFILE, &rl) == 0) { + limit.current_limit = rl.rlim_cur; + limit.max_limit = rl.rlim_max; + return true; + } +#endif + } + + return false; +} + +bool +set_resource_limit (ResourceType resource, const ResourceLimit& limit) +{ + if (resource == OpenFiles) + { +#ifdef PLATFORM_WINDOWS + // no soft and hard limits on windows + rlimit_t new_max = _setmaxstdio(limit.current_limit); + + if (new_max == limit.current_limit) return true; +#else + struct rlimit rl; + rl.rlim_cur = limit.current_limit; + rl.rlim_max = limit.max_limit; + if (setrlimit (RLIMIT_NOFILE, &rl) == 0) { + return true; + } + +#endif + } + + return false; +} + +} // namespace PBD diff --git a/libs/pbd/search_path.cc b/libs/pbd/search_path.cc index 3f7be5aa56..e56e22fee3 100644 --- a/libs/pbd/search_path.cc +++ b/libs/pbd/search_path.cc @@ -27,7 +27,7 @@ using namespace std; namespace { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS const char * const path_delimiter = ";"; #else const char * const path_delimiter = ":"; diff --git a/libs/pbd/semutils.cc b/libs/pbd/semutils.cc index 9ac5f60d35..e5e5898218 100644 --- a/libs/pbd/semutils.cc +++ b/libs/pbd/semutils.cc @@ -23,7 +23,12 @@ using namespace PBD; ProcessSemaphore::ProcessSemaphore (const char* name, int val) { -#ifdef __APPLE__ +#ifdef PLATFORM_WINDOWS + if ((_sem = CreateSemaphore(NULL, val, 32767, name)) == NULL) { + throw failed_constructor (); + } + +#elif __APPLE__ if ((_sem = sem_open (name, O_CREAT, 0600, val)) == (sem_t*) SEM_FAILED) { throw failed_constructor (); } @@ -43,7 +48,28 @@ ProcessSemaphore::ProcessSemaphore (const char* name, int val) ProcessSemaphore::~ProcessSemaphore () { -#ifdef __APPLE__ +#ifdef PLATFORM_WINDOWS + CloseHandle(_sem); +#elif __APPLE__ sem_close (ptr_to_sem()); #endif } + +#ifdef PLATFORM_WINDOWS + +int +ProcessSemaphore::signal () +{ + // non-zero on success, opposite to posix + return !ReleaseSemaphore(_sem, 1, NULL); +} + +int +ProcessSemaphore::wait () +{ + DWORD result = 0; + result = WaitForSingleObject(_sem, INFINITE); + return (result == WAIT_OBJECT_0); +} + +#endif diff --git a/libs/pbd/sndfile_manager.cc b/libs/pbd/sndfile_manager.cc index d1dcd05256..c028bc11ba 100644 --- a/libs/pbd/sndfile_manager.cc +++ b/libs/pbd/sndfile_manager.cc @@ -22,7 +22,6 @@ */ #include <sys/time.h> -#include <sys/resource.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> diff --git a/libs/pbd/stateful.cc b/libs/pbd/stateful.cc index 105af75861..c4077f60af 100644 --- a/libs/pbd/stateful.cc +++ b/libs/pbd/stateful.cc @@ -18,7 +18,11 @@ $Id: stateful.cc 629 2006-06-21 23:01:03Z paul $ */ +#ifdef COMPILER_MSVC +#include <io.h> // Microsoft's nearest equivalent to <unistd.h> +#else #include <unistd.h> +#endif #include <glibmm/fileutils.h> #include <glibmm/miscutils.h> diff --git a/libs/pbd/test/filesystem_test.cc b/libs/pbd/test/filesystem_test.cc index ce2faadc82..458105d177 100644 --- a/libs/pbd/test/filesystem_test.cc +++ b/libs/pbd/test/filesystem_test.cc @@ -10,6 +10,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION (FilesystemTest); void FilesystemTest::testPathIsWithin () { +#ifndef PLATFORM_WINDOWS system ("rm -r foo"); CPPUNIT_ASSERT (g_mkdir_with_parents ("foo/bar/baz", 0755) == 0); @@ -31,5 +32,6 @@ FilesystemTest::testPathIsWithin () CPPUNIT_ASSERT (PBD::path_is_within ("foo/bar", "foo/bar")); CPPUNIT_ASSERT (PBD::path_is_within ("foo/jim/baz", "frobozz") == false); +#endif } diff --git a/libs/pbd/test/mutex_test.cc b/libs/pbd/test/mutex_test.cc new file mode 100644 index 0000000000..52c36c4695 --- /dev/null +++ b/libs/pbd/test/mutex_test.cc @@ -0,0 +1,24 @@ +#include "mutex_test.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (MutexTest); + +using namespace std; + +MutexTest::MutexTest () +{ +} + +void +MutexTest::testBasic () +{ + Glib::Threads::Mutex::Lock lm (m_mutex); + + CPPUNIT_ASSERT (lm.locked()); + + /* This will fail on POSIX systems but not on some older versions of glib + * on win32 as TryEnterCriticalSection is used and it will return true + * as CriticalSection is reentrant and fail the assertion. + */ + CPPUNIT_ASSERT (!m_mutex.trylock()); + +} diff --git a/libs/pbd/test/mutex_test.h b/libs/pbd/test/mutex_test.h new file mode 100644 index 0000000000..95b6ea3f65 --- /dev/null +++ b/libs/pbd/test/mutex_test.h @@ -0,0 +1,17 @@ +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include "glibmm/threads.h" + +class MutexTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE (MutexTest); + CPPUNIT_TEST (testBasic); + CPPUNIT_TEST_SUITE_END (); + +public: + MutexTest (); + void testBasic (); + +private: + Glib::Threads::Mutex m_mutex; +}; diff --git a/libs/pbd/test/test_common.cc b/libs/pbd/test/test_common.cc index 16da3ed2a8..397a69ad8c 100644 --- a/libs/pbd/test/test_common.cc +++ b/libs/pbd/test/test_common.cc @@ -28,7 +28,7 @@ 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, "pbd_testdata"); #else diff --git a/libs/pbd/test/testrunner.cc b/libs/pbd/test/testrunner.cc index 1512ebd024..ea8f0aa115 100644 --- a/libs/pbd/test/testrunner.cc +++ b/libs/pbd/test/testrunner.cc @@ -4,11 +4,15 @@ #include <cppunit/TestResultCollector.h> #include <cppunit/TestRunner.h> #include <cppunit/BriefTestProgressListener.h> +#include <glibmm/thread.h> #include "scalar_properties.h" + int main () { + Glib::thread_init(); + ScalarPropertiesTest::make_property_quarks (); CppUnit::TestResult testresult; diff --git a/libs/pbd/transmitter.cc b/libs/pbd/transmitter.cc index aa5c75da19..e4266d34d7 100644 --- a/libs/pbd/transmitter.cc +++ b/libs/pbd/transmitter.cc @@ -84,12 +84,20 @@ Transmitter::deliver () /* do the right thing if this should not return */ if (does_not_return()) { +#ifndef PLATFORM_WINDOWS +// TODO !!!! Commented out temporarily (for Windows) sigset_t mask; sigemptyset (&mask); sigsuspend (&mask); /*NOTREACHED*/ exit (1); +/* JE - From what I can tell, the above code suspends + * program execution until (any) signal occurs. Not + * sure at the moment what this achieves, unless it + * provides some time for the user to see the message. + */ +#endif } } diff --git a/libs/pbd/uuid.cc b/libs/pbd/uuid.cc index 0ffeca23cb..8b55ab3381 100644 --- a/libs/pbd/uuid.cc +++ b/libs/pbd/uuid.cc @@ -20,19 +20,16 @@ #include "pbd/uuid.h" -using namespace PBD; - -UUID& -UUID::operator= (std::string const & str) +PBD::UUID& +PBD::UUID::operator= (std::string const & str) { - uuid_parse (str.c_str(), id); + boost::uuids::string_generator gen; + *((boost::uuids::uuid*) this) = gen (str); return *this; } std::string -UUID::to_s () const +PBD::UUID::to_s () const { - char buf[37]; - uuid_unparse (id, buf); - return std::string (buf); + return std::string ((const char*) data, size()); } diff --git a/libs/pbd/wscript b/libs/pbd/wscript index 5c8ed194a8..e26b96ca11 100644 --- a/libs/pbd/wscript +++ b/libs/pbd/wscript @@ -38,7 +38,6 @@ libpbd_sources = [ 'controllable.cc', 'controllable_descriptor.cc', 'clear_dir.cc', - 'crossthread.cc', 'cpus.cc', 'debug.cc', 'enumwriter.cc', @@ -46,11 +45,14 @@ libpbd_sources = [ 'enums.cc', 'epa.cc', 'error.cc', + 'ffs.cc', 'file_manager.cc', 'file_utils.cc', 'fpu.cc', + 'glib_semaphore.cc', 'id.cc', 'locale_guard.cc', + 'localtime_r.cc', 'malign.cc', 'mountpoint.cc', 'openuri.cc', @@ -60,6 +62,7 @@ libpbd_sources = [ 'property_list.cc', 'pthread_utils.cc', 'receiver.cc', + 'resource.cc', 'search_path.cc', 'semutils.cc', 'shortpath.cc', @@ -89,20 +92,18 @@ def configure(conf): autowaf.configure(conf) autowaf.check_pkg(conf, 'libxml-2.0', uselib_store='XML') autowaf.check_pkg(conf, 'sigc++-2.0', uselib_store='SIGCPP', atleast_version='2.0') - if sys.platform != 'darwin': - autowaf.check_pkg(conf, 'uuid', uselib_store='UUID') conf.check(function_name='getmntent', header_name='mntent.h', define_name='HAVE_GETMNTENT',mandatory=False) conf.check(header_name='execinfo.h', define_name='HAVE_EXECINFO',mandatory=False) conf.check(header_name='unistd.h', define_name='HAVE_UNISTD',mandatory=False) conf.check_cc(function_name='posix_memalign', header_name='stdlib.h', cflags='-D_XOPEN_SOURCE=600', define_name='HAVE_POSIX_MEMALIGN', mandatory=False) + conf.check(function_name='localtime_r', header_name='time.h', define_name='HAVE_LOCALTIME_R',mandatory=False) conf.write_config_header('libpbd-config.h', remove=False) # Boost headers autowaf.check_header(conf, 'cxx', 'boost/shared_ptr.hpp') autowaf.check_header(conf, 'cxx', 'boost/weak_ptr.hpp') - # autowaf.check_header(conf, 'cxx', 'boost/uuid/uuid.hpp') def build(bld): @@ -121,6 +122,9 @@ def build(bld): if bld.is_defined('DEBUG_RT_ALLOC'): obj.source += 'debug_rt_alloc.c' + if bld.env['build_target'] != 'mingw': + obj.source += [ 'crossthread.cc' ] + obj.export_includes = ['.'] obj.includes = ['.'] obj.name = 'libpbd' @@ -143,6 +147,7 @@ def build(bld): testobj.source = ''' test/testrunner.cc test/xpath.cc + test/mutex_test.cc test/scalar_properties.cc test/signals_test.cc test/convert_test.cc @@ -154,7 +159,7 @@ def build(bld): testobj.uselib = 'CPPUNIT XML SNDFILE' testobj.use = 'libpbd' testobj.name = 'libpbd-tests' - if sys.platform != 'darwin': + if sys.platform != 'darwin' and bld.env['build_target'] != 'mingw': testobj.linkflags = ['-lrt'] diff --git a/libs/pbd/xml++.cc b/libs/pbd/xml++.cc index a1fa77db66..69187995a1 100644 --- a/libs/pbd/xml++.cc +++ b/libs/pbd/xml++.cc @@ -167,6 +167,7 @@ XMLTree::write() const void XMLTree::debug(FILE* out) const { +#ifdef LIBXML_DEBUG_ENABLED xmlDocPtr doc; XMLNodeList children; @@ -176,6 +177,7 @@ XMLTree::debug(FILE* out) const writenode(doc, _root, doc->children, 1); xmlDebugDumpDocument (out, doc); xmlFreeDoc(doc); +#endif } const string& diff --git a/libs/qm-dsp/dsp/wavelet/Wavelet.cpp b/libs/qm-dsp/dsp/wavelet/Wavelet.cpp index 504090528c..ef792460dd 100644 --- a/libs/qm-dsp/dsp/wavelet/Wavelet.cpp +++ b/libs/qm-dsp/dsp/wavelet/Wavelet.cpp @@ -13,6 +13,10 @@ COPYING included with this distribution for more information. */ +#ifdef COMPILER_MSVC +#pragma warning(disable:4305) +#endif + #include "Wavelet.h" #include <cassert> diff --git a/libs/rubberband/rubberband/msvc_rubberband.h b/libs/rubberband/rubberband/msvc_rubberband.h new file mode 100644 index 0000000000..e17cc8ed6f --- /dev/null +++ b/libs/rubberband/rubberband/msvc_rubberband.h @@ -0,0 +1,88 @@ +/* + 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_rubberband_h__ +#define __msvc_rubberband_h__ + +#ifdef RUBBERBAND_IS_IN_WIN_STATIC_LIB // #define if your project uses librubberband (under Windows) as a static library +#define RUBBERBAND_IS_IN_WINDLL 0 +#endif + +#if !defined(RUBBERBAND_IS_IN_WINDLL) + #if defined(_MSC_VER) || defined(__MINGW__) || defined(_MINGW32__) + // If you need '__declspec' compatibility, add extra compilers to the above as necessary + #define RUBBERBAND_IS_IN_WINDLL 1 + #else + #define RUBBERBAND_IS_IN_WINDLL 0 + #endif +#endif + +#if RUBBERBAND_IS_IN_WINDLL && !defined(RUBBERBAND_API) + #if defined(BUILDING_RUBBERBAND) + #define RUBBERBAND_API __declspec(dllexport) + #define RUBBERBAND_APICALLTYPE __stdcall + #elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MINGW32__) + #define RUBBERBAND_API __declspec(dllimport) + #define RUBBERBAND_APICALLTYPE __stdcall + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#elif !defined(RUBBERBAND_API) + // Other compilers / platforms could be accommodated here + #define RUBBERBAND_API + #define RUBBERBAND_APICALLTYPE + #define GETOPT_API + #define GETOPT_APICALLTYPE +#endif + +#ifndef GETOPT_API + #if defined(BUILDING_GETOPT) + #define GETOPT_API __declspec(dllexport) + #define GETOPT_APICALLTYPE __cdecl + #elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MINGW32__) + #define GETOPT_API __declspec(dllimport) + #define GETOPT_APICALLTYPE __cdecl + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#endif // GETOPT_API + +#ifdef _MSC_VER +#include <rpc.h> + +#ifndef __THROW +#define __THROW throw() +#endif + +namespace RubberBand { + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// These are used to replicate 'dirent.h' functionality +// RUBBERBAND_API int RUBBERBAND_APICALLTYPE placeholder(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +} // namespace Rubberband + +#endif // _MSC_VER +#endif // __msvc_rubberband_h__ diff --git a/libs/rubberband/src/Profiler.h b/libs/rubberband/src/Profiler.h index 616a553ecb..d6897b817b 100644 --- a/libs/rubberband/src/Profiler.h +++ b/libs/rubberband/src/Profiler.h @@ -31,7 +31,7 @@ #include <time.h> #else #include "sysutils.h" -#ifndef _WIN32 +#ifndef PLATFORM_WINDOWS #include <sys/time.h> #endif #endif diff --git a/libs/rubberband/src/RingBuffer.h b/libs/rubberband/src/RingBuffer.h index 07312169a6..a9262c8cdc 100644 --- a/libs/rubberband/src/RingBuffer.h +++ b/libs/rubberband/src/RingBuffer.h @@ -20,7 +20,7 @@ #include <cstring> -#ifndef _WIN32 +#ifndef PLATFORM_WINDOWS #include <sys/mman.h> #endif @@ -30,7 +30,7 @@ //#define DEBUG_RINGBUFFER 1 -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS #define MLOCK(a,b) 1 #define MUNLOCK(a,b) 1 #else diff --git a/libs/rubberband/src/Scavenger.h b/libs/rubberband/src/Scavenger.h index d1b6ca9ffa..a922d7ec6e 100644 --- a/libs/rubberband/src/Scavenger.h +++ b/libs/rubberband/src/Scavenger.h @@ -19,7 +19,7 @@ #include <list> #include <iostream> -#ifndef WIN32 +#ifndef PLATFORM_WINDOWS #include <sys/time.h> #endif diff --git a/libs/rubberband/src/StretchCalculator.cpp b/libs/rubberband/src/StretchCalculator.cpp index 1541759762..18ee9cc9c3 100644 --- a/libs/rubberband/src/StretchCalculator.cpp +++ b/libs/rubberband/src/StretchCalculator.cpp @@ -12,6 +12,9 @@ COPYING included with this distribution for more information. */ +#ifdef COMPILER_MSVC +#include "bsd-3rdparty/float_cast/float_cast.h" +#endif #include "StretchCalculator.h" #include <algorithm> diff --git a/libs/rubberband/src/StretcherImpl.cpp b/libs/rubberband/src/StretcherImpl.cpp index 200c8771a8..d15a71d68e 100644 --- a/libs/rubberband/src/StretcherImpl.cpp +++ b/libs/rubberband/src/StretcherImpl.cpp @@ -12,6 +12,9 @@ COPYING included with this distribution for more information. */ +#ifdef COMPILER_MSVC +#include "bsd-3rdparty/float_cast/float_cast.h" +#endif #include "StretcherImpl.h" #include "PercussiveAudioCurve.h" #include "HighFrequencyAudioCurve.h" diff --git a/libs/rubberband/src/Thread.cpp b/libs/rubberband/src/Thread.cpp index 49f75b5b65..d5a7b2f6ff 100644 --- a/libs/rubberband/src/Thread.cpp +++ b/libs/rubberband/src/Thread.cpp @@ -16,11 +16,11 @@ #include <cstdlib> #include <iostream> -#include <cstdlib> -#include <cstdlib> +#ifndef COMPILER_MSVC #include <sys/time.h> #include <time.h> +#endif using std::cerr; using std::endl; @@ -29,7 +29,7 @@ using std::string; namespace RubberBand { -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS Thread::Thread() : m_id(0), @@ -289,7 +289,7 @@ Condition::signal() SetEvent(m_condition); } -#else /* !_WIN32 */ +#else /* !PLATFORM_WINDOWS */ Thread::Thread() : @@ -562,7 +562,7 @@ Condition::signal() pthread_cond_signal(&m_condition); } -#endif /* !_WIN32 */ +#endif /* !PLATFORM_WINDOWS */ MutexLocker::MutexLocker(Mutex *mutex) : m_mutex(mutex) diff --git a/libs/rubberband/src/Thread.h b/libs/rubberband/src/Thread.h index 061469297e..63a5a65b67 100644 --- a/libs/rubberband/src/Thread.h +++ b/libs/rubberband/src/Thread.h @@ -15,11 +15,11 @@ #ifndef _RUBBERBAND_THREAD_H_ #define _RUBBERBAND_THREAD_H_ -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS #include <windows.h> -#else /* !_WIN32 */ +#else /* !PLATFORM_WINDOWS */ #include <pthread.h> -#endif /* !_WIN32 */ +#endif /* !PLATFORM_WINDOWS */ #include <string> @@ -33,7 +33,7 @@ namespace RubberBand class Thread { public: -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS typedef HANDLE Id; #else typedef pthread_t Id; @@ -53,7 +53,7 @@ protected: virtual void run() = 0; private: -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS HANDLE m_id; bool m_extant; static DWORD WINAPI staticRun(LPVOID lpParam); @@ -75,7 +75,7 @@ public: bool trylock(); private: -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS HANDLE m_mutex; #ifndef NO_THREAD_CHECKS DWORD m_lockedBy; @@ -123,7 +123,7 @@ public: private: -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS HANDLE m_mutex; HANDLE m_condition; bool m_locked; diff --git a/libs/rubberband/src/bsd-3rdparty/float_cast/float_cast.h b/libs/rubberband/src/bsd-3rdparty/float_cast/float_cast.h index 1ba0e03bdc..0e3d8a4040 100644 --- a/libs/rubberband/src/bsd-3rdparty/float_cast/float_cast.h +++ b/libs/rubberband/src/bsd-3rdparty/float_cast/float_cast.h @@ -35,6 +35,9 @@ ** long int lrint (double x) ; */ +#ifndef __FLOAT_CAST_H__ // Added by JE - 30-11-2009 +#define __FLOAT_CAST_H__ + #if (defined (WIN32) || defined (_WIN32)) #include <math.h> @@ -69,5 +72,5 @@ #endif - +#endif // __FLOAT_CAST_H__ diff --git a/libs/rubberband/src/main.cpp b/libs/rubberband/src/main.cpp index 1c80696180..cdc62e8afa 100644 --- a/libs/rubberband/src/main.cpp +++ b/libs/rubberband/src/main.cpp @@ -23,7 +23,7 @@ #include <cstring> #include "sysutils.h" -#ifdef __MSVC__ +#ifdef COMPILER_MSVC #include "bsd-3rdparty/getopt/getopt.h" #else #include <getopt.h> @@ -36,7 +36,7 @@ using namespace std; using namespace RubberBand; -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS using RubberBand::gettimeofday; using RubberBand::usleep; #endif @@ -324,7 +324,7 @@ int main(int argc, char **argv) cerr << "Using time ratio " << ratio; cerr << " and frequency ratio " << frequencyshift << endl; -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS RubberBand:: #endif timeval tv; @@ -495,7 +495,11 @@ int main(int argc, char **argv) } delete[] obf; } else { +#ifdef PLATFORM_WINDOWS + RubberBand::usleep(10000); +#else usleep(10000); +#endif } } @@ -506,7 +510,7 @@ int main(int argc, char **argv) cerr << "in: " << countIn << ", out: " << countOut << ", ratio: " << float(countOut)/float(countIn) << ", ideal output: " << lrint(countIn * ratio) << ", error: " << abs(lrint(countIn * ratio) - int(countOut)) << endl; -#ifdef _WIN32 +#ifdef PLATFORM_WINDOWS RubberBand:: #endif timeval etv; diff --git a/libs/rubberband/src/sysutils.h b/libs/rubberband/src/sysutils.h index a529afde0d..3883c59ff5 100644 --- a/libs/rubberband/src/sysutils.h +++ b/libs/rubberband/src/sysutils.h @@ -15,7 +15,7 @@ #ifndef _RUBBERBAND_SYSINFO_H_ #define _RUBBERBAND_SYSINFO_H_ -#ifdef __MSVC__ +#ifdef COMPILER_MSVC #include "bsd-3rdparty/float_cast/float_cast.h" #define R__ __restrict #endif @@ -28,11 +28,11 @@ #define R__ #endif -#ifdef __MINGW32__ +#ifdef COMPILER_MINGW #include <malloc.h> #endif -#ifdef __MSVC__ +#ifdef COMPILER_MSVC #define alloca _alloca #endif diff --git a/libs/surfaces/frontier/kernel_drivers/tranzport.c b/libs/surfaces/frontier/kernel_drivers/tranzport.c index 6893f66921..b7b6709d56 100644 --- a/libs/surfaces/frontier/kernel_drivers/tranzport.c +++ b/libs/surfaces/frontier/kernel_drivers/tranzport.c @@ -445,7 +445,7 @@ static void usb_tranzport_interrupt_out_callback(struct urb *urb) { struct usb_tranzport *dev = urb->context; - /* sync/async unlink faults aren't errors */ + /* sync/async ::g_unlink faults aren't errors */ if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 0c7c8455a4..8b57dc0c3e 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -28,6 +28,7 @@ #include <unistd.h> #include <fcntl.h> +#include <glib/gstdio.h> #include <glibmm/miscutils.h> #include <pbd/pthread_utils.h> @@ -181,7 +182,7 @@ OSC::start () int fd = mkstemp(tmpstr); if (fd >= 0 ) { - unlink (tmpstr); + ::g_unlink (tmpstr); close (fd); _osc_unix_server = lo_server_new (tmpstr, error_callback); @@ -284,11 +285,11 @@ OSC::stop () } if (!_osc_unix_socket_path.empty()) { - unlink (_osc_unix_socket_path.c_str()); + ::g_unlink (_osc_unix_socket_path.c_str()); } if (!_osc_url_file.empty() ) { - unlink (_osc_url_file.c_str() ); + ::g_unlink (_osc_url_file.c_str() ); } // Delete any active route observers diff --git a/libs/surfaces/wscript b/libs/surfaces/wscript index 3a4b562629..335d14ee87 100644 --- a/libs/surfaces/wscript +++ b/libs/surfaces/wscript @@ -23,10 +23,6 @@ children = [ 'control_protocol', 'frontier', 'generic_midi', - 'mackie', - 'osc', - 'tranzport', - 'wiimote' ] def options(opt): @@ -39,22 +35,29 @@ def sub_config_and_use(conf, name, has_objects = True): def configure(conf): autowaf.set_recursive() autowaf.configure(conf) - + for i in children: sub_config_and_use(conf, i) + if (conf.env['build_target'] == 'mingw'): return + #autowaf.check_pkg(conf, 'libusb-1.0', uselib_store='USB', mandatory=False) #if Options.options.tranzport and conf.is_defined('HAVE_USB'): # conf.define('BUILD_TRANZPORT', 1) - autowaf.check_pkg (conf, 'liblo', mandatory=False, uselib_store="LO", atleast_version="0.24") - + if conf.check_cc (header_name='poll.h', define_name='BUILD_MACKIE', mandatory=False): + sub_config_and_use(conf, 'mackie') + + if autowaf.check_pkg (conf, 'liblo', mandatory=False, uselib_store="LO", atleast_version="0.24"): + sub_config_and_use(conf, 'osc') + conf.check_cc (header_name='cwiid.h', define_name='HAVE_CWIID_H',mandatory=False) if conf.is_defined('HAVE_CWIID_H'): conf.check_cc (header_name='bluetooth/bluetooth.h', define_name='HAVE_BLUETOOTH_H',mandatory=False) if conf.is_defined('HAVE_BLUETOOTH_H'): autowaf.check_pkg(conf, 'cwiid', uselib_store='CWIID', atleast_version='0.6.00') conf.define ('BUILD_WIIMOTE', 1) + sub_config_and_use(conf, 'wiimote') else: print('You are missing the libbluetooth headers needed to compile wiimote support') else: @@ -62,8 +65,9 @@ def configure(conf): def build(bld): bld.recurse('control_protocol') - bld.recurse('generic_midi') - bld.recurse('mackie') + if (bld.env['build_target'] == 'mingw'): return + if bld.is_defined ('BUILD_MACKIE'): + bld.recurse('mackie') if bld.is_defined ('HAVE_LO'): bld.recurse('osc') if bld.is_defined('BUILD_WIIMOTE'): diff --git a/libs/taglib/taglib/apefooter.h b/libs/taglib/taglib/apefooter.h deleted file mode 120000 index 4478ae1861..0000000000 --- a/libs/taglib/taglib/apefooter.h +++ /dev/null @@ -1 +0,0 @@ -./ape/apefooter.h
\ No newline at end of file diff --git a/libs/taglib/taglib/apeitem.h b/libs/taglib/taglib/apeitem.h deleted file mode 120000 index 4b5757ca25..0000000000 --- a/libs/taglib/taglib/apeitem.h +++ /dev/null @@ -1 +0,0 @@ -./ape/apeitem.h
\ No newline at end of file diff --git a/libs/taglib/taglib/apetag.h b/libs/taglib/taglib/apetag.h deleted file mode 120000 index 6e08d878ca..0000000000 --- a/libs/taglib/taglib/apetag.h +++ /dev/null @@ -1 +0,0 @@ -./ape/apetag.h
\ No newline at end of file diff --git a/libs/taglib/taglib/attachedpictureframe.h b/libs/taglib/taglib/attachedpictureframe.h deleted file mode 120000 index f48f568c55..0000000000 --- a/libs/taglib/taglib/attachedpictureframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/attachedpictureframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/commentsframe.h b/libs/taglib/taglib/commentsframe.h deleted file mode 120000 index 54c9c1d848..0000000000 --- a/libs/taglib/taglib/commentsframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/commentsframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/flacfile.h b/libs/taglib/taglib/flacfile.h deleted file mode 120000 index 163f8fe06b..0000000000 --- a/libs/taglib/taglib/flacfile.h +++ /dev/null @@ -1 +0,0 @@ -./flac/flacfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/flacproperties.h b/libs/taglib/taglib/flacproperties.h deleted file mode 120000 index 3f2524267c..0000000000 --- a/libs/taglib/taglib/flacproperties.h +++ /dev/null @@ -1 +0,0 @@ -./flac/flacproperties.h
\ No newline at end of file diff --git a/libs/taglib/taglib/generalencapsulatedobjectframe.h b/libs/taglib/taglib/generalencapsulatedobjectframe.h deleted file mode 120000 index dbb35ace6a..0000000000 --- a/libs/taglib/taglib/generalencapsulatedobjectframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/generalencapsulatedobjectframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v1genres.h b/libs/taglib/taglib/id3v1genres.h deleted file mode 120000 index a6e5fa27d5..0000000000 --- a/libs/taglib/taglib/id3v1genres.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v1/id3v1genres.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v1tag.h b/libs/taglib/taglib/id3v1tag.h deleted file mode 120000 index 0843ca4c7b..0000000000 --- a/libs/taglib/taglib/id3v1tag.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v1/id3v1tag.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v2extendedheader.h b/libs/taglib/taglib/id3v2extendedheader.h deleted file mode 120000 index ce495056cf..0000000000 --- a/libs/taglib/taglib/id3v2extendedheader.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/id3v2extendedheader.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v2footer.h b/libs/taglib/taglib/id3v2footer.h deleted file mode 120000 index ad6745fd9e..0000000000 --- a/libs/taglib/taglib/id3v2footer.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/id3v2footer.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v2frame.h b/libs/taglib/taglib/id3v2frame.h deleted file mode 120000 index cbb258be8c..0000000000 --- a/libs/taglib/taglib/id3v2frame.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/id3v2frame.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v2framefactory.h b/libs/taglib/taglib/id3v2framefactory.h deleted file mode 120000 index 32fcfab860..0000000000 --- a/libs/taglib/taglib/id3v2framefactory.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/id3v2framefactory.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v2header.h b/libs/taglib/taglib/id3v2header.h deleted file mode 120000 index 90639420a4..0000000000 --- a/libs/taglib/taglib/id3v2header.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/id3v2header.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v2synchdata.h b/libs/taglib/taglib/id3v2synchdata.h deleted file mode 120000 index 45374981b4..0000000000 --- a/libs/taglib/taglib/id3v2synchdata.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/id3v2synchdata.h
\ No newline at end of file diff --git a/libs/taglib/taglib/id3v2tag.h b/libs/taglib/taglib/id3v2tag.h deleted file mode 120000 index e9b6219657..0000000000 --- a/libs/taglib/taglib/id3v2tag.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/id3v2tag.h
\ No newline at end of file diff --git a/libs/taglib/taglib/mpcfile.h b/libs/taglib/taglib/mpcfile.h deleted file mode 120000 index 3f31e3d713..0000000000 --- a/libs/taglib/taglib/mpcfile.h +++ /dev/null @@ -1 +0,0 @@ -./mpc/mpcfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/mpcproperties.h b/libs/taglib/taglib/mpcproperties.h deleted file mode 120000 index 81f0916dfc..0000000000 --- a/libs/taglib/taglib/mpcproperties.h +++ /dev/null @@ -1 +0,0 @@ -./mpc/mpcproperties.h
\ No newline at end of file diff --git a/libs/taglib/taglib/mpegfile.h b/libs/taglib/taglib/mpegfile.h deleted file mode 120000 index 9906423f74..0000000000 --- a/libs/taglib/taglib/mpegfile.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/mpegfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/mpegheader.h b/libs/taglib/taglib/mpegheader.h deleted file mode 120000 index beb79d9d17..0000000000 --- a/libs/taglib/taglib/mpegheader.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/mpegheader.h
\ No newline at end of file diff --git a/libs/taglib/taglib/mpegproperties.h b/libs/taglib/taglib/mpegproperties.h deleted file mode 120000 index ca2391c005..0000000000 --- a/libs/taglib/taglib/mpegproperties.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/mpegproperties.h
\ No newline at end of file diff --git a/libs/taglib/taglib/oggfile.h b/libs/taglib/taglib/oggfile.h deleted file mode 120000 index 629411e4a6..0000000000 --- a/libs/taglib/taglib/oggfile.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/oggfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/oggflacfile.h b/libs/taglib/taglib/oggflacfile.h deleted file mode 120000 index a637866754..0000000000 --- a/libs/taglib/taglib/oggflacfile.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/flac/oggflacfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/oggpage.h b/libs/taglib/taglib/oggpage.h deleted file mode 120000 index c1d996bd86..0000000000 --- a/libs/taglib/taglib/oggpage.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/oggpage.h
\ No newline at end of file diff --git a/libs/taglib/taglib/oggpageheader.h b/libs/taglib/taglib/oggpageheader.h deleted file mode 120000 index 1bb403504c..0000000000 --- a/libs/taglib/taglib/oggpageheader.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/oggpageheader.h
\ No newline at end of file diff --git a/libs/taglib/taglib/relativevolumeframe.h b/libs/taglib/taglib/relativevolumeframe.h deleted file mode 120000 index 98cbd6b46e..0000000000 --- a/libs/taglib/taglib/relativevolumeframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/relativevolumeframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/speexfile.h b/libs/taglib/taglib/speexfile.h deleted file mode 120000 index 69b8223553..0000000000 --- a/libs/taglib/taglib/speexfile.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/speex/speexfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/speexproperties.h b/libs/taglib/taglib/speexproperties.h deleted file mode 120000 index 28b883c1d2..0000000000 --- a/libs/taglib/taglib/speexproperties.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/speex/speexproperties.h
\ No newline at end of file diff --git a/libs/taglib/taglib/taglib.h b/libs/taglib/taglib/taglib.h deleted file mode 120000 index 8a9f286ab9..0000000000 --- a/libs/taglib/taglib/taglib.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/taglib.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tbytevector.h b/libs/taglib/taglib/tbytevector.h deleted file mode 120000 index 2aba448a9c..0000000000 --- a/libs/taglib/taglib/tbytevector.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tbytevector.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tbytevectorlist.h b/libs/taglib/taglib/tbytevectorlist.h deleted file mode 120000 index e2308fae3b..0000000000 --- a/libs/taglib/taglib/tbytevectorlist.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tbytevectorlist.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tdebug.h b/libs/taglib/taglib/tdebug.h deleted file mode 120000 index a27b5c3bc9..0000000000 --- a/libs/taglib/taglib/tdebug.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tdebug.h
\ No newline at end of file diff --git a/libs/taglib/taglib/textidentificationframe.h b/libs/taglib/taglib/textidentificationframe.h deleted file mode 120000 index 4b775ee038..0000000000 --- a/libs/taglib/taglib/textidentificationframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/textidentificationframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tfile.h b/libs/taglib/taglib/tfile.h deleted file mode 120000 index 09d3e52a3a..0000000000 --- a/libs/taglib/taglib/tfile.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tlist.h b/libs/taglib/taglib/tlist.h deleted file mode 120000 index ce60095443..0000000000 --- a/libs/taglib/taglib/tlist.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tlist.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tlist.tcc b/libs/taglib/taglib/tlist.tcc deleted file mode 120000 index 03b9a96362..0000000000 --- a/libs/taglib/taglib/tlist.tcc +++ /dev/null @@ -1 +0,0 @@ -toolkit/tlist.tcc
\ No newline at end of file diff --git a/libs/taglib/taglib/tmap.h b/libs/taglib/taglib/tmap.h deleted file mode 120000 index 7a59378e13..0000000000 --- a/libs/taglib/taglib/tmap.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tmap.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tmap.tcc b/libs/taglib/taglib/tmap.tcc deleted file mode 120000 index c9d4591d7d..0000000000 --- a/libs/taglib/taglib/tmap.tcc +++ /dev/null @@ -1 +0,0 @@ -toolkit/tmap.tcc
\ No newline at end of file diff --git a/libs/taglib/taglib/trueaudiofile.h b/libs/taglib/taglib/trueaudiofile.h deleted file mode 120000 index 7a677f17fd..0000000000 --- a/libs/taglib/taglib/trueaudiofile.h +++ /dev/null @@ -1 +0,0 @@ -./trueaudio/trueaudiofile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/trueaudioproperties.h b/libs/taglib/taglib/trueaudioproperties.h deleted file mode 120000 index 5e7f7d6c37..0000000000 --- a/libs/taglib/taglib/trueaudioproperties.h +++ /dev/null @@ -1 +0,0 @@ -./trueaudio/trueaudioproperties.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tstring.h b/libs/taglib/taglib/tstring.h deleted file mode 120000 index acbe0c80be..0000000000 --- a/libs/taglib/taglib/tstring.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tstring.h
\ No newline at end of file diff --git a/libs/taglib/taglib/tstringlist.h b/libs/taglib/taglib/tstringlist.h deleted file mode 120000 index 918658c425..0000000000 --- a/libs/taglib/taglib/tstringlist.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/tstringlist.h
\ No newline at end of file diff --git a/libs/taglib/taglib/unicode.h b/libs/taglib/taglib/unicode.h deleted file mode 120000 index 30009297b5..0000000000 --- a/libs/taglib/taglib/unicode.h +++ /dev/null @@ -1 +0,0 @@ -./toolkit/unicode.h
\ No newline at end of file diff --git a/libs/taglib/taglib/uniquefileidentifierframe.h b/libs/taglib/taglib/uniquefileidentifierframe.h deleted file mode 120000 index 55b9305b66..0000000000 --- a/libs/taglib/taglib/uniquefileidentifierframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/uniquefileidentifierframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/unknownframe.h b/libs/taglib/taglib/unknownframe.h deleted file mode 120000 index e46996ab13..0000000000 --- a/libs/taglib/taglib/unknownframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/unknownframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/unsynchronizedlyricsframe.h b/libs/taglib/taglib/unsynchronizedlyricsframe.h deleted file mode 120000 index 162a88d26f..0000000000 --- a/libs/taglib/taglib/unsynchronizedlyricsframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/unsynchronizedlyricsframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/urllinkframe.h b/libs/taglib/taglib/urllinkframe.h deleted file mode 120000 index 1e1aa15219..0000000000 --- a/libs/taglib/taglib/urllinkframe.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/id3v2/frames/urllinkframe.h
\ No newline at end of file diff --git a/libs/taglib/taglib/vorbisfile.h b/libs/taglib/taglib/vorbisfile.h deleted file mode 120000 index d5d372bf03..0000000000 --- a/libs/taglib/taglib/vorbisfile.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/vorbis/vorbisfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/vorbisproperties.h b/libs/taglib/taglib/vorbisproperties.h deleted file mode 120000 index e1d36a3f23..0000000000 --- a/libs/taglib/taglib/vorbisproperties.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/vorbis/vorbisproperties.h
\ No newline at end of file diff --git a/libs/taglib/taglib/wavpackfile.h b/libs/taglib/taglib/wavpackfile.h deleted file mode 120000 index c88dd7c45d..0000000000 --- a/libs/taglib/taglib/wavpackfile.h +++ /dev/null @@ -1 +0,0 @@ -./wavpack/wavpackfile.h
\ No newline at end of file diff --git a/libs/taglib/taglib/wavpackproperties.h b/libs/taglib/taglib/wavpackproperties.h deleted file mode 120000 index 089b5b713e..0000000000 --- a/libs/taglib/taglib/wavpackproperties.h +++ /dev/null @@ -1 +0,0 @@ -./wavpack/wavpackproperties.h
\ No newline at end of file diff --git a/libs/taglib/taglib/xingheader.h b/libs/taglib/taglib/xingheader.h deleted file mode 120000 index a2711031ab..0000000000 --- a/libs/taglib/taglib/xingheader.h +++ /dev/null @@ -1 +0,0 @@ -./mpeg/xingheader.h
\ No newline at end of file diff --git a/libs/taglib/taglib/xiphcomment.h b/libs/taglib/taglib/xiphcomment.h deleted file mode 120000 index 96e9483222..0000000000 --- a/libs/taglib/taglib/xiphcomment.h +++ /dev/null @@ -1 +0,0 @@ -./ogg/xiphcomment.h
\ No newline at end of file diff --git a/libs/taglib/wscript b/libs/taglib/wscript index a6994d6391..8e6fbbbe48 100644 --- a/libs/taglib/wscript +++ b/libs/taglib/wscript @@ -65,6 +65,7 @@ def build(bld): '''.split() obj.export_includes = ['.', 'taglib', 'taglib/toolkit'] obj.includes = include_dirs + obj.defines = ['MAKE_TAGLIB_LIB'] obj.name = 'libtaglib' obj.target = 'taglib' obj.vnum = LIBTAGLIB_LIB_VERSION diff --git a/libs/vamp-plugins/Onset.cpp b/libs/vamp-plugins/Onset.cpp index d475b11be9..4a58bf9fa5 100644 --- a/libs/vamp-plugins/Onset.cpp +++ b/libs/vamp-plugins/Onset.cpp @@ -14,6 +14,9 @@ */ +#ifdef COMPILER_MSVC +#include <ardourext/float_cast.h> +#endif #include <math.h> #include "Onset.h" diff --git a/libs/vamp-plugins/OnsetDetect.cpp b/libs/vamp-plugins/OnsetDetect.cpp index 614eb4c943..714eee3647 100644 --- a/libs/vamp-plugins/OnsetDetect.cpp +++ b/libs/vamp-plugins/OnsetDetect.cpp @@ -12,6 +12,9 @@ COPYING included with this distribution for more information. */ +#ifdef COMPILER_MSVC +#include <ardourext/float_cast.h> +#endif #include "OnsetDetect.h" #include "dsp/onsets/DetectionFunction.h" diff --git a/libs/vamp-plugins/PercussionOnsetDetector.cpp b/libs/vamp-plugins/PercussionOnsetDetector.cpp index 447eb19a28..623b89b6a0 100644 --- a/libs/vamp-plugins/PercussionOnsetDetector.cpp +++ b/libs/vamp-plugins/PercussionOnsetDetector.cpp @@ -34,6 +34,9 @@ authorization. */ +#ifdef COMPILER_MSVC +#include <ardourext/float_cast.h> +#endif #include "PercussionOnsetDetector.h" using std::string; diff --git a/libs/vamp-plugins/SpectralCentroid.cpp b/libs/vamp-plugins/SpectralCentroid.cpp index 82d80b8100..f93fdcaa32 100644 --- a/libs/vamp-plugins/SpectralCentroid.cpp +++ b/libs/vamp-plugins/SpectralCentroid.cpp @@ -34,6 +34,19 @@ authorization. */ +#include <cmath> + +#ifdef COMPILER_MSVC +#include <float.h> + +// 'std::isinf()' and 'std::isnan()' are not available in MSVC. +#define isinf(val) !((bool)_finite((double)val)) +#define isnan(val) (bool)_isnan((double)val) +#else +using std::isnan; +using std::isinf; +#endif + #include "SpectralCentroid.h" using std::string; @@ -41,8 +54,6 @@ using std::vector; using std::cerr; using std::endl; -#include <cmath> - SpectralCentroid::SpectralCentroid(float inputSampleRate) : Plugin(inputSampleRate), @@ -165,13 +176,13 @@ SpectralCentroid::process(const float *const *inputBuffers, Vamp::RealTime) Feature feature; feature.hasTimestamp = false; - if (!std::isnan(centroidLog) && !std::isinf(centroidLog)) { + if (!isnan(centroidLog) && !isinf(centroidLog)) { feature.values.push_back(centroidLog); } returnFeatures[0].push_back(feature); feature.values.clear(); - if (!std::isnan(centroidLin) && !std::isinf(centroidLin)) { + if (!isnan(centroidLin) && !isinf(centroidLin)) { feature.values.push_back(centroidLin); } returnFeatures[1].push_back(feature); |