diff options
48 files changed, 4779 insertions, 47 deletions
diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc index 5725d69182..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> @@ -47,13 +51,13 @@ BaseUI::BaseUI (const string& str) : m_context(MainContext::get_default()) , run_loop_thread (0) , _name (str) -#ifndef WIN32 +#ifndef PLATFORM_WINDOWS , request_channel (true) #endif { base_ui_instance = this; -#ifndef WIN32 +#ifndef PLATFORM_WINDOWS request_channel.ios()->connect (sigc::mem_fun (*this, &BaseUI::request_handler)); #endif @@ -120,7 +124,7 @@ BaseUI::quit () } } -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS gboolean BaseUI::_request_handler (gpointer data) { @@ -168,7 +172,7 @@ void BaseUI::signal_new_request () { DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::signal_new_request\n"); -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS // handled in timeout, how to signal...? #else request_channel.wakeup (); @@ -182,7 +186,7 @@ void BaseUI::attach_request_source () { DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::attach_request_source\n"); -#ifdef WIN32 +#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()); diff --git a/libs/pbd/clear_dir.cc b/libs/pbd/clear_dir.cc index 86f7067201..2f9c7b772d 100644 --- a/libs/pbd/clear_dir.cc +++ b/libs/pbd/clear_dir.cc @@ -17,9 +17,17 @@ */ -#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> 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 d8a3cd5a65..1a27a436a6 100644 --- a/libs/pbd/epa.cc +++ b/libs/pbd/epa.cc @@ -24,7 +24,12 @@ #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; diff --git a/libs/pbd/fallback_folders.cc b/libs/pbd/fallback_folders.cc new file mode 100644 index 0000000000..deecd60d7a --- /dev/null +++ b/libs/pbd/fallback_folders.cc @@ -0,0 +1,591 @@ +/* + Copyright (C) 2008 John Emmas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <pbd/fallback_folders.h> +#include <glib.h> +#include <glibmm.h> +#include <string.h> + + + +#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!! +#include <shlobj.h> +#include <winreg.h> + +//*************************************************************** +// +// get_win_special_folder() +// +// Gets the full path name that corresponds of one of the Windows +// special folders, such as "My Documents" and the like. The input +// parameter must be one of the corresponding CSIDL values, such +// as CSIDL_SYSTEM etc. +// +// Returns: +// +// On Success: A pointer to a newly allocated string containing +// the name of the special folder (must later be freed). +// On Failure: NULL +// +gchar * +get_win_special_folder (int csidl) +{ +wchar_t path[PATH_MAX+1]; +HRESULT hr; +LPITEMIDLIST pidl = 0; +gchar *retval = 0; + + if (S_OK == (hr = SHGetSpecialFolderLocation (0, csidl, &pidl))) + { + if (SHGetPathFromIDListW (pidl, path)) + retval = g_utf16_to_utf8 ((const gunichar2*)path, -1, 0, 0, 0); + CoTaskMemFree (pidl); + } + + return retval; +} +#endif // PLATFORM_WINDOWS + +namespace PBD { + +static gchar **fallback_folders = 0; + +//*************************************************************** +// +// get_platform_fallback_folders() +// +// Returns an array of folders to fall back to if the folders +// weren't named at build time and subsequently couldn't be found +// in the user's environment. This might not be needed any more +// because the function 'fixup_bundle_environment()' (in the +// gtk2_ardour branch) now explicitly sets up any environment +// paths that the program will need at run time. However, having +// the folders here might help us to simplify the above function +// which would be useful (currently, there are different versions +// of 'fixup_bundle_environment()' for each supported platform). +// Twelve fallback folders are currently catered for, corresponding to:- +// +// LOCALEDIR +// GTK_DIR +// CONFIG_DIR +// ARDOUR_DIR +// MODULE_DIR +// DATA_DIR +// ICONS_DIR +// PIXMAPS_DIR +// CONTROL_SURFACES_DIR +// VAMP_DIR +// LADSPA_PATH - note that there's only one entry in the path +// VST_PATH - note that there may only be one entry in the path +// +// Returns: +// +// On Success: A pointer to an array containing the above dirs. +// On Failure: NULL +// +#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!! + +static gchar** +get_platform_fallback_folders () +{ +gchar **fallback_dir_vector = 0; +const gchar *pUsrHome = 0; // Do not free !! + + if (!fallback_folders) + { + GArray *pFallbackDirs; + gchar *pAppData = 0; + gchar *pMyAppData = 0; + gchar *pExeRoot = 0; + gchar *pPersonal = 0; + + pFallbackDirs = g_array_new (TRUE, TRUE, sizeof (char *)); + + if (pFallbackDirs) + { + /* Get the path for the user's personal folder */ + gchar *pPersonalTemp = get_win_special_folder (CSIDL_PERSONAL); + + /* and the path for the user's personal application data */ + gchar *pMyAppDataTemp = get_win_special_folder (CSIDL_LOCAL_APPDATA); + + /* and the path for common application data ("Documents and Settings\All Users\Application Data") */ + gchar *pAppDataTemp = get_win_special_folder (CSIDL_COMMON_APPDATA); + + if (0 == pAppDataTemp) + pAppData = g_build_filename("C:\\", "Documents and Settings", "All Users", "Application Data", PROGRAM_NAME, "local", 0); + else + { + pAppData = g_build_filename(pAppDataTemp, PROGRAM_NAME, "local", 0); + g_free (pAppDataTemp); + } + + if (0 == pMyAppDataTemp) + { + pMyAppData = g_build_filename(g_get_home_dir(), "Application Data", "local", 0); + } + else + { + pMyAppData = g_build_filename(pMyAppDataTemp, 0); + g_free (pMyAppDataTemp); + } + + if (0 == pPersonalTemp) + pPersonal = g_build_filename(g_get_home_dir(), 0); + else + { + pPersonal = g_build_filename(pPersonalTemp, 0); + g_free (pPersonalTemp); + } + + /* Get the path to the running application */ + pExeRoot = g_win32_get_package_installation_directory_of_module (0); + + if (0 == pExeRoot) + { + pExeRoot = g_build_filename("C:\\", "Program Files", PROGRAM_NAME, 0); + } + + if ((pExeRoot) && (pAppData) && (pMyAppData) && (pPersonal)) + { + gchar tmp[PATH_MAX+1]; + gchar* p; + + // Build our LOCALEDIR entry + if (0 != (p = g_build_filename(pAppData, "share", "locale", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our GTK_DIR entry + if (0 != (p = g_build_filename(pPersonal, ".gtk-2.0", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONFIG_DIR entry + if (0 != (p = g_build_filename(pAppData, "etc", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ARDOUR_DIR entry + p = g_build_filename(pMyAppData, PROGRAM_NAME, 0); + + if (0 != p) + { + g_array_append_val (pFallbackDirs, p); + + // Build our MODULE_DIR entry + strcpy(tmp, pExeRoot); + if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR))) + { + *p = '\0'; + + if (0 != (p = g_build_filename(tmp, 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our DATA_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ICONS_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", "icons", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our PIXMAPS_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", "pixmaps", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONTROL_SURFACES_DIR entry + if (0 != (p = g_build_filename(pExeRoot, "bin", "surfaces", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our VAMP_DIR entry + p = g_build_filename(pExeRoot, "bin", "vamp", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + + // Next, build our LADSPA_PATH entry + p = g_build_filename(pExeRoot, "bin", "plugins", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + + // And finally, build our VST_PATH entry + DWORD dwType = REG_SZ; HKEY hKey; + DWORD dwSize = PATH_MAX; p = 0; + if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_CURRENT_USER, "Software\\VST", 0, KEY_READ, &hKey)) + { + // Look for the user's VST Registry entry + if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize)) + p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), 0); + + RegCloseKey (hKey); + } + + if (p == 0) + if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Software\\VST", 0, KEY_READ, &hKey)) + { + // Look for a global VST Registry entry + if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize)) + p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), 0); + + RegCloseKey (hKey); + } + + if (p == 0) + { + gchar *pVSTx86 = 0; + gchar *pProgFilesX86 = get_win_special_folder (CSIDL_PROGRAM_FILESX86); + + if (pProgFilesX86) + { + // Look for a VST folder under C:\Program Files (x86) + if (pVSTx86 = g_build_filename (pProgFilesX86, "Steinberg", "VSTPlugins", 0)) + { + if (Glib::file_test (pVSTx86, Glib::FILE_TEST_EXISTS)) + if (Glib::file_test (pVSTx86, Glib::FILE_TEST_IS_DIR)) + p = g_build_filename (pVSTx86, 0); + + g_free (pVSTx86); + } + + g_free (pProgFilesX86); + } + + if (p == 0) + { + // Look for a VST folder under C:\Program Files + gchar *pVST = 0; + gchar *pProgFiles = get_win_special_folder (CSIDL_PROGRAM_FILES); + + if (pProgFiles) + { + if (pVST = g_build_filename (pProgFiles, "Steinberg", "VSTPlugins", 0)) + { + if (Glib::file_test (pVST, Glib::FILE_TEST_EXISTS)) + if (Glib::file_test (pVST, Glib::FILE_TEST_IS_DIR)) + p = g_build_filename (pVST, 0); + + g_free (pVST); + } + + g_free (pProgFiles); + } + } + } + + if (p == 0) + { + // If all else failed, assume the plugins are under "My Documents" + pUsrHome = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + if (pUsrHome) + p = g_build_filename (pUsrHome, "Plugins", "VST", 0); + else + { + pUsrHome = g_build_filename(g_get_home_dir(), "My Documents", 0); + if (pUsrHome) + p = g_build_filename (pUsrHome, "Plugins", "VST", 0); + } + } + else + { + gchar* q = 0; + + // Concatenate the registry path with the user's personal path + pUsrHome = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + + if (pUsrHome) + { + q = p; + p = g_build_path (";", q, g_build_filename(pUsrHome, "Plugins", "VST", 0), 0); + } + else + { + pUsrHome = g_build_filename(g_get_home_dir(), "My Documents", 0); + if (pUsrHome) + { + q = p; + p = g_build_path (";", q, g_build_filename (pUsrHome, "Plugins", "VST", 0), 0); + } + } + } + + if (p) //VST + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + + // BUNDLED_LV2 + p = g_build_filename(pExeRoot, "bin", "lv2", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + else + g_array_append_val (pFallbackDirs, ""); + } + } + } + } + } + } + } + } + } + } + + g_free (pAppData); + g_free (pMyAppData); + g_free (pExeRoot); + g_free (pPersonal); + } + + fallback_dir_vector = fallback_folders = (gchar **) g_array_free (pFallbackDirs, FALSE); + } + } + else + fallback_dir_vector = fallback_folders; + + return (fallback_dir_vector); +} + +#else +// Assume Linux, Cygwin or OS-X. Note that in all 3 cases we only +// need to cater for unbundled releases (those built by a user from +// source). Bundled releases of Ardour and Mixbus now specifically +// write their folders and paths to the user's environment at startup. +// See the function 'fixup_bundle_environment()'. + +static gchar** +get_platform_fallback_folders () +{ +gchar **fallback_dir_vector = 0; +gchar *pUsrHome = 0; + + if (!fallback_folders) + { + GArray *pFallbackDirs; + gchar *pAppData = 0; + gchar *pExeRoot = 0; + gchar *pPersonal = 0; + + pFallbackDirs = g_array_new (TRUE, TRUE, sizeof (char *)); + + if (pFallbackDirs) + { + pAppData = g_build_filename("/usr", "local", 0); + pExeRoot = g_build_filename("/usr", "local", "lib", "ardour2", 0); + pPersonal = g_build_filename(g_get_home_dir(), 0); + + if ((pExeRoot) && (pAppData) && (pPersonal)) + { + gchar tmp[PATH_MAX+1]; + gchar* p; + + // Build our LOCALEDIR entry + if (0 != (p = g_build_filename(pAppData, "share", "locale", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our GTK_DIR entry + if (0 != (p = g_build_filename(pPersonal, ".gtk-2.0", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONFIG_DIR entry + if (0 != (p = g_build_filename(pAppData, "etc", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ARDOUR_DIR entry + p = ""; // Empty string (temporary) + if (0 != p) + { + g_array_append_val (pFallbackDirs, p); + + // Build our MODULE_DIR entry + strcpy(tmp, pExeRoot); + if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR))) + { + *p = '\0'; + + if (0 != (p = g_build_filename(tmp, 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our DATA_DIR entry + if (0 != (p = g_build_filename(pAppData, "share", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our ICONS_DIR entry (re-use 'tmp') + strcpy(tmp, "/usr/local/share/ardour2"); + if (0 != (p = g_build_filename(tmp, "icons", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our PIXMAPS_DIR entry + if (0 != (p = g_build_filename(tmp, "pixmaps", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our CONTROL_SURFACES_DIR entry + if (0 != (p = g_build_filename(pExeRoot, "surfaces", 0))) + { + g_array_append_val (pFallbackDirs, p); + + // Build our VAMP_DIR entry + p = g_build_filename(pExeRoot, "vamp", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + + // Next, build our LADSPA_PATH entry + p = g_build_filename(Glib::path_get_dirname(pExeRoot).c_str(), "plugins", 0); + if (p) + g_array_append_val (pFallbackDirs, p); + + // And finally, build our VST_PATH entry + if (g_getenv("HOME")) + p = g_build_filename(g_getenv("HOME"), "VST", "plugins", 0); + else + p = g_build_filename(g_get_home_dir(), "VST", "plugins", 0); + + if (p) + g_array_append_val (pFallbackDirs, p); + } + } + } + } + } + } + } + } + } + } + + g_free (pAppData); + g_free (pExeRoot); + g_free (pPersonal); + } + + fallback_dir_vector = fallback_folders = (gchar **) g_array_free (pFallbackDirs, FALSE); + } + } + else + fallback_dir_vector = fallback_folders; + + if (pUsrHome) + g_free (pUsrHome); + + return (fallback_dir_vector); +} +#endif + + +//*************************************************************** +// +// get_platform_fallback_folder() +// +// Returns a const gchar* which points to a string describing +// the full path to the Ardour fallback folder corresponding to +// the supplied index. See 'get_platform_fallback_folders()' for a +// complete list of the supported index enumerations. Calling this +// function will initialize the fallback folder array if it wasn't +// already initiaized. The array should then (eventually) be freed +// using 'free_platform_fallback_folders()'. +// +// Returns: +// +// On Success: A pointer to the path string contained at the +// relevant index. +// On Failure: NULL +// +PBD_API G_CONST_RETURN gchar* PBD_APICALLTYPE +get_platform_fallback_folder (PBD::fallback_folder_t index) +{ + if ((index >= 0) && (index < FALLBACK_FOLDER_MAX)) + return ((G_CONST_RETURN gchar *)get_platform_fallback_folders ()[index]); + else + return (G_CONST_RETURN gchar *) 0; +} + + +//*************************************************************** +// +// alloc_platform_fallback_folders() +// +// Calls 'get_platform_fallback_folders()' to ensure that memory +// for the fallback folder array is already allocated before the +// array gets used. It doesn't cause any problems if the array gets +// used prior to calling this function (since the memory will get +// allocated anyway, on fist usage). Either way however, the momory +// must later be freed using 'free_platform_fallback_folders()'. +// +// Returns: +// +// The value obtained from 'get_platform_fallback_folders()' +// +PBD_API G_CONST_RETURN gchar* G_CONST_RETURN * PBD_APICALLTYPE +alloc_platform_fallback_folders () +{ + return ((G_CONST_RETURN gchar* G_CONST_RETURN *)get_platform_fallback_folders ()); +} + + +//*************************************************************** +// +// free_platform_fallback_folders() +// +// Frees the memory that was previously allocated for the Ardour +// fallback folder array. +// +// Returns: +// +// NONE. +// +PBD_API void PBD_APICALLTYPE +free_platform_fallback_folders () +{ +int index = FOLDER_LOCALE; + + if (fallback_folders) + { + gchar *p = get_platform_fallback_folders()[(fallback_folder_t)index++]; + + while (index < (FALLBACK_FOLDER_MAX+1)) { + if (p) + g_free (p); + + if (index < FALLBACK_FOLDER_MAX) + p = get_platform_fallback_folders()[(fallback_folder_t)index++]; + else + break; + } + + fallback_folders = 0; + } +} + +} // namespace PBD + diff --git a/libs/pbd/file_utils.cc b/libs/pbd/file_utils.cc index 1a32377ff6..50287149e1 100644 --- a/libs/pbd/file_utils.cc +++ b/libs/pbd/file_utils.cc @@ -23,8 +23,8 @@ #include <glib.h> #include <glib/gstdio.h> -#ifdef WIN32 -#include <io.h> // for W_OK +#ifdef COMPILER_MINGW +#include <io.h> // For W_OK #endif #include <glibmm/fileutils.h> @@ -202,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); @@ -235,7 +235,7 @@ exists_and_writable (const std::string & p) make us unwritable. */ - struct stat statbuf; + GStatBuf statbuf; if (g_stat (p.c_str(), &statbuf) != 0) { /* doesn't exist - not writable */ diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc index 40f8cca9d6..5d81cd2fd3 100644 --- a/libs/pbd/fpu.cc +++ b/libs/pbd/fpu.cc @@ -16,7 +16,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#ifndef COMPILER_MSVC #include "libpbd-config.h" #define _XOPEN_SOURCE 600 @@ -141,3 +141,7 @@ FPU::FPU () FPU::~FPU () { } + +#else // COMPILER_MSVC + const char* pbd_fpu = "pbd/msvc/fpu.cc takes precedence over this file"; +#endif // COMPILER_MSVC diff --git a/libs/pbd/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 index 26e9dcc4a4..c72e3eb458 100644 --- a/libs/pbd/localtime_r.cc +++ b/libs/pbd/localtime_r.cc @@ -5,8 +5,8 @@ #ifndef HAVE_LOCALTIME_R #include <time.h> #include <string.h> -#include <pthread.h> +#include "pbd/pthread_utils.h" #include "pbd/localtime_r.h" #ifdef localtime_r diff --git a/libs/pbd/mountpoint.cc b/libs/pbd/mountpoint.cc index b2fb84760d..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,7 +94,7 @@ mountpoint (string path) return best; } -#elif defined(WIN32) +#elif defined(PLATFORM_WINDOWS) string mountpoint (string path) @@ -172,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/mountpoint.cc b/libs/pbd/msvc/mountpoint.cc new file mode 100644 index 0000000000..d30b24462f --- /dev/null +++ b/libs/pbd/msvc/mountpoint.cc @@ -0,0 +1,166 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: mountpoint.cc 3920 2008-10-11 12:34:46Z paul $ +*/ + +#ifdef COMPILER_MSVC + +/* TODO - Still to be implemented */ + +#include <cstdio> +#include <cstring> +#include <string> +#include <cstring> +#include <limits.h> + +#include <pbd/mountpoint.h> + +using std::string; + +#if HAVE_GETMNTENT +#include <mntent.h> + +struct mntent_sorter { + bool operator() (const mntent *a, const mntent *b) { + return strcmp (a->mnt_dir, b->mnt_dir); + } +}; + +string +mountpoint (string path) +{ + FILE *mntf; + mntent *mnt; + unsigned int maxmatch = 0; + unsigned int matchlen; + const char *cpath = path.c_str(); + char best[PATH_MAX+1]; + + if ((mntf = setmntent ("/etc/mtab", "r")) == 0) { + return ""; + } + + best[0] = '\0'; + + while ((mnt = getmntent (mntf))) { + unsigned int n; + + n = 0; + matchlen = 0; + + /* note: strcmp's semantics are not + strict enough to use for this. + */ + + while (cpath[n] && mnt->mnt_dir[n]) { + if (cpath[n] != mnt->mnt_dir[n]) { + break; + } + matchlen++; + n++; + } + + if (cpath[matchlen] == '\0') { + + endmntent (mntf); + return mnt->mnt_dir; + + } else { + + if (matchlen > maxmatch) { + snprintf (best, sizeof(best), "%s", mnt->mnt_dir); + maxmatch = matchlen; + } + } + } + + endmntent (mntf); + + return best; +} + +#else // !HAVE_GETMNTENT + +string +mountpoint (string path) +{ +return ""; + +/* // The rest is commented out temporarily by JE - 30-11-2009 + // (I think this must be the implementation for MacOS). + struct statfs *mntbufp = 0; + int count; + unsigned int maxmatch = 0; + unsigned int matchlen; + const char *cpath = path.c_str(); + char best[PATH_MAX+1]; + + if ((count = getmntinfo(&mntbufp, MNT_NOWAIT)) == 0) { + free(mntbufp); + return "\0"; + } + + best[0] = '\0'; + + for (int i = 0; i < count; ++i) { + unsigned int n = 0; + matchlen = 0; + + // note: strcmp's semantics are not + // strict enough to use for this. + + while (cpath[n] && mntbufp[i].f_mntonname[n]) { + if (cpath[n] != mntbufp[i].f_mntonname[n]) { + break; + } + matchlen++; + n++; + } + + if (cpath[matchlen] == '\0') { + snprintf(best, sizeof(best), "%s", mntbufp[i].f_mntonname); + free(mntbufp); + return best; + + } else { + + if (matchlen > maxmatch) { + snprintf (best, sizeof(best), "%s", mntbufp[i].f_mntonname); + maxmatch = matchlen; + } + } + } + + return best; +*/ +} +#endif // HAVE_GETMNTENT + +#ifdef TEST_MOUNTPOINT + +main (int argc, char *argv[]) +{ + printf ("mp of %s = %s\n", argv[1], mountpoint (argv[1]).c_str()); + exit (0); +} + +#endif // TEST_MOUNTPOINT + +#else // !COMPILER_MSVC + const char* pbd_mountpoint = "original pbd/mountpoint.cc takes precedence over this file"; +#endif // COMPILER_MSVC diff --git a/libs/pbd/msvc/msvc_pbd.cc b/libs/pbd/msvc/msvc_pbd.cc new file mode 100644 index 0000000000..45137da0f3 --- /dev/null +++ b/libs/pbd/msvc/msvc_pbd.cc @@ -0,0 +1,895 @@ +/* + Copyright (C) 2009 John Emmas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifdef COMPILER_MSVC + +#include <WTypes.h> + +extern "C" WINBASEAPI BOOL WINAPI +CreateHardLinkA( LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes ); // Needs kernel32.lib on anything higher than Win2K + +#include <algorithm> +#include <string> +#include <io.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <pbd/error.h> +#include <ardourext/misc.h> +#include <ardourext/pthread.h> // Should ensure that we include the right + // version - but we'll check anyway, later + +#include <glibmm.h> + +#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 + +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +PBD_API int PBD_APICALLTYPE +gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz) // Does this need to be exported ? +{ +FILETIME ft; +unsigned __int64 tmpres = 0; +static int tzflag = 0; + + if (NULL != tv) + { + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + /*converting file time to unix epoch*/ + tmpres /= 10; /*convert into microseconds*/ + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) + { + struct timezone *ptz = static_cast<struct timezone*> (tz); + if (!tzflag) + { + _tzset(); + tzflag++; + } + if (ptz) + { + ptz->tz_minuteswest = _timezone / 60; + ptz->tz_dsttime = _daylight; + } + } + + return 0; +} + +// Define the default comparison operators for Windows (ptw32) 'pthread_t' (not used +// by Ardour AFAIK but would be needed if an array of 'pthread_t' had to be sorted). +#ifndef PTHREAD_H // Defined by PTW32 (Linux and other versions define _PTHREAD_H) +#error "An incompatible version of 'pthread.h' is #included. Use only the Windows (ptw32) version!" +#else +bool operator> (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::greater<void*>()(lhs.p, rhs.p)); +} + +bool operator< (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::less<void*>()(lhs.p, rhs.p)); +} + +bool operator!= (const pthread_t& lhs, const pthread_t& rhs) +{ + return (std::not_equal_to<void*>()(lhs.p, rhs.p)); +} + +bool operator== (const pthread_t& lhs, const pthread_t& rhs) +{ + return (!(lhs != rhs)); +} +#endif + +// Functions supplied (later) to std::transform +//*************************************************************** +// +// invert_backslash() +// +// Examines a supplied ASCII character and (if the character is +// a backslash) converts it to a forward slash, +// +// Returns: +// +// The supplied character (converted, if it was a backslash) +// +char invert_backslash(char character) +{ + if ('\\' == character) + character = '/'; + + return (character); +} + +//*************************************************************** +// +// invert_forwardslash() +// +// Examines a supplied ASCII character and (if the character is +// a forward slash) converts it to a backslash, +// +// Returns: +// +// The supplied character (converted, if it was a fwd slash) +// +char invert_forwardslash(char character) +{ + if ('/' == character) + character = '\\'; + + return (character); +} + + +//*************************************************************** +// +// pread() +// +// Emulates pread() using _lseek()/_read()/_lseek(). +// +// Returns: +// +// On Success: The number of bytes read from the file +// On Failure: -1 +// +PBD_API ssize_t PBD_APICALLTYPE +pread(int handle, void *buf, size_t nbytes, off_t offset) +{ +int old_errno; +ssize_t ret; + + off_t old_offset = _tell(handle); + + if (0 > old_offset) + ret = (-1); + else + { + _lseek(handle, offset, SEEK_SET); + ret = _read(handle, buf, nbytes); + + old_errno = errno; + _lseek(handle, old_offset, SEEK_SET); + errno = old_errno; + } + + return (ret); +} + + +//*************************************************************** +// +// pwrite() +// +// Emulates pwrite() using _lseek()/_write()/_lseek(). +// +// Returns: +// +// On Success: The number of bytes written to the file +// On Failure: -1 +// +PBD_API ssize_t PBD_APICALLTYPE +pwrite(int handle, const void *buf, size_t nbytes, off_t offset) +{ +int old_errno; +ssize_t ret; + + off_t old_offset = _lseek(handle, offset, SEEK_SET); + + if (0 > old_offset) + ret = (-1); + else + { + ret = _write(handle, buf, nbytes); + + old_errno = errno; + _lseek(handle, old_offset, SEEK_SET); + errno = old_errno; + } + + return (ret); +} + +namespace PBD { + +//*************************************************************** +// +// TestForMinimumSpecOS() +// +// Tests the user's OS to see if it is Win2K or later (could be +// expanded quite easily to accommodate other OS's) +// +// Returns: +// +// On Success: TRUE (if the user's OS matches the minimum spec) +// On Failure: FALSE otherwise +// +PBD_API bool PBD_APICALLTYPE +TestForMinimumSpecOS(char *revision /* currently ignored */) +{ +bool bRet = true; +#ifdef PLATFORM_WINDOWS + bRet = false; + HINSTANCE hKernelDll = (HINSTANCE)dlopen("kernel32.dll", RTLD_NOW); + + if (hKernelDll) + { + // 'CreateHardLink()' is only available from Win2K onwards. + if (NULL != dlsym(hKernelDll, "CreateHardLinkA")) + bRet = true; + + dlclose(hKernelDll); + } +#endif + // Other OS's could be accommodated here + + return (bRet); +} + + +//*************************************************************** +// +// realpath() +// +// Emulates POSIX realpath() using Win32 _fullpath(). +// +// Returns: +// +// On Success: A pointer to the resolved (absolute) path +// On Failure: NULL +// +PBD_API char* PBD_APICALLTYPE +realpath (const char *original_path, char resolved_path[_MAX_PATH+1]) +{ +char *pRet = NULL; +bool bIsSymLink = 0; // We'll probably need to test the incoming path + // to find out if it points to a Windows shortcut + // (or a hard link) and set this appropriately. + if (bIsSymLink) + { + // At the moment I'm not sure if Windows '_fullpath()' is directly + // equivalent to POSIX 'realpath()' - in as much as the latter will + // resolve the supplied path if it happens to point to a symbolic + // link ('_fullpath()' probably DOESN'T do this but I'm not really + // sure if Ardour needs such functionality anyway). Therefore we'll + // possibly need to add that functionality here at a later date. + } + else + { + char temp[(MAX_PATH+1)*6]; // Allow for maximum length of a path in UTF8 characters + + // POSIX 'realpath()' requires that the buffer size is at + // least PATH_MAX+1, so assume that the user knew this !! + pRet = _fullpath(temp, Glib::locale_from_utf8(original_path).c_str(), _MAX_PATH); + if (NULL != pRet) + strcpy(resolved_path, Glib::locale_to_utf8(temp).c_str()); + } + + return (pRet); +} + + +//*************************************************************** +// +// opendir() +// +// Creates a pointer to a DIR structure, appropriately filled in +// and ready to begin a directory search iteration. +// +// Returns: +// +// On Success: Pointer to a (heap based) DIR structure +// On Failure: NULL +// +PBD_API DIR* PBD_APICALLTYPE +opendir (const char *szPath) +{ +wchar_t wpath[PATH_MAX+1]; +unsigned int rc; +DIR *pDir = 0; + + errno = 0; + + if (!szPath) + errno = EFAULT; + + if ((!errno) && ('\0' == szPath[0])) + errno = ENOTDIR; + + // Determine if the given path really is a directory + + if (!errno) + if (0 == MultiByteToWideChar (CP_UTF8, 0, (LPCSTR)szPath, -1, (LPWSTR)wpath, sizeof(wpath))) + errno = EFAULT; + + if ((!errno) && ((rc = GetFileAttributesW(wpath)) == -1)) + errno = ENOENT; + + if ((!errno) && (!(rc & FILE_ATTRIBUTE_DIRECTORY))) + // Error. Entry exists but not a directory. */ + errno = ENOTDIR; + + if (!errno) + { + // Allocate enough memory to store DIR structure, plus + // the complete directory path originally supplied. + pDir = (DIR *)malloc(sizeof(DIR) + strlen(szPath) + strlen("\\") + strlen ("*")); + + if (!pDir) + { + // Error - out of memory + errno = ENOMEM; + } + } + + if (!errno) + { + // Create the search expression + strcpy(pDir->dd_name, szPath); + + // Add a backslash if the path doesn't already end with one + if (pDir->dd_name[0] != '\0' && + pDir->dd_name[strlen(pDir->dd_name) - 1] != '/' && + pDir->dd_name[strlen(pDir->dd_name) - 1] != '\\') + { + strcat (pDir->dd_name, "\\"); + } + + // Add the search pattern + strcat(pDir->dd_name, "*"); + + // Initialize handle to -1 so that a premature closedir() + // doesn't try to call _findclose() on it. + pDir->dd_handle = (-1); + + // Initialize the status + pDir->dd_stat = 0; + + // Initialize the dirent structure. 'ino' and 'reclen' are invalid under Win32 + // and 'name' simply points at the appropriate part of the findfirst_t struct. + pDir->dd_dir.d_ino = 0; + pDir->dd_dir.d_reclen = 0; + pDir->dd_dir.d_namlen = 0; + strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name); + + return (pDir); // Succeeded + } + + if (pDir) + free (pDir); + return (DIR *) 0; // Failed +} + + +//*************************************************************** +// +// readdir() +// +// Return a pointer to a dirent struct, filled with information +// about the next entry in the directory. +// +// Returns: +// +// On Success: A pointer to the supplied DIR's 'dirent' struct +// On Failure: NULL +// +PBD_API struct dirent* PBD_APICALLTYPE +readdir (DIR* pDir) +{ +int old_errno = 0; +errno = 0; + + // Check for valid DIR struct + if (!pDir) + errno = EFAULT; + + if ((strcmp(pDir->dd_dir.d_name, pDir->dd_dta.name)) && (!errno)) + // The structure does not seem to be set up correctly + errno = EINVAL; + else + { + if (pDir->dd_stat < 0) + { + // We have already returned all files in this directory + // (or the structure has an invalid dd_stat). + return (struct dirent *)0; + } + else if (pDir->dd_stat == 0) + { + // We haven't started the search yet. + // Start the search + pDir->dd_handle = _findfirst (Glib::locale_from_utf8(pDir->dd_name).c_str(), &(pDir->dd_dta)); + + if (pDir->dd_handle == -1) + // The directory is empty + pDir->dd_stat = -1; + else + pDir->dd_stat = 1; + } + else + { + // Do not return ENOENT on last file in directory + old_errno = errno; + + // Get the next search entry + if (_findnext (pDir->dd_handle, &(pDir->dd_dta))) + { + // We are off the end or otherwise error + errno = old_errno; + _findclose (pDir->dd_handle); + pDir->dd_handle = -1; + pDir->dd_stat = -1; + } + else + // Update to indicate the correct status number + pDir->dd_stat++; + } + + if (pDir->dd_stat > 0) + { + // We successfully got an entry. Details about the file are + // already appropriately filled in except for the length of + // file name. + strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name); + pDir->dd_dir.d_namlen = strlen (pDir->dd_dir.d_name); + return (&pDir->dd_dir); // Succeeded + } + } + + return (struct dirent *) 0; // Failed +} + + +//*************************************************************** +// +// closedir() +// +// Frees the resources allocated by opendir(). +// +// Returns: +// +// On Success: 0 +// On Failure: -1 +// +PBD_API int PBD_APICALLTYPE +closedir (DIR *pDir) +{ +int rc = 0; + + errno = 0; + + if (!pDir) + errno = EFAULT; + else + { + if ((-1) != pDir->dd_handle) + rc = _findclose (pDir->dd_handle); + + // Free the DIR structure + free (pDir); + + return rc; // Succeeded + } + + return (-1); // Failed +} + +//*************************************************************** +// +// mkstemp() +// +// Emulates Linux mkstemp() using Win32 _mktemp() and _open() etc. +// +// Returns: +// +// On Success: A file descriptor for the opened file. +// On Failure: (-1) +// +PBD_API int PBD_APICALLTYPE +mkstemp (char *template_name) +{ +int ret = (-1); +char *szFileName; +char szTempPath[PATH_MAX+100]; // Just ensure we have plenty of buffer space + + if (NULL != (szFileName = _mktemp(template_name))) + { + if (0 != ::GetTempPathA(sizeof(szTempPath), szTempPath)) + { + strcat(szTempPath, szFileName); + ret = _open(szTempPath, (_O_CREAT|_O_BINARY|_O_TEMPORARY|_O_RDWR|_O_TRUNC), _S_IWRITE); + } + } + + return (ret); +} + + +//*************************************************************** +// +// ntfs_link() +// +// Emulates Linux link() using Win32 CreateHardLink()(NTFS only). +// +// Returns: +// +// On Success: Non-zero. +// On Failure: Zero (call 'GetLastError()' to retrieve info) +// +PBD_API int PBD_APICALLTYPE +ntfs_link (const char *existing_filepath, const char *link_filepath) +{ +int ret = 1; // 'ERROR_INVALID_FUNCTION' +bool bValidPath = false; + + // Make sure we've been sent a valid input string + if (existing_filepath && link_filepath) + { + std::string strRoot = existing_filepath; + + if ((1 < strRoot.length()) && ('\\' == existing_filepath[0]) && ('\\' == existing_filepath[1])) + { + int slashcnt = 0; + + // We've been sent a network path. Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + // Now, if there are less than four slashes, add a fourth one or abort + std::string::iterator iter = strRoot.begin(); + while ((slashcnt < 4) && (iter != strRoot.end())) + { + if ('/' == (*iter)) + slashcnt++; + + ++iter; + } + + if (slashcnt > 2) + { + // If only 3 slashes were counted, add a trailing slash + if (slashcnt == 3) + strRoot += '/'; + + // Now find the position of the fourth slash + iter = strRoot.begin(); + int charcnt = 0; + for (slashcnt=0; slashcnt<4;) + { + charcnt++; + + if ('/' == (*iter)) + slashcnt++; + + if (++iter == strRoot.end()) + break; + } + + strRoot.resize(charcnt); + bValidPath = true; + } + } + else + { + // Assume a standard Windows style path + if (1 < strRoot.length() && (':' == existing_filepath[1])) + { + // Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + if (2 == strRoot.length()) + strRoot += '/'; + + if ('/' == strRoot[2]) + { + strRoot.resize(3); + bValidPath = true; + } + } + } + + if (bValidPath) + { + char szFileSystemType[_MAX_PATH+1]; + + // Restore the original backslashes + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash); + + // Windows only supports hard links for the NTFS filing + // system, so let's make sure that's what we're using!! + if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1)) + { + std::string strRootFileSystemType = szFileSystemType; + std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper); +#if (_WIN32_WINNT >= 0x0500) + if (0 == strRootFileSystemType.compare("NTFS")) + { + if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards + if (0 == CreateHardLinkA(link_filepath, existing_filepath, NULL)) + { // Note that the above API call cannot create a link to a directory, so + // should we also be checking that the supplied path was actually a file? + ret = GetLastError(); + } + else + SetLastError(ret = 0); // 'NO_ERROR' + } + else + { + ret = 4300; // 'ERROR_INVALID_MEDIA' + } +#endif + } + } + else + ret = 123; // 'ERROR_INVALID_NAME' + } + else + ret = 161; // 'ERROR_BAD_PATHNAME' + + if (ret) + { + SetLastError(ret); + return (-1); + } + else + return (0); +} + + +//*************************************************************** +// +// ntfs_unlink() +// +// Emulates Linux unlink() using Win32 DeleteFile()(NTFS only). +// +// Returns: +// +// On Success: Non-zero. +// On Failure: Zero (call 'GetLastError()' to retrieve info) +// +PBD_API int PBD_APICALLTYPE +ntfs_unlink (const char *link_filepath) +{ +int ret = 1; // 'ERROR_INVALID_FUNCTION' +bool bValidPath = false; + + // Make sure we've been sent a valid input string + if (link_filepath) + { + std::string strRoot = link_filepath; + + if ((1 < strRoot.length()) && ('\\' == link_filepath[0]) && ('\\' == link_filepath[1])) + { + int slashcnt = 0; + + // We've been sent a network path. Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + // Now, if there are less than four slashes, add a fourth one or abort + std::string::iterator iter = strRoot.begin(); + while ((slashcnt < 4) && (iter != strRoot.end())) + { + if ('/' == (*iter)) + slashcnt++; + + ++iter; + } + + if (slashcnt > 2) + { + // If only 3 slashes were counted, add a trailing slash + if (slashcnt == 3) + strRoot += '/'; + + // Now find the position of the fourth slash + iter = strRoot.begin(); + int charcnt = 0; + for (slashcnt=0; slashcnt<4;) + { + charcnt++; + + if ('/' == (*iter)) + slashcnt++; + + if (++iter == strRoot.end()) + break; + } + + strRoot.resize(charcnt); + bValidPath = true; + } + } + else + { + // Assume a standard Windows style path + if (1 < strRoot.length() && (':' == link_filepath[1])) + { + // Convert backslashes to forward slashes temporarily. + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash); + + if (2 == strRoot.length()) + strRoot += '/'; + + if ('/' == strRoot[2]) + { + strRoot.resize(3); + bValidPath = true; + } + } + } + + if (bValidPath) + { + char szFileSystemType[_MAX_PATH+1]; + + // Restore the original backslashes + std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash); + + // Windows only supports hard links for the NTFS filing + // system, so let's make sure that's what we're using!! + if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1)) + { + std::string strRootFileSystemType = szFileSystemType; + std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper); +#if (_WIN32_WINNT >= 0x0500) + if (0 == strRootFileSystemType.compare("NTFS")) + if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards + if (0 == DeleteFileA(link_filepath)) + ret = GetLastError(); + else + ret = 0; // 'NO_ERROR' +#endif + } + } + else + ret = 123; // 'ERROR_INVALID_NAME' + } + else + ret = 161; // 'ERROR_BAD_PATHNAME' + + if (ret) + { + SetLastError(ret); + return (-1); + } + else + return (0); +} + +} // namespace PBD + + +//*************************************************************** +// +// dlopen() +// +// Emulates POSIX dlopen() using Win32 LoadLibrary(). +// +// Returns: +// +// On Success: A handle to the opened DLL +// On Failure: NULL +// +PBD_API void* PBD_APICALLTYPE +dlopen (const char *file_name, int mode) +{ + // Note that 'mode' is ignored in Win32 + return(::LoadLibraryA(Glib::locale_from_utf8(file_name).c_str())); +} + + +//*************************************************************** +// +// dlclose() +// +// Emulates POSIX dlclose() using Win32 FreeLibrary(). +// +// Returns: +// +// On Success: A non-zero number +// On Failure: 0 +// +PBD_API int PBD_APICALLTYPE +dlclose (void *handle) +{ + return (::FreeLibrary((HMODULE)handle)); +} + + +//*************************************************************** +// +// dlsym() +// +// Emulates POSIX dlsym() using Win32 GetProcAddress(). +// +// Returns: +// +// On Success: A pointer to the found function or symbol +// On Failure: NULL +// +PBD_API void* PBD_APICALLTYPE +dlsym (void *handle, const char *symbol_name) +{ + // First test for RTLD_DEFAULT and RTLD_NEXT + if ((handle == 0/*RTLD_DEFAULT*/) || (handle == ((void *) -1L)/*RTLD_NEXT*/)) + { + return 0; // Not yet supported for Win32 + } + else + return (::GetProcAddress((HMODULE)handle, symbol_name)); +} + +#define LOCAL_ERROR_BUF_SIZE 1024 +static char szLastWinError[LOCAL_ERROR_BUF_SIZE]; +//*************************************************************** +// +// dlerror() +// +// Emulates POSIX dlerror() using Win32 GetLastError(). +// +// Returns: +// +// On Success: The translated message corresponding to the +// last error +// On Failure: NULL (if the last error was ERROR_SUCCESS) +// +PBD_API char* PBD_APICALLTYPE +dlerror () +{ + DWORD dwLastErrorId = GetLastError(); + if (ERROR_SUCCESS == dwLastErrorId) + return 0; + else + { + if (0 == FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwLastErrorId, + 0, + szLastWinError, + LOCAL_ERROR_BUF_SIZE, + 0)) + { + sprintf(szLastWinError, "Could not decipher the previous error message"); + } + + // POSIX dlerror() seems to reset the + // error system, so emulate that here + SetLastError(ERROR_SUCCESS); + } + + return(szLastWinError); +} + +#endif // COMPILER_MSVC diff --git a/libs/pbd/msvc/msvc_poll.cc b/libs/pbd/msvc/msvc_poll.cc new file mode 100644 index 0000000000..e12ef2bbef --- /dev/null +++ b/libs/pbd/msvc/msvc_poll.cc @@ -0,0 +1,215 @@ +/* + Copyright (C) 2009 John Emmas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifdef COMPILER_MSVC + +//#include <glib/gtimer.h> +#include "pbd/msvc_pbd.h" + +#ifndef _DWORD_DEFINED +#define _DWORD_DEFINED +typedef unsigned long DWORD; +#endif // !_DWORD_DEFINED + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Note that this entire strategy failed to work, at least for pipes. It turned * + * out that Windows 'tell()' always returns 0 when used on a pipe. This strategy * + * is now deprecated, having been replaced by a new pipe-like object, which I've * + * called 'PBD::pipex'. This polling functionality is included here mostly so * + * that Ardour will build and launch under Windows. However, any module that * + * relies on polling a pipe will eventually need to use the new pipex object. * + * This code will allow it to compile and link successfully, although it won't * + * poll successfully at run time. Having said that, these functions might well * + * work for ports and/or other machanisms that get represented by a file handle. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +int poll_input (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout) +{ +DWORD dwOldTickCount, + dwNewTickCount = GetTickCount(); +bool input = false, + error = false; +int ret = 0; + + if (NULL != fds) + { + nfds_t loop; + short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND); + + errno = NO_ERROR; + + do + { + dwOldTickCount = dwNewTickCount; + + for (loop=0; loop<nfds; loop++) + fds[loop].revents = 0; + + for (loop=0; (loop<nfds && !error); loop++) + { + if (!(fds[loop].events & ev_mask)) + { + long pos = _tell(fds[loop].fd); + + if (0 > pos) + { + // An error occured ('errno' should have been set by '_tell()') + ret = (-1); + fds[loop].revents = POLLERR; + if (fds[loop].events & POLLRDNORM) + fds[loop].revents |= POLLRDNORM; + if (fds[loop].events & POLLRDBAND) + fds[loop].revents |= POLLRDBAND; + if (fds[loop].events & POLLPRI) + fds[loop].revents |= POLLPRI; + + // Do we want to abort on error? + if (fds[loop].events & POLLERR) + error = true; + } + else if (pos > 0) + { + // Input characters were found for this fd + ret += 1; + if (fds[loop].events & POLLRDNORM) + fds[loop].revents |= POLLRDNORM; + if (fds[loop].events & POLLRDBAND) + fds[loop].revents |= POLLRDBAND; + if (fds[loop].events & POLLPRI) + fds[loop].revents |= POLLPRI; + + // Do we want to abort on input? + if ((fds[loop].events & POLLIN) || + (fds[loop].events & POLLPRI) || + (fds[loop].events & POLLRDNORM) || + (fds[loop].events & POLLRDBAND)) + input = true; + } + } + } + + if (input) + break; + + dwNewTickCount = GetTickCount(); + elapsed_time += (dwNewTickCount-dwOldTickCount); + // Note that the above will wrap round if the user leaves + // his computer powered up for more than about 50 days! + + // Sleep briefly because GetTickCount() only has an accuracy of 10mS + Sleep(10); // For some reason 'g_usleep()' craps over everything here. Different 'C' runtimes??? + + } while ((!error) && ((timeout == (-1)) || (elapsed_time < timeout))); + } + else + { + errno = ERROR_BAD_ARGUMENTS; + ret = (-1); + } + + return (ret); +} + +int poll_output (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout) +{ +int ret = 0; // This functionality is not yet implemented + + if (NULL != fds) + { + // Just flag whichever pollfd was specified for writing + short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND); + + errno = NO_ERROR; + elapsed_time = 0; + + for (nfds_t loop=0; loop<nfds; loop++) + { + if (fds[loop].events & ev_mask) + { + fds[loop].revents = POLLNVAL; + errno = ERROR_INVALID_ACCESS; + ret = (-1); + } + } + } + else + { + errno = ERROR_BAD_ARGUMENTS; + ret = (-1); + } + + return (ret); +} + +//*************************************************************** +// +// poll() +// +// Emulates POSIX poll() using Win32 _tell(). +// +// Returns: +// +// On Success: A positive integer indicating the total number +// of file descriptors that were available for +// writing or had data available for reading. +// On Failure: -1 (the actual error is saved in 'errno'). +// +PBD_API int PBD_APICALLTYPE +poll (struct pollfd *fds, nfds_t nfds, int timeout) +{ +int elapsed_time = 0; +int ret = (-1); + + // Note that this functionality is not fully implemented. + // At the time of writing, Ardour seems only to poll on + // read pipes. Therefore return an error if any write + // pipe seems to have been specified or if too many file + // descriptors were passed. + short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND); + + if ((nfds > OPEN_MAX) || (nfds > NPOLLFILE)) + { + errno = ERROR_TOO_MANY_OPEN_FILES; + } + else + { + ret = 0; + + for (nfds_t loop=0; loop<nfds; loop++) + { + if (fds[loop].events & ev_mask) + { + ret = poll_output(fds, nfds, elapsed_time, timeout); + break; + } + } + + if (0 == ret) + { + // Poll for input + ret = poll_input(fds, nfds, elapsed_time, timeout); + } + } + + return (ret); +} + +#endif //COMPILER_MSVC diff --git a/libs/pbd/pathexpand.cc b/libs/pbd/pathexpand.cc index 89fc148ad7..3f1f1cf670 100644 --- a/libs/pbd/pathexpand.cc +++ b/libs/pbd/pathexpand.cc @@ -23,7 +23,7 @@ #include <cerrno> #include <cstdlib> -#include <regex.h> +#include <boost/regex.h> #include <glibmm/miscutils.h> @@ -36,7 +36,7 @@ using std::vector; string PBD::canonical_path (const std::string& path) { -#ifdef WIN32 +#ifdef COMPILER_MINGW return path; #else char buf[PATH_MAX+1]; 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 02b42fdead..9c405745ac 100644 --- a/libs/pbd/pbd/abstract_ui.cc +++ b/libs/pbd/pbd/abstract_ui.cc @@ -28,6 +28,15 @@ #include "i18n.h" +#ifdef COMPILER_MSVC +#include <ardourext/misc.h> // Needed for 'DECLARE_DEFAULT_COMPARISONS'. Objects in an STL container can be + // searched and sorted. Thus, when instantiating the container, MSVC complains + // if the type of object being contained has no appropriate comparison operators + // defined (specifically, if operators '<' and '==' are undefined). This seems + // to be the case with ptw32 'pthread_t' which is a simple struct. +DECLARE_DEFAULT_COMPARISONS(pthread_t) +#endif + using namespace std; template<typename RequestBuffer> void diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h index 686af485e6..d947a06b34 100644 --- a/libs/pbd/pbd/base_ui.h +++ b/libs/pbd/pbd/base_ui.h @@ -92,7 +92,7 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop virtual void thread_init () {}; -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS static gboolean _request_handler (gpointer); bool request_handler (); #else @@ -114,7 +114,7 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop std::string _name; BaseUI* base_ui_instance; -#ifndef WIN32 +#ifndef PLATFORM_WINDOWS CrossThreadChannel request_channel; #endif diff --git a/libs/pbd/pbd/fallback_folders.h b/libs/pbd/pbd/fallback_folders.h new file mode 100644 index 0000000000..60935b4424 --- /dev/null +++ b/libs/pbd/pbd/fallback_folders.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2009 John Emmas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef __platform_fallback_folders_h__ +#define __platform_fallback_folders_h__ + +#include <pbd/msvc_pbd.h> +#include <glib/gtypes.h> + +#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!! + PBD_API gchar* PBD_APICALLTYPE get_win_special_folder (int csidl); +#endif + +namespace PBD { + + typedef enum fallback_folder_t { + FOLDER_LOCALE, + FOLDER_GTK, + FOLDER_CONFIG, + FOLDER_ARDOUR, + FOLDER_MODULE, + FOLDER_DATA, + FOLDER_ICONS, + FOLDER_PIXMAPS, + FOLDER_CONTROL_SURFACES, + FOLDER_VAMP, + FOLDER_LADSPA, + FOLDER_VST, + FOLDER_BUNDLED_LV2, + FALLBACK_FOLDER_MAX + }; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + PBD_API G_CONST_RETURN gchar* PBD_APICALLTYPE get_platform_fallback_folder (PBD::fallback_folder_t index); + PBD_API G_CONST_RETURN gchar* G_CONST_RETURN * PBD_APICALLTYPE alloc_platform_fallback_folders (); + PBD_API void PBD_APICALLTYPE free_platform_fallback_folders (); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +} // namespace PBD + +#endif /* __platform_fallback_folders_h__ */ diff --git a/libs/pbd/pbd/localeguard.h b/libs/pbd/pbd/localeguard.h new file mode 100644 index 0000000000..20899b5c80 --- /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 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 index 2e7c7aa149..ad5b89d134 100644 --- a/libs/pbd/pbd/localtime_r.h +++ b/libs/pbd/pbd/localtime_r.h @@ -2,6 +2,12 @@ #define PBD_LOCALTIME_R #include <time.h> -extern struct tm *localtime_r(const time_t *const timep, struct tm *p_tm); +#ifdef COMPILER_MSVC + #define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) +#else + extern struct tm *localtime_r(const time_t *const timep, struct tm *p_tm); +#endif #endif diff --git a/libs/pbd/pbd/msvc_pbd.h b/libs/pbd/pbd/msvc_pbd.h new file mode 100644 index 0000000000..1c971308d7 --- /dev/null +++ b/libs/pbd/pbd/msvc_pbd.h @@ -0,0 +1,235 @@ +/* + Copyright (C) 2009 John Emmas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#ifndef _msvc_pbd_h_ +#define _msvc_pbd_h_ + +#ifdef PBD_IS_IN_WIN_STATIC_LIB // #define if your project uses libpbd (under Windows) as a static library +#define PBD_IS_IN_WINDLL 0 +#endif + +#ifdef COMPILER_MSVC +#include <sys/time.h> +#else +#include <ardourext/misc.h> +#include <ardourext/sys/time.h> +#endif + +#if !defined(PBD_IS_IN_WINDLL) + #if defined(COMPILER_MSVC) || defined(COMPILER_MINGW) + // If you need '__declspec' compatibility, add extra compilers to the above as necessary + #define PBD_IS_IN_WINDLL 1 + #else + #define PBD_IS_IN_WINDLL 0 + #endif +#endif + +#if PBD_IS_IN_WINDLL && !defined(PBD_API) + #if defined(BUILDING_PBD) + #define PBD_API __declspec(dllexport) + #define PBD_APICALLTYPE __stdcall + #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point + #define PBD_API __declspec(dllimport) + #define PBD_APICALLTYPE __stdcall + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#elif !defined(PBD_API) + // Other compilers / platforms could be accommodated here + #define PBD_API + #define PBD_APICALLTYPE +#endif + +#ifndef _MAX_PATH +#define _MAX_PATH 260 +#endif +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// This function is (hopefully) temporary and is placed here +// because 'g_usleep()' doesn't seem to work very well for glib-win32 +void pbd_g_usleep (unsigned long microseconds); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#ifndef POLLIN +#define POLLIN 1 +#define POLLPRI 2 +#define POLLOUT 4 +#define POLLERR 8 +#define POLLHUP 16 +#define POLLNVAL 32 +#define NPOLLFILE 64 + +#define POLLRDNORM POLLIN +#define POLLRDBAND POLLIN +#define POLLWRNORM POLLOUT +#define POLLWRBAND POLLOUT +#endif + +#ifdef PLATFORM_WINDOWS + +#ifndef PBDEXTN_API + #if defined(BUILDING_PBDEXTN) + #define PBDEXTN_API __declspec(dllexport) + #define PBDEXTN_APICALLTYPE __cdecl + #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point + #define PBDEXTN_API __declspec(dllimport) + #define PBDEXTN_APICALLTYPE __cdecl + #else + #error "Attempting to define __declspec with an incompatible compiler !" + #endif +#endif // PBDEXTN_API + +#ifndef CYGIMPORT_API + #define CYGIMPORT_API __declspec(dllimport) + #define CYGIMPORT_APICALLTYPE __cdecl +#endif // CYGIMPORT_API + +#ifndef __THROW +#define __THROW throw() +#endif + +#ifndef RTLD_DEFAULT +#define RTLD_DEFAULT ((void *) 0) +#define RTLD_NEXT ((void *) -1L) +#define RTLD_LAZY 0x00001 +#define RTLD_NOW 0x00002 +#define RTLD_BINDING_MASK 0x00003 +#define RTLD_NOLOAD 0x00004 +#define RTLD_GLOBAL 0x00004 +#define RTLD_DEEPBIND 0x00008 +#endif + +#ifndef OPEN_MAX +#define OPEN_MAX 32 +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +PBDEXTN_API int PBDEXTN_APICALLTYPE cyginit (unsigned int result); +PBD_API int PBD_APICALLTYPE dlclose (void *handle) __THROW; +PBD_API void* PBD_APICALLTYPE dlopen (const char *file_name, int mode) __THROW; +PBD_API void* PBD_APICALLTYPE dlsym (void *handle, const char *symbol_name) __THROW; +PBD_API char* PBD_APICALLTYPE dlerror () __THROW; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#ifndef __CYGWIN__ +#include <rpc.h> +#include <io.h> +#include <sys/types.h> + +typedef int (FAR PBDEXTN_APICALLTYPE *CYGINIT_API)(unsigned int); + +#ifndef FILENAME_MAX +#define FILENAME_MAX (260) +#endif + +#ifndef _SSIZE_T_ +#define _SSIZE_T_ +typedef long _ssize_t; + +#ifndef _NO_OLDNAMES +typedef _ssize_t ssize_t; +#endif +#endif /* ! _SSIZE_T_ */ + +struct dirent +{ + long d_ino; // Always zero + unsigned short d_reclen; // Always zero + unsigned short d_namlen; // Length of name in d_name + char d_name[FILENAME_MAX]; // File name +}; + +// This is an internal data structure. Do not use it +// except as an argument to one of the functions below. +typedef struct +{ + // Disk transfer area for this dir + struct _finddata_t dd_dta; + + // 'dirent' struct to return from dir (NOTE: this + // is not thread safe). + struct dirent dd_dir; + + // '_findnext()' handle + long dd_handle; + + // Current status of search: + // 0 = not started yet (next entry to read is first entry) + // -1 = off the end + // Otherwise - positive (0 based) index of next entry + int dd_stat; + + // Full path for dir with search pattern (struct will be extended) + char dd_name[1]; +} DIR; + +struct pollfd +{ + int fd; + short events; + short revents; +}; + +typedef unsigned int nfds_t; + +PBD_API int PBD_APICALLTYPE gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz); +PBD_API ssize_t PBD_APICALLTYPE pread(int handle, void *buf, size_t nbytes, off_t offset); +PBD_API ssize_t PBD_APICALLTYPE pwrite(int handle, const void *buf, size_t nbytes, off_t offset); +PBD_API int PBD_APICALLTYPE poll(struct pollfd *fds, nfds_t nfds, int timeout); + +namespace PBD { + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +PBD_API bool PBD_APICALLTYPE TestForMinimumSpecOS(char *revision="currently ignored"); +PBD_API char* PBD_APICALLTYPE realpath (const char *original_path, char resolved_path[_MAX_PATH+1]); +PBD_API int PBD_APICALLTYPE mkstemp (char *template_name); +PBD_API int PBD_APICALLTYPE ntfs_link (const char *existing_filepath, const char *link_filepath); +PBD_API int PBD_APICALLTYPE ntfs_unlink (const char *link_filepath); + +// These are used to replicate 'dirent.h' functionality +PBD_API DIR* PBD_APICALLTYPE opendir (const char *szPath); +PBD_API struct dirent* PBD_APICALLTYPE readdir (DIR *pDir); +PBD_API int PBD_APICALLTYPE closedir (DIR *pDir); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +} // namespace PBD + +#endif // !__CYGWIN__ +#endif // PLATFORM_WINDOWS +#endif // _msvc_pbd_h_ diff --git a/libs/pbd/pbd/pathscanner.h b/libs/pbd/pbd/pathscanner.h index 1b7ef58655..796648de0f 100644 --- a/libs/pbd/pbd/pathscanner.h +++ b/libs/pbd/pbd/pathscanner.h @@ -22,7 +22,11 @@ #include <vector> #include <string> +#ifdef COMPILER_MSVC +#include <ardourext/misc.h> +#else #include <regex.h> +#endif class PathScanner diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h index 793c3a1980..3d89d5581e 100644 --- a/libs/pbd/pbd/pthread_utils.h +++ b/libs/pbd/pbd/pthread_utils.h @@ -20,7 +20,11 @@ #ifndef __pbd_pthread_utils__ #define __pbd_pthread_utils__ +#ifdef COMPILER_MSVC +#include <ardourext/pthread.h> +#else #include <pthread.h> +#endif #include <signal.h> #include <string> #include <stdint.h> diff --git a/libs/pbd/pbd/ringbuffer.h b/libs/pbd/pbd/ringbuffer.h index f14fa71851..a1a6151542 100644 --- a/libs/pbd/pbd/ringbuffer.h +++ b/libs/pbd/pbd/ringbuffer.h @@ -198,7 +198,7 @@ RingBuffer<T>::write (T const *src, guint cnt) } template<class T> void -RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec) +RingBuffer<T>::get_read_vector (typename RingBuffer<T>::rw_vector *vec) { guint free_cnt; @@ -238,7 +238,7 @@ RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec) } template<class T> void -RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec) +RingBuffer<T>::get_write_vector (typename RingBuffer<T>::rw_vector *vec) { guint free_cnt; diff --git a/libs/pbd/pbd/semaphore.h b/libs/pbd/pbd/semaphore.h index e54063a15a..5f0a2df2c0 100644 --- a/libs/pbd/pbd/semaphore.h +++ b/libs/pbd/pbd/semaphore.h @@ -22,7 +22,7 @@ #ifdef __APPLE__ # include <mach/mach.h> -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) # include <windows.h> #else # include <semaphore.h> @@ -69,7 +69,7 @@ public: private: #if defined(__APPLE__) semaphore_t _sem; // sem_t is a worthless broken mess on OSX -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) HANDLE _sem; // types are overrated anyway #else sem_t _sem; @@ -114,7 +114,7 @@ Semaphore::try_wait() return semaphore_timedwait(_sem, zero) == KERN_SUCCESS; } -#elif defined(_WIN32) +#elif defined(PLATFORM_WINDOWS) inline Semaphore::Semaphore(unsigned initial) @@ -151,7 +151,7 @@ Semaphore::try_wait() return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0; } -#else /* !defined(__APPLE__) && !defined(_WIN32) */ +#else /* !defined(__APPLE__) && !defined(PLATFORM_WINDOWS) */ Semaphore::Semaphore(unsigned initial) { diff --git a/libs/pbd/pbd/semutils.h b/libs/pbd/pbd/semutils.h index 0e8bed0512..af5c201b85 100644 --- a/libs/pbd/pbd/semutils.h +++ b/libs/pbd/pbd/semutils.h @@ -19,7 +19,7 @@ #ifndef __pbd_semutils_h__ #define __pbd_semutils_h__ -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS #include <windows.h> #else #include <semaphore.h> @@ -29,7 +29,7 @@ namespace PBD { class ProcessSemaphore { private: -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS HANDLE _sem; #elif __APPLE__ @@ -44,7 +44,7 @@ class ProcessSemaphore { ProcessSemaphore (const char* name, int val); ~ProcessSemaphore (); -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS int signal (); int wait (); diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h index 11ff2bf321..e9582a1b53 100644 --- a/libs/pbd/pbd/undo.h +++ b/libs/pbd/pbd/undo.h @@ -25,7 +25,11 @@ #include <map> #include <sigc++/slot.h> #include <sigc++/bind.h> +#ifndef COMPILER_MSVC #include <sys/time.h> +#else +#include <ardourext/misc.h> +#endif #include "pbd/command.h" diff --git a/libs/pbd/pthread_utils.cc b/libs/pbd/pthread_utils.cc index 96cf99716f..91d93ec4f8 100644 --- a/libs/pbd/pthread_utils.cc +++ b/libs/pbd/pthread_utils.cc @@ -28,6 +28,14 @@ #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::list<pthread_t> ThreadMap; diff --git a/libs/pbd/resource.cc b/libs/pbd/resource.cc index b2988b6314..9d6f8b1746 100644 --- a/libs/pbd/resource.cc +++ b/libs/pbd/resource.cc @@ -17,7 +17,7 @@ */ -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS #include <stdio.h> #else #include <sys/time.h> @@ -33,7 +33,7 @@ get_resource_limit (ResourceType resource, ResourceLimit& limit) { if (resource == OpenFiles) { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS limit.current_limit = _getmaxstdio(); limit.max_limit = 2048; return true; @@ -55,7 +55,7 @@ set_resource_limit (ResourceType resource, const ResourceLimit& limit) { if (resource == OpenFiles) { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS // no soft and hard limits on windows rlimit_t new_max = _setmaxstdio(limit.current_limit); diff --git a/libs/pbd/search_path.cc b/libs/pbd/search_path.cc index 3f7be5aa56..e56e22fee3 100644 --- a/libs/pbd/search_path.cc +++ b/libs/pbd/search_path.cc @@ -27,7 +27,7 @@ using namespace std; namespace { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS const char * const path_delimiter = ";"; #else const char * const path_delimiter = ":"; diff --git a/libs/pbd/semutils.cc b/libs/pbd/semutils.cc index e5df2e5c44..e5e5898218 100644 --- a/libs/pbd/semutils.cc +++ b/libs/pbd/semutils.cc @@ -23,7 +23,7 @@ using namespace PBD; ProcessSemaphore::ProcessSemaphore (const char* name, int val) { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS if ((_sem = CreateSemaphore(NULL, val, 32767, name)) == NULL) { throw failed_constructor (); } @@ -48,14 +48,14 @@ ProcessSemaphore::ProcessSemaphore (const char* name, int val) ProcessSemaphore::~ProcessSemaphore () { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS CloseHandle(_sem); #elif __APPLE__ sem_close (ptr_to_sem()); #endif } -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS int ProcessSemaphore::signal () 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 0cbe5baf32..458105d177 100644 --- a/libs/pbd/test/filesystem_test.cc +++ b/libs/pbd/test/filesystem_test.cc @@ -10,7 +10,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION (FilesystemTest); void FilesystemTest::testPathIsWithin () { -#ifndef WIN32 +#ifndef PLATFORM_WINDOWS system ("rm -r foo"); CPPUNIT_ASSERT (g_mkdir_with_parents ("foo/bar/baz", 0755) == 0); diff --git a/libs/pbd/test/test_common.cc b/libs/pbd/test/test_common.cc index 16da3ed2a8..397a69ad8c 100644 --- a/libs/pbd/test/test_common.cc +++ b/libs/pbd/test/test_common.cc @@ -28,7 +28,7 @@ PBD::SearchPath test_search_path () { -#ifdef WIN32 +#ifdef PLATFORM_WINDOWS std::string wsp(g_win32_get_package_installation_directory_of_module(NULL)); return Glib::build_filename (wsp, "pbd_testdata"); #else diff --git a/libs/pbd/transmitter.cc b/libs/pbd/transmitter.cc index a172ac457d..e4266d34d7 100644 --- a/libs/pbd/transmitter.cc +++ b/libs/pbd/transmitter.cc @@ -84,14 +84,20 @@ Transmitter::deliver () /* do the right thing if this should not return */ if (does_not_return()) { -#ifndef WIN32 +#ifndef PLATFORM_WINDOWS +// TODO !!!! Commented out temporarily (for Windows) sigset_t mask; sigemptyset (&mask); sigsuspend (&mask); -#endif /*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 1a988b9820..8b55ab3381 100644 --- a/libs/pbd/uuid.cc +++ b/libs/pbd/uuid.cc @@ -20,10 +20,8 @@ #include "pbd/uuid.h" -using namespace PBD; - -UUID& -UUID::operator= (std::string const & str) +PBD::UUID& +PBD::UUID::operator= (std::string const & str) { boost::uuids::string_generator gen; *((boost::uuids::uuid*) this) = gen (str); @@ -31,7 +29,7 @@ UUID::operator= (std::string const & str) } std::string -UUID::to_s () const +PBD::UUID::to_s () const { return std::string ((const char*) data, size()); } diff --git a/libs/pbd/xml++.cc b/libs/pbd/xml++.cc index a1fa77db66..69187995a1 100644 --- a/libs/pbd/xml++.cc +++ b/libs/pbd/xml++.cc @@ -167,6 +167,7 @@ XMLTree::write() const void XMLTree::debug(FILE* out) const { +#ifdef LIBXML_DEBUG_ENABLED xmlDocPtr doc; XMLNodeList children; @@ -176,6 +177,7 @@ XMLTree::debug(FILE* out) const writenode(doc, _root, doc->children, 1); xmlDebugDumpDocument (out, doc); xmlFreeDoc(doc); +#endif } const string& diff --git a/msvc_extra_headers/ardourext/float_cast.h.input b/msvc_extra_headers/ardourext/float_cast.h.input new file mode 100644 index 0000000000..a5a82e3668 --- /dev/null +++ b/msvc_extra_headers/ardourext/float_cast.h.input @@ -0,0 +1,73 @@ +/* +** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> +** +** Permission to use, copy, modify, distribute, and sell this file for any +** purpose is hereby granted without fee, provided that the above copyright +** and this permission notice appear in all copies. No representations are +** made about the suitability of this software for any purpose. It is +** provided "as is" without express or implied warranty. +*/ + +/* Version 1.1 */ + + +/*============================================================================ +** On Intel Pentium processors (especially PIII and probably P4), converting +** from float to int is very slow. To meet the C specs, the code produced by +** most C compilers targeting Pentium needs to change the FPU rounding mode +** before the float to int conversion is performed. +** +** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It +** is this flushing of the pipeline which is so slow. +** +** Fortunately the ISO C99 specifications define the functions lrint, lrintf, +** llrint and llrintf which fix this problem as a side effect. +** +** On Unix-like systems, the configure process should have detected the +** presence of these functions. If they weren't found we have to replace them +** here with a standard C cast. +*/ + +/* +** The C99 prototypes for lrint and lrintf are as follows: +** +** long int lrintf (float x) ; +** long int lrint (double x) ; +*/ +#ifndef __FLOAT_CAST_H__ // Added by JE - 30-11-2009 +#define __FLOAT_CAST_H__ +#if (defined (WIN32) || defined (_WIN32)) + + #include <math.h> + + /* Win32 doesn't seem to have these functions. + ** Therefore implement inline versions of these functions here. + */ + + __inline long int + lrint (double flt) + { int intgr; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + + __inline long int + lrintf (float flt) + { int intgr; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + +#endif + +#endif // __FLOAT_CAST_H__ diff --git a/msvc_extra_headers/ardourext/libcharset.h.input b/msvc_extra_headers/ardourext/libcharset.h.input new file mode 100644 index 0000000000..2baf24c8b3 --- /dev/null +++ b/msvc_extra_headers/ardourext/libcharset.h.input @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU CHARSET Library. + + The GNU CHARSET Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU CHARSET 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with the GNU CHARSET Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _LIBCHARSET_H +#define _LIBCHARSET_H + +#include <ardourext/localcharset.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Support for relocatable packages. */ + +/* Sets the original and the current installation prefix of the package. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +extern void libcharset_set_relocation_prefix (const char *orig_prefix, + const char *curr_prefix); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _LIBCHARSET_H */ diff --git a/msvc_extra_headers/ardourext/localcharset.h.input b/msvc_extra_headers/ardourext/localcharset.h.input new file mode 100644 index 0000000000..129e4a4a32 --- /dev/null +++ b/msvc_extra_headers/ardourext/localcharset.h.input @@ -0,0 +1,42 @@ +/* Determine a canonical name for the current locale's character encoding. + Copyright (C) 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU CHARSET Library. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +#ifndef _LOCALCHARSET_H +#define _LOCALCHARSET_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed in config.charset. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ +extern const char * locale_charset (void); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _LOCALCHARSET_H */ diff --git a/msvc_extra_headers/ardourext/misc.h.input b/msvc_extra_headers/ardourext/misc.h.input new file mode 100644 index 0000000000..55eb529f24 --- /dev/null +++ b/msvc_extra_headers/ardourext/misc.h.input @@ -0,0 +1,223 @@ +/* + 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 __ardour_msvc_extensions_h__ +#define __ardour_msvc_extensions_h__ + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif +#ifndef _CPP_VECTOR +#define _CPP_VECTOR 1 +#endif + +#include <vector> +#include <math.h> +#include <float.h> +#include <direct.h> +#include <boost/regex.h> +#include <glib.h> +#include <ardourext/float_cast.h> + +// 'std::isnan()' is not available in MSVC. Assume '_isnan(double)' +#define isnan(val) (bool)_isnan((double)val) + +// 'std::isinf()' is not available in MSVC. Assume '!_finite(double)' +#define isinf(val) !((bool)_finite((double)val)) + +// 'INFINITY' is not defined in MSVC. Assume 'HUGE_VAL' +#ifndef INFINITY +#define INFINITY HUGE_VAL +#endif + +// File access modes copied from unistd.h +#define F_OK 0 +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 + +// Miscellaneous #defines +#define __attribute__(x) +#define llabs _abs64 +#define atoll _atoi64 +#define access _access +#define getcwd _getcwd +#define getpid _getpid +#define snprintf _snprintf +#define link ntfs_link +#define unlink ntfs_unlink +#define strcasecmp stricmp +#define strncasecmp strnicmp +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) + +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif +#define DECLARE_DEFAULT_COMPARISONS(Type) \ + extern bool operator > (const Type& lhs, const Type& rhs); \ + extern bool operator < (const Type& lhs, const Type& rhs); \ + extern bool operator != (const Type& lhs, const Type& rhs); \ + extern bool operator == (const Type& lhs, const Type& rhs); + +// Types missing from Win32 'stat.h' (hopefully Windows +// will either act sensibly or ignore most of them). +#define _S_IFBLK 0x3000 +#define S_IRWXU _S_IRWXU +#define S_IXUSR _S_IXUSR +#define S_IWUSR _S_IWUSR +#define S_IRUSR _S_IRUSR +#define S_IXGRP _S_IXGRP +#define S_IWGRP _S_IWGRP +#define S_IRGRP _S_IRGRP +#define S_IXOTH _S_IXOTH +#define S_IWOTH _S_IWOTH +#define S_IROTH _S_IROTH + +#define _S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC) +#define _S_IXUSR _S_IEXEC +#define _S_IWUSR _S_IWRITE +#define _S_IRUSR _S_IREAD +#define _S_IXGRP _S_IEXEC +#define _S_IWGRP _S_IWRITE +#define _S_IRGRP _S_IREAD +#define _S_IXOTH _S_IEXEC +#define _S_IWOTH _S_IWRITE +#define _S_IROTH _S_IREAD + +#define S_ISFIFO(m) _S_ISFIFO(m) +#define S_ISDIR(m) _S_ISDIR(m) +#define S_ISCHR(m) _S_ISCHR(m) +#define S_ISBLK(m) _S_ISBLK(m) +#define S_ISREG(m) _S_ISREG(m) + +#define _S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) +#define _S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) +#define _S_ISCHR(m) (((m) & _S_IFMT) == _S_IFCHR) +#define _S_ISBLK(m) (((m) & _S_IFMT) == _S_IFBLK) +#define _S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) + + +#if defined(__USE_BSD) || defined(_BSD_SOURCE) +/* Convenience macros for operations on timevals. + NOTE: `timercmp' does not work for >= or <=. + Note also that 'timerset', 'timerclear' and + 'timercmp' are (perhaps strangely) already + defined, along with various other 'time' + functions in WinSock.h */ +# define timeradd(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 >= 1000000) \ + { \ + ++(result)->tv_sec; \ + (result)->tv_usec -= 1000000; \ + } \ + } while (0) +# 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 /* BSD */ + +#if !defined(__BIT_TYPES_DEFINED) || !defined(__BIT_TYPES_DEFINED__) +#define __BIT_TYPES_DEFINED__ 1 +// Doesn't yet define all 'bit types'. Only those +// needed by Ardour. More can be added as needed. +#ifndef __int8_t_defined +#define __int8_t_defined +typedef unsigned char u_int8_t; +typedef unsigned short int u_int16_t; +typedef unsigned int u_int32_t; +typedef unsigned __int64 u_int64_t; + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif // __int8_t + +#ifndef __register_t_defined +#define __register_t_defined +typedef int register_t; +#endif // __register_t +#endif // __BIT_TYPESD + +// throw() +#ifndef __THROW +#define __THROW throw() +#endif + +// round().... Unlike Linux, Windows doesn't seem to support the +// concept of a system-wide (or programmable) rounding direction. +// Fortunately, 'round to nearest' seems to be the default action +// under Linux, so let's copy that until we find out otherwise. +#define rint(value) round(value) +#define round(value) floor((value) + 0.5) + +// System V compatibility +typedef unsigned short ushort; +typedef unsigned int uint; + +// mode_t +#ifndef _MODE_T_ +#define _MODE_T_ +typedef unsigned short _mode_t; + +#ifndef NO_OLDNAMES +typedef _mode_t mode_t; +#endif /* NO_OLDNAMES */ +#endif /* _MODE_T_ */ + +// fmin() and fmax() +#define fmin(a, b) min((double)a, (double)b) +#define fmax(a, b) max((double)a, (double)b) + +// approximate POSIX pipe() +#define pipe(handles) _pipe(handles, 4096, _O_BINARY) + +// Windows mkdir() doesn't care about access privileges +#define mkdir(path, mode) _mkdir(path) + +// Redefine 'ftruncate()' to use the glib-win32 version +#define ftruncate(fd, len) g_win32_ftruncate((gint)fd, (guint)len) + + +// #include the main headers for Ardour MSVC +#if defined(BUILDING_PBD) || defined(PBD_IS_IN_WIN_STATIC_LIB) +#include <pbd/msvc_pbd.h> +#endif +#if defined(BUILDING_LIBARDOUR) || defined(LIBARDOUR_IS_IN_WIN_STATIC_LIB) +#include <ardour/msvc_libardour.h> +#endif +#if defined(BUILDING_RUBBERBAND) || defined(RUBBERBAND_IS_IN_WIN_STATIC_LIB) +#include <rubberband/msvc_rubberband.h> +#endif + +#endif /* __ardour_msvc_extensions_h__ */ diff --git a/msvc_extra_headers/ardourext/pthread.h.input b/msvc_extra_headers/ardourext/pthread.h.input new file mode 100644 index 0000000000..9699ef91eb --- /dev/null +++ b/msvc_extra_headers/ardourext/pthread.h.input @@ -0,0 +1,7 @@ +#if !defined( PTHREAD_H ) +#ifdef _PTHREAD_H // Test added by JE - 12-12-2009 +#error "ardourext/pthread.h conflicts with an existing pthread library" +#else +#include <ardourext/ptw32/pthread.h> +#endif /* _PTHREAD_H */ +#endif /* PTHREAD_H */ diff --git a/msvc_extra_headers/ardourext/ptw32/pthread.h.input b/msvc_extra_headers/ardourext/ptw32/pthread.h.input new file mode 100644 index 0000000000..0aa4522556 --- /dev/null +++ b/msvc_extra_headers/ardourext/ptw32/pthread.h.input @@ -0,0 +1,1373 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This 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 of the License, or (at your option) any later version. + * + * This 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 this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#ifdef _PTHREAD_H // Test added by JE - 12-12-2009 +#error "ptw32/pthread.h conflicts with an existing pthread library" +#endif +// Now make sure we can't accidentally include a conflicting library !! +#define _PTHREAD_H +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,8,0,0 +#define PTW32_VERSION_STRING "2, 8, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson <rpj@callisto.canberra.edu.au> + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include <windows.h> +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include <time.h> +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include <signal.h> +#endif /* HAVE_SIGNAL_H */ + +#include <setjmp.h> +#include <limits.h> + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include <errno.h> +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include <ardourext/sched.h> + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in <unistd.h>, which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in <limits.h>, which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include <sys/types.h> +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/msvc_extra_headers/ardourext/sched.h.input b/msvc_extra_headers/ardourext/sched.h.input new file mode 100644 index 0000000000..e7f4ab0a52 --- /dev/null +++ b/msvc_extra_headers/ardourext/sched.h.input @@ -0,0 +1,183 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This 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 of the License, or (at your option) any later version. + * + * This 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 this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef SCHED_H +#ifdef _SCHED_H // Test added by JE - 12-12-2009 +#error "ardourext/sched.h conflicts with an existing pthread library" +#endif +// Now make sure we can't accidentally include a conflicting library !! +#define _SCHED_H +#define SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include <errno.h> +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include <sys/types.h> +/* Required by Unix 98 */ +# include <time.h> +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SCHED_H */ + diff --git a/msvc_extra_headers/ardourext/semaphore.h.input b/msvc_extra_headers/ardourext/semaphore.h.input new file mode 100644 index 0000000000..c06373fd77 --- /dev/null +++ b/msvc_extra_headers/ardourext/semaphore.h.input @@ -0,0 +1,171 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This 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 of the License, or (at your option) any later version. + * + * This 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 this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#ifdef _SEMAPHORE_H // Test added by JE - 12-12-2009 +#error "ardourext/semaphore.h conflicts with an existing pthread library" +#endif +// Now make sure we can't accidentally include a conflicting library !! +#define _SEMAPHORE_H +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include <errno.h> +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/msvc_extra_headers/ardourext/sys/targetsxs.h.input b/msvc_extra_headers/ardourext/sys/targetsxs.h.input new file mode 100644 index 0000000000..6653041d8a --- /dev/null +++ b/msvc_extra_headers/ardourext/sys/targetsxs.h.input @@ -0,0 +1,66 @@ +#ifndef _TARGETSXS_H_ +#define _TARGETSXS_H_ + +#pragma warning( disable : 4996 ) + +#ifndef HAVE_LV2 +#define HAVE_SUIL +#define HAVE_LV2 +/* Comment out the above lines to build Mixbus without LV2 support */ +#endif + +#ifndef VST_SUPPORT +#define VST_SUPPORT +/* Comment out the above line to build Mixbus without VST support */ +#endif + +#ifndef JACK_32_64 +#define JACK_32_64 +/* Shouldn't really be needed but make sure that any structs we + obtain from libjack will have 1-byte packing alignment where + necessary (belt & braces approach to be on the safe side) */ +#endif + +#ifdef _DEBUG +#define _SECURE_SCL 1 +#define _HAS_ITERATOR_DEBUGGING 1 +/* #define to zero for a more conventional Debug build */ +#endif + +#ifndef __midl +#if defined(_DEBUG) || defined (DEBUG) +/* Experimental - link to the lowest DebugCRT so we can run on another system */ +#define _SXS_ASSEMBLY_VERSION "8.0.50727.42" +#else +#define _SXS_ASSEMBLY_VERSION "8.0.50727.6195" +#endif +#define _CRT_ASSEMBLY_VERSION _SXS_ASSEMBLY_VERSION +#define _MFC_ASSEMBLY_VERSION _SXS_ASSEMBLY_VERSION +#define _ATL_ASSEMBLY_VERSION _SXS_ASSEMBLY_VERSION + +#ifdef __cplusplus +extern "C" { +#endif +__declspec(selectany) int _forceCRTManifest; +__declspec(selectany) int _forceMFCManifest; +__declspec(selectany) int _forceAtlDllManifest; +__declspec(selectany) int _forceCRTManifestRTM; +__declspec(selectany) int _forceMFCManifestRTM; +__declspec(selectany) int _forceAtlDllManifestRTM; +#ifdef __cplusplus +} +#endif +#endif + +/* 'stdint.h' conflicts with various other libraries so + let's #include stdint.h first to ensure one consistent + implementation for commonly used integer types. */ +#include <stdint.h> + +#if (BUILDING_ARDOUR) +#if defined(_MSC_VER) && !defined(__MINGW__) && !defined(__MINGW32__) +#include <ardourext/misc.h> +#endif +#endif + +#endif /*_TARGETSXS_H_*/ diff --git a/msvc_extra_headers/ardourext/sys/time.h.input b/msvc_extra_headers/ardourext/sys/time.h.input new file mode 100644 index 0000000000..2e54976641 --- /dev/null +++ b/msvc_extra_headers/ardourext/sys/time.h.input @@ -0,0 +1,110 @@ +#ifndef _WINX_SYS_TIME_H_ +#define _WINX_SYS_TIME_H_ + +//#include <features.h> +#include <WinSock.h> // gets 'struct timeval' + +#ifdef _TIMEVAL_DEFINED +# define _STRUCT_TIMEVAL 1 +#endif /* _TIMEVAL_DEFINED */ +//#include <bits/types.h> +#define __need_time_t +#include <time.h> +#define __need_timeval +//#include <bits/time.h> + +#ifdef _TIMEVAL_DEFINED /* also in winsock[2].h */ +# undef __TIMEVAL__ +# define __TIMEVAL__ 1 +# undef _STRUCT_TIMEVAL +# define _STRUCT_TIMEVAL 1 +#endif /* _TIMEVAL_DEFINED */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __USE_GNU +/* Macros for converting between `struct timeval' and `struct timespec'. */ +# define TIMEVAL_TO_TIMESPEC(tv, ts) { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} +# define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ +} +#endif + +#ifdef __USE_BSD +/* Structure crudely representing a timezone. + This is obsolete and should never be used. */ +struct timezone + { + int tz_minuteswest; /* Minutes west of GMT. */ + int tz_dsttime; /* Nonzero if DST is ever in effect. */ + }; + +typedef struct timezone *__restrict __timezone_ptr_t; +#else +typedef void *__restrict __timezone_ptr_t; +#endif + +/* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. + NOTE: This form of timezone information is obsolete. + Use the functions and variables declared in <time.h> instead. */ +extern int gettimeofday (struct timeval *__restrict __tv, + __timezone_ptr_t __tz) __THROW; + +extern int getntptimeofday (struct timespec *__restrict __tp, + __timezone_ptr_t __tz) __THROW; + +#ifdef __USE_BSD +/* Set the current time of day and timezone information. + This call is restricted to the super-user. */ +extern int settimeofday (__const struct timeval *__tv, + __const struct timezone *__tz) __THROW; +extern int setntptimeofday (__const struct timespec *__tp, + __const struct timezone *__tz) __THROW; +#endif + +///* Values for the first argument to `getitimer' and `setitimer'. */ +//enum __itimer_which +// { +// /* Timers run in real time. */ +// ITIMER_REAL = 0, +//#define ITIMER_REAL ITIMER_REAL +// /* Timers run only when the process is executing. */ +// ITIMER_VIRTUAL = 1, +//#define ITIMER_VIRTUAL ITIMER_VIRTUAL +// /* Timers run when the process is executing and when +// the system is executing on behalf of the process. */ +// ITIMER_PROF = 2 +//#define ITIMER_PROF ITIMER_PROF +// }; + +/* Type of the second argument to `getitimer' and + the second and third arguments `setitimer'. */ +struct itimerval + { + /* Value to put into `it_value' when the timer expires. */ + struct timeval it_interval; + /* Time to the next timer expiration. */ + struct timeval it_value; + }; + +#if defined __USE_GNU && !defined __cplusplus +/* Use the nicer parameter type only in GNU mode and not for C++ since the + strict C++ rules prevent the automatic promotion. */ +typedef enum __itimer_which __itimer_which_t; +#else +typedef int __itimer_which_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*_WINX_SYS_TIMEX_H_*/ |