diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2014-01-10 16:07:57 -0500 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2014-01-10 16:07:57 -0500 |
commit | 3020b224fa2d6e1b6b8a576e8e8e211e0585f2a2 (patch) | |
tree | 314c3099bcc57d9af09d249e1e7dd8e45baca642 /libs/pbd | |
parent | d15fda6d751a465d278f477923075d4783f3b1ca (diff) | |
parent | 897fbdc652434d3aa1e67223c3c3ef7ae9be2318 (diff) |
Merge windows+cc branch into cairocanvas branch. Not finished, need to now merge windows branch to get changes from there
Diffstat (limited to 'libs/pbd')
83 files changed, 4232 insertions, 267 deletions
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..c7a1d41b0e 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..f17e69e417 --- /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 +// +LIBPBD_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()' +// +LIBPBD_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. +// +LIBPBD_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..44254989c1 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); } } @@ -94,7 +104,7 @@ find_matching_files_in_directories (const vector<std::string>& paths, } void -find_matching_files_in_search_path (const SearchPath& search_path, +find_matching_files_in_search_path (const Searchpath& search_path, const Glib::PatternSpec& pattern, vector<std::string>& result) { @@ -102,7 +112,7 @@ find_matching_files_in_search_path (const SearchPath& search_path, } bool -find_file_in_search_path(const SearchPath& search_path, +find_file_in_search_path(const Searchpath& search_path, const string& filename, std::string& result) { @@ -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 8929491cd9..73bc7e599d 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..5b9c9d449a --- /dev/null +++ b/libs/pbd/msvc/msvc_pbd.cc @@ -0,0 +1,914 @@ +/* + 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 <math.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 */ +}; + +LIBPBD_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 +LIBPBD_API bool operator> (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::greater<void*>()(lhs.p, rhs.p)); +} + +LIBPBD_API bool operator< (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::less<void*>()(lhs.p, rhs.p)); +} + +LIBPBD_API bool operator!= (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::not_equal_to<void*>()(lhs.p, rhs.p)); +} + +LIBPBD_API 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 +// +LIBPBD_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 +// +LIBPBD_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); +} + +//*************************************************************** +// +// round() +// +// Emulates round() using floor(). +// +// Returns: +// +// On Success: The largest integer that is less than or +// equal to 'x'. +// On Failure: None +// +LIBPBD_API double PBD_APICALLTYPE +round(double x) +{ + return (floor(x)); +} + +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 +// +LIBPBD_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 +// +LIBPBD_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 +// +LIBPBD_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 +// +LIBPBD_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 +// +LIBPBD_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) +// +LIBPBD_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) +// +LIBPBD_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) +// +LIBPBD_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 +// +LIBPBD_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 +// +LIBPBD_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 +// +LIBPBD_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) +// +LIBPBD_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..921638a3f5 --- /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'). +// +LIBPBD_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..67c39b57e4 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(ptw32_handle_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 f78ba26090..1ceefe7b3b 100644 --- a/libs/pbd/pbd/abstract_ui.h +++ b/libs/pbd/pbd/abstract_ui.h @@ -52,7 +52,7 @@ class Touchable; template<typename RequestObject> -class ABSTRACT_UI_API AbstractUI : public BaseUI /* see notes in visibility.h about why this is not LIBPBD_API */ +class /*ABSTRACT_UI_API*/ AbstractUI : public BaseUI /* see notes in visibility.h about why this is not LIBPBD_API */ { public: AbstractUI (const std::string& name); @@ -74,8 +74,22 @@ class ABSTRACT_UI_API AbstractUI : public BaseUI /* see notes in visibility.h ab , 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 ee2bbf5ee9..ea1afbbb5a 100644 --- a/libs/pbd/pbd/base_ui.h +++ b/libs/pbd/pbd/base_ui.h @@ -72,13 +72,13 @@ class LIBPBD_API 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 @@ -93,9 +93,17 @@ class LIBPBD_API 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 @@ -106,6 +114,10 @@ class LIBPBD_API 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/cartesian.h b/libs/pbd/pbd/cartesian.h index 20c8b27088..5f0b951d5f 100644 --- a/libs/pbd/pbd/cartesian.h +++ b/libs/pbd/pbd/cartesian.h @@ -97,7 +97,7 @@ struct LIBPBD_API AngularVector { } }; -LIBPBD_API inline void CartesianVector::angular (AngularVector& a) const { +inline void CartesianVector::angular (AngularVector& a) const { cartesian_to_spherical (x, y, z, a.azi, a.ele, a.length); } diff --git a/libs/pbd/pbd/compose.h b/libs/pbd/pbd/compose.h index a80cb213b2..cb4182699f 100644 --- a/libs/pbd/pbd/compose.h +++ b/libs/pbd/pbd/compose.h @@ -204,7 +204,7 @@ namespace StringPrivate // a series of functions which accept a format string on the form "text %1 // more %2 less %3" and a number of templated parameters and spits out the // composited string - template <typename T1> LIBPBD_API + template <typename T1> inline std::string string_compose(const std::string &fmt, const T1 &o1) { StringPrivate::Composition c(fmt); @@ -212,7 +212,7 @@ namespace StringPrivate return c.str(); } - template <typename T1, typename T2> LIBPBD_API + template <typename T1, typename T2> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2) { @@ -221,7 +221,7 @@ namespace StringPrivate return c.str(); } - template <typename T1, typename T2, typename T3> LIBPBD_API + template <typename T1, typename T2, typename T3> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3) { @@ -230,7 +230,7 @@ namespace StringPrivate return c.str(); } - template <typename T1, typename T2, typename T3, typename T4> LIBPBD_API + template <typename T1, typename T2, typename T3, typename T4> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4) @@ -240,7 +240,7 @@ namespace StringPrivate return c.str(); } - template <typename T1, typename T2, typename T3, typename T4, typename T5> LIBPBD_API + template <typename T1, typename T2, typename T3, typename T4, typename T5> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5) @@ -251,7 +251,7 @@ namespace StringPrivate } template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> LIBPBD_API + typename T6> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6) @@ -262,7 +262,7 @@ namespace StringPrivate } template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7> LIBPBD_API + typename T6, typename T7> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -274,7 +274,7 @@ namespace StringPrivate } template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8> LIBPBD_API + typename T6, typename T7, typename T8> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -286,7 +286,7 @@ namespace StringPrivate } template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9> LIBPBD_API + typename T6, typename T7, typename T8, typename T9> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -298,7 +298,7 @@ namespace StringPrivate } template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, typename T10> LIBPBD_API + typename T6, typename T7, typename T8, typename T9, typename T10> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -313,7 +313,7 @@ namespace StringPrivate template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11> LIBPBD_API + typename T11> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -328,7 +328,7 @@ namespace StringPrivate template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11, typename T12> LIBPBD_API + typename T11, typename T12> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -343,7 +343,7 @@ namespace StringPrivate template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11, typename T12, typename T13> LIBPBD_API + typename T11, typename T12, typename T13> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -359,7 +359,7 @@ namespace StringPrivate template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11, typename T12, typename T13, typename T14> LIBPBD_API + typename T11, typename T12, typename T13, typename T14> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, @@ -376,7 +376,7 @@ namespace StringPrivate template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, - typename T15> LIBPBD_API + typename T15> inline std::string string_compose(const std::string &fmt, const T1 &o1, const T2 &o2, const T3 &o3, const T4 &o4, const T5 &o5, const T6 &o6, diff --git a/libs/pbd/pbd/convert.h b/libs/pbd/pbd/convert.h index 1269254906..6580a6e8e7 100644 --- a/libs/pbd/pbd/convert.h +++ b/libs/pbd/pbd/convert.h @@ -47,7 +47,7 @@ LIBPBD_API std::string length2string (const int64_t frames, const double sample_ LIBPBD_API std::vector<std::string> internationalize (const char *, const char **); LIBPBD_API bool strings_equal_ignore_case (const std::string& a, const std::string& b); -template <class T> std::string LIBPBD_API +template <class T> std::string /*LIBPBD_API*/ to_string (T t, std::ios_base & (*f)(std::ios_base&)) { std::ostringstream oss; diff --git a/libs/pbd/pbd/debug.h b/libs/pbd/pbd/debug.h index dc7e1ce906..54577f1a7e 100644 --- a/libs/pbd/pbd/debug.h +++ b/libs/pbd/pbd/debug.h @@ -45,6 +45,7 @@ namespace PBD { LIBPBD_API extern uint64_t Pool; LIBPBD_API extern uint64_t EventLoop; LIBPBD_API extern uint64_t AbstractUI; + extern uint64_t FileUtils; } } diff --git a/libs/pbd/pbd/demangle.h b/libs/pbd/pbd/demangle.h index c9f5c194c0..12dc58839c 100644 --- a/libs/pbd/pbd/demangle.h +++ b/libs/pbd/pbd/demangle.h @@ -32,7 +32,7 @@ namespace PBD { - template<typename T> LIBPBD_API + template<typename T> /*LIBPBD_API*/ std::string demangled_name (T const & obj) { #ifdef __GNUC__ diff --git a/libs/pbd/pbd/fallback_folders.h b/libs/pbd/pbd/fallback_folders.h new file mode 100644 index 0000000000..db8992db6d --- /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!! + LIBPBD_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 */ + + LIBPBD_API G_CONST_RETURN gchar* PBD_APICALLTYPE get_platform_fallback_folder (PBD::fallback_folder_t index); + LIBPBD_API G_CONST_RETURN gchar* G_CONST_RETURN * PBD_APICALLTYPE alloc_platform_fallback_folders (); + LIBPBD_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/uuid_boost.cc b/libs/pbd/pbd/ffs.h index 1a988b9820..f21fc82a39 100644 --- a/libs/pbd/uuid_boost.cc +++ b/libs/pbd/pbd/ffs.h @@ -1,6 +1,5 @@ /* - Copyright (C) 2008 Paul Davis - Author: Sakari Bergen + 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 @@ -18,20 +17,13 @@ */ -#include "pbd/uuid.h" +#ifndef __libpbd_ffs_h__ +#define __libpbd_ffs_h__ -using namespace PBD; +#include "pbd/libpbd_visibility.h" -UUID& -UUID::operator= (std::string const & str) -{ - boost::uuids::string_generator gen; - *((boost::uuids::uuid*) this) = gen (str); - return *this; -} +namespace PBD { + LIBPBD_API int ffs(int x); +} -std::string -UUID::to_s () const -{ - return std::string ((const char*) data, size()); -} +#endif /* __libpbd_ffs_h__ */ diff --git a/libs/pbd/pbd/file_utils.h b/libs/pbd/pbd/file_utils.h index 6f8a98b697..01ff8606a7 100644 --- a/libs/pbd/pbd/file_utils.h +++ b/libs/pbd/pbd/file_utils.h @@ -69,15 +69,15 @@ find_matching_files_in_directories (const std::vector<std::string>& directory_pa std::vector<std::string>& result); /** - * Takes a SearchPath and puts a list of all the files in the search path + * Takes a Searchpath and puts a list of all the files in the search path * that match pattern into the result vector. * - * @param search_path A SearchPath + * @param search_path A Searchpath * @param pattern A Glib::PatternSpec used to match the files * @param result A vector in which to place the resulting matches. */ LIBPBD_API void -find_matching_files_in_search_path (const SearchPath& search_path, +find_matching_files_in_search_path (const Searchpath& search_path, const Glib::PatternSpec& pattern, std::vector<std::string>& result); @@ -88,7 +88,7 @@ find_matching_files_in_search_path (const SearchPath& search_path, * @return true If file is found within the search path. */ LIBPBD_API bool -find_file_in_search_path (const SearchPath& search_path, +find_file_in_search_path (const Searchpath& search_path, const std::string& filename, std::string& result); diff --git a/libs/pbd/pbd/floating.h b/libs/pbd/pbd/floating.h index e5d582625a..c0003a3113 100644 --- a/libs/pbd/pbd/floating.h +++ b/libs/pbd/pbd/floating.h @@ -26,13 +26,15 @@ #ifndef __libpbd__floating_h__ #define __libpbd__floating_h__ +#include <stdint.h> + #include <cmath> #include "pbd/libpbd_visibility.h" namespace PBD { -union LIBPBD_API Float_t +union /*LIBPBD_API*/ Float_t { Float_t (float num = 0.0f) : f(num) {} diff --git a/libs/pbd/pbd/functor_command.h b/libs/pbd/pbd/functor_command.h index d2aacd18ac..6cca13209f 100644 --- a/libs/pbd/pbd/functor_command.h +++ b/libs/pbd/pbd/functor_command.h @@ -37,7 +37,7 @@ namespace PBD { template <class obj_type, class arg_type> -class LIBPBD_API FunctorCommand : public Command +class /*LIBPBD_API*/ FunctorCommand : public Command { private: typedef void (obj_type::*functor_type)(arg_type); diff --git a/libs/pbd/pbd/glib_semaphore.h b/libs/pbd/pbd/glib_semaphore.h new file mode 100644 index 0000000000..7f96120d7d --- /dev/null +++ b/libs/pbd/pbd/glib_semaphore.h @@ -0,0 +1,57 @@ +/* + 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 "pbd/libpbd_visibility.h" +#include "atomic_counter.h" + +namespace PBD { + +class LIBPBD_API 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/pbd/localeguard.h b/libs/pbd/pbd/localeguard.h new file mode 100644 index 0000000000..21ea5380fa --- /dev/null +++ b/libs/pbd/pbd/localeguard.h @@ -0,0 +1,37 @@ +/* + 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 + 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_localeguard_h__ +#define __pbd_localeguard_h__ + +#include <string> + +namespace PBD { + +struct LIBPBD_API /* Added by JE - */ 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/memento_command.h b/libs/pbd/pbd/memento_command.h index 6560780f3c..f6d11a0b33 100644 --- a/libs/pbd/pbd/memento_command.h +++ b/libs/pbd/pbd/memento_command.h @@ -51,7 +51,7 @@ * can do `just-in-time' binding from the crossfade ID. */ template <class obj_T> -class LIBPBD_API MementoCommandBinder : public PBD::Destructible +class /*LIBPBD_API*/ MementoCommandBinder : public PBD::Destructible { public: /** @return Stateful object to operate on */ @@ -68,7 +68,7 @@ public: /** A simple MementoCommandBinder which binds directly to an object */ template <class obj_T> -class LIBPBD_API SimpleMementoCommandBinder : public MementoCommandBinder<obj_T> +class /*LIBPBD_API*/ SimpleMementoCommandBinder : public MementoCommandBinder<obj_T> { public: SimpleMementoCommandBinder (obj_T& o) @@ -100,7 +100,7 @@ private: * memento, and redo is restoring the after memento. */ template <class obj_T> -class LIBPBD_API MementoCommand : public Command +class /*LIBPBD_API*/ MementoCommand : public Command { public: MementoCommand (obj_T& a_object, XMLNode* a_before, XMLNode* a_after) diff --git a/libs/pbd/pbd/msvc_pbd.h b/libs/pbd/pbd/msvc_pbd.h new file mode 100644 index 0000000000..a623ca2eb2 --- /dev/null +++ b/libs/pbd/pbd/msvc_pbd.h @@ -0,0 +1,256 @@ +/* + 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 +#undef LIBPBD_DLL +#define PBD_IS_IN_WINDLL 0 +#endif + +#include <pbd/libpbd_visibility.h> + +#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_APICALLTYPE) + #if defined(BUILDING_PBD) + #define PBD_APICALLTYPE __cdecl + #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point + #define PBD_APICALLTYPE __cdecl + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#elif !defined(PBD_APICALLTYPE) + // Other compilers / platforms could be accommodated here + #define PBD_APICALLTYPE +#ifndef GETOPT_API + #define GETOPT_API + #define GETOPT_APICALLTYPE +#endif +#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 +// JE - let's see if we can do without this now! 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); +LIBPBD_API int PBD_APICALLTYPE dlclose (void *handle) __THROW; +LIBPBD_API void* PBD_APICALLTYPE dlopen (const char *file_name, int mode) __THROW; +LIBPBD_API void* PBD_APICALLTYPE dlsym (void *handle, const char *symbol_name) __THROW; +LIBPBD_API char* PBD_APICALLTYPE dlerror () __THROW; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#ifndef __CYGWIN__ +/* For whatever reason, Ardour's 'libevoral' refuses to build as a DLL if we include both 'rpc.h' */ +/* and 'WinSock2.h'. It doesn't seem to matter which order we #include them. Given that we can't */ +/* edit 'rpc.h' or 'WinSock2.h', just make sure we don't #include them when building libevoral. */ +#ifndef BUILDING_EVORAL +#include <rpc.h> +typedef int (FAR PBDEXTN_APICALLTYPE *CYGINIT_API)(unsigned int); +#endif +#include <io.h> +#include <sys/types.h> + +#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; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +LIBPBD_API int __cdecl gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz); +LIBPBD_API ssize_t PBD_APICALLTYPE pread(int handle, void *buf, size_t nbytes, off_t offset); +LIBPBD_API ssize_t PBD_APICALLTYPE pwrite(int handle, const void *buf, size_t nbytes, off_t offset); +LIBPBD_API int PBD_APICALLTYPE poll(struct pollfd *fds, nfds_t nfds, int timeout); +LIBPBD_API double PBD_APICALLTYPE round(double x); + +namespace PBD { + +LIBPBD_API bool PBD_APICALLTYPE TestForMinimumSpecOS(char *revision="currently ignored"); +LIBPBD_API char* PBD_APICALLTYPE realpath (const char *original_path, char resolved_path[_MAX_PATH+1]); +LIBPBD_API int PBD_APICALLTYPE mkstemp (char *template_name); +LIBPBD_API int PBD_APICALLTYPE ntfs_link (const char *existing_filepath, const char *link_filepath); +LIBPBD_API int PBD_APICALLTYPE ntfs_unlink (const char *link_filepath); + +// These are used to replicate 'dirent.h' functionality +LIBPBD_API DIR* PBD_APICALLTYPE opendir (const char *szPath); +LIBPBD_API struct dirent* PBD_APICALLTYPE readdir (DIR *pDir); +LIBPBD_API int PBD_APICALLTYPE closedir (DIR *pDir); + +} // namespace PBD + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif // !__CYGWIN__ +#endif // PLATFORM_WINDOWS +#endif // _msvc_pbd_h_ diff --git a/libs/pbd/pbd/pathexpand.h b/libs/pbd/pbd/pathexpand.h index 5f1c03f8ee..5c5d4cf772 100644 --- a/libs/pbd/pbd/pathexpand.h +++ b/libs/pbd/pbd/pathexpand.h @@ -24,6 +24,7 @@ #include "pbd/libpbd_visibility.h" namespace PBD { + LIBPBD_API std::string canonical_path (const std::string& path); LIBPBD_API std::string path_expand (std::string path); LIBPBD_API std::string search_path_expand (std::string path); } diff --git a/libs/pbd/pbd/pathscanner.h b/libs/pbd/pbd/pathscanner.h index ef6499c759..d62203c008 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 #include "pbd/libpbd_visibility.h" diff --git a/libs/pbd/pbd/properties.h b/libs/pbd/pbd/properties.h index 27a0be1895..70d18db4c7 100644 --- a/libs/pbd/pbd/properties.h +++ b/libs/pbd/pbd/properties.h @@ -37,7 +37,7 @@ namespace PBD { /** Parent class for classes which represent a single scalar property in a Stateful object */ template<class T> -class LIBPBD_API PropertyTemplate : public PropertyBase +class /*LIBPBD_API*/ PropertyTemplate : public PropertyBase { public: PropertyTemplate (PropertyDescriptor<T> p, T const& v) @@ -197,7 +197,7 @@ private: PropertyTemplate (PropertyTemplate<T> const &); }; -template<class T> LIBPBD_API +template<class T> /*LIBPBD_API*/ std::ostream & operator<<(std::ostream& os, PropertyTemplate<T> const& s) { return os << s.val (); @@ -207,7 +207,7 @@ std::ostream & operator<<(std::ostream& os, PropertyTemplate<T> const& s) * with types that can be written to / read from stringstreams. */ template<class T> -class LIBPBD_API Property : public PropertyTemplate<T> +class /*LIBPBD_API*/ Property : public PropertyTemplate<T> { public: Property (PropertyDescriptor<T> q, T const& v) @@ -285,7 +285,7 @@ private: * separators, etc. */ template<> -class LIBPBD_API Property<std::string> : public PropertyTemplate<std::string> +class /*LIBPBD_API*/ Property<std::string> : public PropertyTemplate<std::string> { public: Property (PropertyDescriptor<std::string> d, std::string const & v) @@ -319,7 +319,7 @@ private: }; template<class T> -class LIBPBD_API EnumProperty : public Property<T> +class /*LIBPBD_API*/ EnumProperty : public Property<T> { public: EnumProperty (PropertyDescriptor<T> q, T const& v) @@ -352,7 +352,7 @@ private: * one. */ template <class T> -class LIBPBD_API SharedStatefulProperty : public PropertyBase +class /*LIBPBD_API*/ SharedStatefulProperty : public PropertyBase { public: typedef boost::shared_ptr<T> Ptr; diff --git a/libs/pbd/pbd/property_basics.h b/libs/pbd/pbd/property_basics.h index 2da21ddb84..d0eb1db922 100644 --- a/libs/pbd/pbd/property_basics.h +++ b/libs/pbd/pbd/property_basics.h @@ -38,7 +38,7 @@ class LIBPBD_API StatefulDiffCommand; typedef GQuark PropertyID; template<typename T> -struct LIBPBD_API PropertyDescriptor { +struct /*LIBPBD_API*/ PropertyDescriptor { PropertyDescriptor () : property_id (0) {} PropertyDescriptor (PropertyID pid) : property_id (pid) {} @@ -47,16 +47,17 @@ struct LIBPBD_API PropertyDescriptor { }; /** A list of IDs of Properties that have changed in some situation or other */ -class LIBPBD_API PropertyChange : public std::set<PropertyID> +class /*LIBPBD_API*/ PropertyChange : public std::set<PropertyID> { public: - PropertyChange() {} + LIBPBD_API PropertyChange() {} + LIBPBD_API ~PropertyChange() {} template<typename T> PropertyChange(PropertyDescriptor<T> p); - PropertyChange(const PropertyChange& other) : std::set<PropertyID> (other) {} + LIBPBD_API PropertyChange(const PropertyChange& other) : std::set<PropertyID> (other) {} - PropertyChange operator=(const PropertyChange& other) { + LIBPBD_API PropertyChange operator=(const PropertyChange& other) { clear (); insert (other.begin (), other.end ()); return *this; @@ -65,7 +66,7 @@ public: template<typename T> PropertyChange operator=(PropertyDescriptor<T> p); template<typename T> bool contains (PropertyDescriptor<T> p) const; - bool contains (const PropertyChange& other) const { + LIBPBD_API bool contains (const PropertyChange& other) const { for (const_iterator x = other.begin (); x != other.end (); ++x) { if (find (*x) != end ()) { return true; @@ -74,8 +75,8 @@ public: return false; } - void add (PropertyID id) { insert (id); } - void add (const PropertyChange& other) { insert (other.begin (), other.end ()); } + LIBPBD_API void add (PropertyID id) { insert (id); } + LIBPBD_API void add (const PropertyChange& other) { insert (other.begin (), other.end ()); } template<typename T> void add (PropertyDescriptor<T> p); }; diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h index c66feb73a5..37ce723715 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/rcu.h b/libs/pbd/pbd/rcu.h index 6ee68afabf..eceec24cd5 100644 --- a/libs/pbd/pbd/rcu.h +++ b/libs/pbd/pbd/rcu.h @@ -45,7 +45,7 @@ and managed object. */ template<class T> -class LIBPBD_API RCUManager +class /*LIBPBD_API*/ RCUManager { public: @@ -111,7 +111,7 @@ class LIBPBD_API RCUManager means that no actual objects will be deleted incorrectly if this is misused. */ template<class T> -class LIBPBD_API SerializedRCUManager : public RCUManager<T> +class /*LIBPBD_API*/ SerializedRCUManager : public RCUManager<T> { public: @@ -214,7 +214,7 @@ private: */ template<class T> -class LIBPBD_API RCUWriter +class /*LIBPBD_API*/ RCUWriter { public: 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 bb2b8244f9..e3cec6adf1 100644 --- a/libs/pbd/pbd/ringbuffer.h +++ b/libs/pbd/pbd/ringbuffer.h @@ -26,7 +26,7 @@ #include "pbd/libpbd_visibility.h" template<class T> -class LIBPBD_API RingBuffer +class /*LIBPBD_API*/ RingBuffer { public: RingBuffer (guint sz) { @@ -120,7 +120,7 @@ class LIBPBD_API RingBuffer guint size_mask; }; -template<class T> LIBPBD_API guint +template<class T> /*LIBPBD_API*/ guint RingBuffer<T>::read (T *dest, guint cnt) { guint free_cnt; @@ -159,7 +159,7 @@ RingBuffer<T>::read (T *dest, guint cnt) return to_read; } -template<class T> LIBPBD_API guint +template<class T> /*LIBPBD_API*/ guint RingBuffer<T>::write (T const *src, guint cnt) { @@ -199,8 +199,8 @@ RingBuffer<T>::write (T const *src, guint cnt) return to_write; } -template<class T> LIBPBD_API void -RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec) +template<class T> /*LIBPBD_API*/ void +RingBuffer<T>::get_read_vector (typename RingBuffer<T>::rw_vector *vec) { guint free_cnt; @@ -240,8 +240,8 @@ RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec) } } -template<class T> LIBPBD_API void -RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec) +template<class T> /*LIBPBD_API*/ void +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 65fe939597..cd17299961 100644 --- a/libs/pbd/pbd/ringbufferNPT.h +++ b/libs/pbd/pbd/ringbufferNPT.h @@ -32,7 +32,7 @@ namespace PBD { /* ringbuffer class where the element size is not required to be a power of two */ template<class T> -class LIBPBD_API RingBufferNPT +class /*LIBPBD_API*/ RingBufferNPT { public: RingBufferNPT (size_t sz) { @@ -120,7 +120,7 @@ class LIBPBD_API RingBufferNPT mutable gint read_ptr; }; -template<class T> LIBPBD_API size_t +template<class T> /*LIBPBD_API*/ size_t RingBufferNPT<T>::read (T *dest, size_t cnt) { size_t free_cnt; @@ -159,7 +159,7 @@ RingBufferNPT<T>::read (T *dest, size_t cnt) return to_read; } -template<class T> LIBPBD_API size_t +template<class T> /*LIBPBD_API*/ size_t RingBufferNPT<T>::write (const T *src, size_t cnt) { size_t free_cnt; @@ -198,8 +198,8 @@ RingBufferNPT<T>::write (const T *src, size_t cnt) return to_write; } -template<class T> LIBPBD_API void -RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec) +template<class T> /*LIBPBD_API*/ void +RingBufferNPT<T>::get_read_vector (typename RingBufferNPT<T>::rw_vector *vec) { size_t free_cnt; size_t cnt2; @@ -238,8 +238,8 @@ RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec) } } -template<class T> LIBPBD_API void -RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec) +template<class T> /*LIBPBD_API*/ void +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 ad0b6c75d5..909bffb0a4 100644 --- a/libs/pbd/pbd/search_path.h +++ b/libs/pbd/pbd/search_path.h @@ -17,8 +17,8 @@ */ -#ifndef PBD_SEARCH_PATH_INCLUDED -#define PBD_SEARCH_PATH_INCLUDED +#ifndef __libpbd_search_path_h__ +#define __libpbd_search_path_h__ #include <string> #include <vector> @@ -28,26 +28,26 @@ namespace PBD { /** - * @class SearchPath + * @class Searchpath * - * The SearchPath class is a helper class for getting a + * The Searchpath class is a helper class for getting a * vector of paths contained in a search path string where a * "search path string" contains absolute directory paths * separated by a colon(:) or a semi-colon(;) on windows. * - * The SearchPath class does not test whether the paths exist + * The Searchpath class does not test whether the paths exist * or are directories. It is basically just a container. */ -class LIBPBD_API SearchPath : public std::vector<std::string> +class /*LIBPBD_API*/ Searchpath : public std::vector<std::string> { public: /** - * Create an empty SearchPath. + * Create an empty Searchpath. */ - SearchPath (); + LIBPBD_API Searchpath (); /** - * Initialize SearchPath from a string where the string contains + * Initialize Searchpath from a string where the string contains * one or more absolute paths to directories which are delimited * by a path separation character. The path delimeter is a * colon(:) on unix and a semi-colon(;) on windows. @@ -57,15 +57,17 @@ public: * * @param search_path A path string. */ - SearchPath (const std::string& search_path); + LIBPBD_API Searchpath (const std::string& search_path); /** - * Initialize SearchPath from a vector of paths that may or may + * Initialize Searchpath from a vector of paths that may or may * not exist. * * @param paths A vector of paths. */ - SearchPath (const std::vector<std::string>& paths); + LIBPBD_API Searchpath (const std::vector<std::string>& paths); + + LIBPBD_API ~Searchpath () {}; /** * @return a search path string. @@ -73,41 +75,41 @@ public: * The string that is returned contains the platform specific * path separator. */ - const std::string to_string () const; + LIBPBD_API const std::string to_string () const; /** * Add all the directories in path to this. */ - SearchPath& operator+= (const SearchPath& spath); + LIBPBD_API Searchpath& operator+= (const Searchpath& spath); /** * Add another directory path to the search path. */ - SearchPath& operator+= (const std::string& directory_path); + LIBPBD_API Searchpath& operator+= (const std::string& directory_path); /** - * Concatenate another SearchPath onto this. + * Concatenate another Searchpath onto this. */ - SearchPath& operator+ (const SearchPath& other); + LIBPBD_API Searchpath& operator+ (const Searchpath& other); /** * Add another path to the search path. */ - SearchPath& operator+ (const std::string& directory_path); + LIBPBD_API Searchpath& operator+ (const std::string& directory_path); /** * Add a sub-directory to each path in the search path. * @param subdir The directory name, it should not contain * any path separating tokens. */ - SearchPath& add_subdirectory_to_paths (const std::string& subdir); + LIBPBD_API Searchpath& add_subdirectory_to_paths (const std::string& subdir); protected: - void add_directory (const std::string& directory_path); - void add_directories (const std::vector<std::string>& paths); + LIBPBD_API void add_directory (const std::string& directory_path); + LIBPBD_API void add_directories (const std::vector<std::string>& paths); }; } // namespace PBD -#endif +#endif /* __libpbd_search_path_h__ */ diff --git a/libs/pbd/pbd/semaphore.h b/libs/pbd/pbd/semaphore.h index a2390f5a18..265a219e07 100644 --- a/libs/pbd/pbd/semaphore.h +++ b/libs/pbd/pbd/semaphore.h @@ -22,8 +22,11 @@ #ifdef __APPLE__ # include <mach/mach.h> -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) # include <windows.h> +#ifndef INFINITE +#define INFINITE 0xffffffffL +#endif #else # include <semaphore.h> # include <errno.h> @@ -46,7 +49,7 @@ namespace PBD { only safe way to reliably signal from a real-time audio thread. The counting semantics also complement ringbuffers of events nicely. */ -class LIBPBD_API Semaphore +class /*LIBPBD_API*/ Semaphore { public: /** @@ -70,7 +73,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; @@ -115,7 +118,7 @@ Semaphore::try_wait() return semaphore_timedwait(_sem, zero) == KERN_SUCCESS; } -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) inline Semaphore::Semaphore(unsigned initial) @@ -152,7 +155,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 719a3d0f46..5c0191e25b 100644 --- a/libs/pbd/pbd/semutils.h +++ b/libs/pbd/pbd/semutils.h @@ -19,7 +19,11 @@ #ifndef __pbd_semutils_h__ #define __pbd_semutils_h__ +#ifdef PLATFORM_WINDOWS +#include <windows.h> +#else #include <semaphore.h> +#endif #include "pbd/libpbd_visibility.h" @@ -27,7 +31,10 @@ namespace PBD { class LIBPBD_API ProcessSemaphore { private: -#ifdef __APPLE__ +#ifdef PLATFORM_WINDOWS + HANDLE _sem; + +#elif __APPLE__ sem_t* _sem; sem_t* ptr_to_sem() const { return _sem; } #else @@ -39,8 +46,15 @@ class LIBPBD_API 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/sequence_property.h b/libs/pbd/pbd/sequence_property.h index 28775b5f3c..e105e82e47 100644 --- a/libs/pbd/pbd/sequence_property.h +++ b/libs/pbd/pbd/sequence_property.h @@ -44,7 +44,7 @@ namespace PBD { * any change. */ template<typename Container> -class LIBPBD_API SequenceProperty : public PropertyBase +class /*LIBPBD_API*/ SequenceProperty : public PropertyBase { public: typedef std::set<typename Container::value_type> ChangeContainer; @@ -95,14 +95,14 @@ class LIBPBD_API SequenceProperty : public PropertyBase /* record the change described in our change member */ if (!_changes.added.empty()) { - for (typename ChangeContainer::iterator i = _changes.added.begin(); i != _changes.added.end(); ++i) { + for (typename ChangeContainer::const_iterator i = _changes.added.begin(); i != _changes.added.end(); ++i) { XMLNode* add_node = new XMLNode ("Add"); child->add_child_nocopy (*add_node); get_content_as_xml (*i, *add_node); } } if (!_changes.removed.empty()) { - for (typename ChangeContainer::iterator i = _changes.removed.begin(); i != _changes.removed.end(); ++i) { + for (typename ChangeContainer::const_iterator i = _changes.removed.begin(); i != _changes.removed.end(); ++i) { XMLNode* remove_node = new XMLNode ("Remove"); child->add_child_nocopy (*remove_node); get_content_as_xml (*i, *remove_node); @@ -171,7 +171,7 @@ class LIBPBD_API SequenceProperty : public PropertyBase with this diff(). */ - for (typename ChangeContainer::iterator i = a->changes().added.begin(); i != a->changes().added.end(); ++i) { + for (typename ChangeContainer::const_iterator i = a->changes().added.begin(); i != a->changes().added.end(); ++i) { (*i)->DropReferences.connect_same_thread (*cmd, boost::bind (&Destructible::drop_references, cmd)); } } @@ -311,10 +311,10 @@ class LIBPBD_API SequenceProperty : public PropertyBase } Container& operator= (const Container& other) { - for (typename Container::iterator i = _val.begin(); i != _val.end(); ++i) { + for (typename Container::const_iterator i = _val.begin(); i != _val.end(); ++i) { _changes.remove (*i); } - for (typename Container::iterator i = other.begin(); i != other.end(); ++i) { + for (typename Container::const_iterator i = other.begin(); i != other.end(); ++i) { _changes.add (*i); } return _val = other; diff --git a/libs/pbd/pbd/signals.h b/libs/pbd/pbd/signals.h index 3896fd55b5..672dc66850 100644 --- a/libs/pbd/pbd/signals.h +++ b/libs/pbd/pbd/signals.h @@ -79,7 +79,7 @@ private: }; template<typename R> -class LIBPBD_API OptionalLastValue +class /*LIBPBD_API*/ OptionalLastValue { public: typedef boost::optional<R> result_type; diff --git a/libs/pbd/pbd/stacktrace.h b/libs/pbd/pbd/stacktrace.h index fbb92c8fa0..c5d9743b1e 100644 --- a/libs/pbd/pbd/stacktrace.h +++ b/libs/pbd/pbd/stacktrace.h @@ -44,7 +44,7 @@ namespace PBD { LIBPBD_API std::string demangle (const std::string&); template<typename T> -class LIBPBD_API thing_with_backtrace +class /*LIBPBD_API*/ thing_with_backtrace { public: thing_with_backtrace () { @@ -113,11 +113,11 @@ private: static Glib::Threads::Mutex all_mutex; }; -template<typename T> LIBPBD_API std::list<PBD::thing_with_backtrace<T> *> PBD::thing_with_backtrace<T>::all; -template<typename T> LIBPBD_API Glib::Threads::Mutex PBD::thing_with_backtrace<T>::all_mutex; +template<typename T> /*LIBPBD_API*/ std::list<PBD::thing_with_backtrace<T> *> PBD::thing_with_backtrace<T>::all; +template<typename T> /*LIBPBD_API*/ Glib::Threads::Mutex PBD::thing_with_backtrace<T>::all_mutex; } // namespace PBD - +// JE - !!!!#include "../pbd/stacktrace.impl" #endif /* __libpbd_stacktrace_h__ */ diff --git a/libs/pbd/pbd/stl_delete.h b/libs/pbd/pbd/stl_delete.h index b98bb5e8e3..1598a90e2c 100644 --- a/libs/pbd/pbd/stl_delete.h +++ b/libs/pbd/pbd/stl_delete.h @@ -26,7 +26,7 @@ first include the revelant container type header. */ #if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR) || defined(_LIBCPP_VECTOR) -template<class T> LIBPBD_API void vector_delete (std::vector<T *> *vec) +template<class T> /*LIBPBD_API*/ void vector_delete (std::vector<T *> *vec) { typename std::vector<T *>::iterator i; @@ -38,7 +38,7 @@ template<class T> LIBPBD_API void vector_delete (std::vector<T *> *vec) #endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR || _LIBCPP_VECTOR #if defined(_CPP_MAP) || defined(_GLIBCXX_MAP) || defined(__SGI_STL_MAP) -template<class K, class T> LIBPBD_API void map_delete (std::map<K, T *> *m) +template<class K, class T> /*LIBPBD_API*/ void map_delete (std::map<K, T *> *m) { typename std::map<K, T *>::iterator i; @@ -50,7 +50,7 @@ template<class K, class T> LIBPBD_API void map_delete (std::map<K, T *> *m) #endif // _CPP_MAP || _GLIBCXX_MAP || __SGI_STL_MAP #if defined(_CPP_LIST) || defined(_GLIBCXX_LIST) || defined(__SGI_STL_LIST) -template<class T> LIBPBD_API void list_delete (std::list<T *> *l) +template<class T> /*LIBPBD_API*/ void list_delete (std::list<T *> *l) { typename std::list<T *>::iterator i; @@ -63,7 +63,7 @@ template<class T> LIBPBD_API void list_delete (std::list<T *> *l) #endif // _CPP_LIST || _GLIBCXX_LIST || __SGI_STL_LIST #if defined(_CPP_SLIST) || defined(_GLIBCXX_SLIST) || defined(__SGI_STL_SLIST) -template<class T> LIBPBD_API void slist_delete (std::slist<T *> *l) +template<class T> /*LIBPBD_API*/ void slist_delete (std::slist<T *> *l) { typename std::slist<T *>::iterator i; @@ -76,7 +76,7 @@ template<class T> LIBPBD_API void slist_delete (std::slist<T *> *l) #endif // _CPP_SLIST || _GLIBCXX_SLIST || __SGI_STL_SLIST #if defined(_CPP_SET) || defined(_GLIBCXX_SET) || defined(__SGI_STL_SET) -template<class T> void LIBPBD_API set_delete (std::set<T *> *sset) +template<class T> void /*LIBPBD_API*/ set_delete (std::set<T *> *sset) { typename std::set<T *>::iterator i; 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/tokenizer.h b/libs/pbd/pbd/tokenizer.h index b4b3b107c0..3253473519 100644 --- a/libs/pbd/pbd/tokenizer.h +++ b/libs/pbd/pbd/tokenizer.h @@ -37,7 +37,7 @@ namespace PBD { are discarded. */ template<typename StringType, typename Iter> -LIBPBD_API unsigned int +/*LIBPBD_API*/ unsigned int tokenize(const StringType& str, const StringType& delims, Iter it, diff --git a/libs/pbd/pbd/touchable.h b/libs/pbd/pbd/touchable.h index ed7d75df52..297be8b0f1 100644 --- a/libs/pbd/pbd/touchable.h +++ b/libs/pbd/pbd/touchable.h @@ -21,7 +21,7 @@ #include "pbd/libpbd_visibility.h" -class LIBPBD_API Touchable +class /*LIBPBD_API*/ Touchable { public: Touchable() : _delete_after_touch (false) {} @@ -37,7 +37,7 @@ class LIBPBD_API Touchable }; template<class T> -class LIBPBD_API DynamicTouchable : public Touchable +class /*LIBPBD_API*/ DynamicTouchable : public Touchable { public: DynamicTouchable (T& t, void (T::*m)(void)) @@ -53,7 +53,7 @@ class LIBPBD_API DynamicTouchable : public Touchable }; template<class T1, class T2> -class LIBPBD_API DynamicTouchable1 : public Touchable +class /*LIBPBD_API*/ DynamicTouchable1 : public Touchable { public: DynamicTouchable1 (T1& t, void (T1::*m)(T2), T2 a) @@ -70,7 +70,7 @@ class LIBPBD_API DynamicTouchable1 : public Touchable }; template<class T1, class T2, class T3> -class LIBPBD_API DynamicTouchable2 : public Touchable +class /*LIBPBD_API*/ DynamicTouchable2 : public Touchable { public: DynamicTouchable2 (T1& t, void (T1::*m)(T2, T3), T2 a1, T3 a2) diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h index 753bc13b15..794e68ce97 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/libpbd_visibility.h" #include "pbd/command.h" diff --git a/libs/pbd/pbd/unknown_type.h b/libs/pbd/pbd/unknown_type.h index 4d984269a7..ef9db1ac43 100644 --- a/libs/pbd/pbd/unknown_type.h +++ b/libs/pbd/pbd/unknown_type.h @@ -22,9 +22,9 @@ #include <exception> -#include "pbd/libpbd_visibility.h" +//#include "pbd/libpbd_visibility.h" -class LIBPBD_API unknown_type : public std::exception { +class /*LIBPBD_API*/ unknown_type : public std::exception { public: virtual const char *what() const throw() { return "unknown type"; } }; diff --git a/libs/pbd/pbd/unwind.h b/libs/pbd/pbd/unwind.h index cf7998fdd4..5a0fe26559 100644 --- a/libs/pbd/pbd/unwind.h +++ b/libs/pbd/pbd/unwind.h @@ -25,7 +25,7 @@ namespace PBD { template <typename T> -class LIBPBD_API Unwinder { +class /*LIBPBD_API*/ Unwinder { public: Unwinder (T& var, T new_val) : _var (var), _old_val (var) { var = new_val; } ~Unwinder () { _var = _old_val; } diff --git a/libs/pbd/pbd/uuid.h b/libs/pbd/pbd/uuid.h index 333a902b4d..77e84c5f09 100644 --- a/libs/pbd/pbd/uuid.h +++ b/libs/pbd/pbd/uuid.h @@ -22,31 +22,37 @@ #define __pbd_uuid_h__ #include <string> -#include <uuid/uuid.h> +#include <boost/uuid/uuid.hpp> +#include <boost/uuid/uuid_generators.hpp> #include "pbd/libpbd_visibility.h" namespace PBD { -class LIBPBD_API UUID { +class LIBPBD_API 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/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 3d3cb96fb5..b8ca8fc093 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); @@ -116,7 +124,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); } @@ -149,7 +157,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); } } @@ -161,6 +169,7 @@ void pthread_cancel_all () { pthread_mutex_lock (&thread_map_lock); + for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ) { ThreadMap::iterator nxt = i; 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..ea08785f68 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 = ":"; @@ -37,12 +37,12 @@ const char * const path_delimiter = ":"; namespace PBD { -SearchPath::SearchPath () +Searchpath::Searchpath () { } -SearchPath::SearchPath (const string& path) +Searchpath::Searchpath (const string& path) { vector<std::string> tmp; @@ -51,13 +51,13 @@ SearchPath::SearchPath (const string& path) } } -SearchPath::SearchPath (const vector<std::string>& paths) +Searchpath::Searchpath (const vector<std::string>& paths) { add_directories (paths); } void -SearchPath::add_directory (const std::string& directory_path) +Searchpath::add_directory (const std::string& directory_path) { if (!directory_path.empty()) { push_back(directory_path); @@ -65,7 +65,7 @@ SearchPath::add_directory (const std::string& directory_path) } void -SearchPath::add_directories (const vector<std::string>& paths) +Searchpath::add_directories (const vector<std::string>& paths) { for(vector<std::string>::const_iterator i = paths.begin(); i != paths.end(); ++i) { add_directory (*i); @@ -73,7 +73,7 @@ SearchPath::add_directories (const vector<std::string>& paths) } const string -SearchPath::to_string () const +Searchpath::to_string () const { string path; @@ -87,37 +87,37 @@ SearchPath::to_string () const return path; } -SearchPath& -SearchPath::operator+= (const SearchPath& spath) +Searchpath& +Searchpath::operator+= (const Searchpath& spath) { insert(end(), spath.begin(), spath.end()); return *this; } -SearchPath& -SearchPath::operator+= (const std::string& directory_path) +Searchpath& +Searchpath::operator+= (const std::string& directory_path) { add_directory (directory_path); return *this; } -SearchPath& -SearchPath::operator+ (const std::string& directory_path) +Searchpath& +Searchpath::operator+ (const std::string& directory_path) { add_directory (directory_path); return *this; } -SearchPath& -SearchPath::operator+ (const SearchPath& spath) +Searchpath& +Searchpath::operator+ (const Searchpath& spath) { - // concatenate paths into new SearchPath + // concatenate paths into new Searchpath insert(end(), spath.begin(), spath.end()); return *this; } -SearchPath& -SearchPath::add_subdirectory_to_paths (const string& subdir) +Searchpath& +Searchpath::add_subdirectory_to_paths (const string& subdir) { for (vector<std::string>::iterator i = begin(); i != end(); ++i) { // should these new paths just be added to the end of diff --git a/libs/pbd/semutils.cc b/libs/pbd/semutils.cc index 48fdd249f6..cf7b54d30e 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 (); } @@ -45,7 +50,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/stacktrace.cc b/libs/pbd/stacktrace.cc index 0177b8c9e8..c74dd946f7 100644 --- a/libs/pbd/stacktrace.cc +++ b/libs/pbd/stacktrace.cc @@ -22,6 +22,7 @@ #include "pbd/stacktrace.h" #include <cstdio> #include <iostream> +#include <string> void PBD::trace_twb () @@ -105,7 +106,7 @@ PBD::stacktrace (std::ostream& out, int levels) #else std::string -PBD::demangle (std::string const & l) +PBD::demangle (std::string const & l) /* JE - !!!! 'PBD' namespace might possibly get removed (except it's still used in 'libs/canvas/item.cc') */ { return std::string(); } 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..6e099d2f3e 100644 --- a/libs/pbd/test/test_common.cc +++ b/libs/pbd/test/test_common.cc @@ -25,10 +25,10 @@ * in an installed location on windows or by setting an environment variable * on unix. */ -PBD::SearchPath +PBD::Searchpath test_search_path () { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS std::string wsp(g_win32_get_package_installation_directory_of_module(NULL)); return Glib::build_filename (wsp, "pbd_testdata"); #else diff --git a/libs/pbd/test/test_common.h b/libs/pbd/test/test_common.h index 0dc62f61dc..825c01fecb 100644 --- a/libs/pbd/test/test_common.h +++ b/libs/pbd/test/test_common.h @@ -21,6 +21,6 @@ #include "pbd/search_path.h" -PBD::SearchPath test_search_path (); +PBD::Searchpath test_search_path (); #endif 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 09af0f614b..d721a78675 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', @@ -61,6 +63,7 @@ libpbd_sources = [ 'property_list.cc', 'pthread_utils.cc', 'receiver.cc', + 'resource.cc', 'search_path.cc', 'semutils.cc', 'shortpath.cc', @@ -90,20 +93,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): @@ -127,6 +128,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' @@ -150,6 +154,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 @@ -161,7 +166,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& |