JOHNE source files (needed for building libpbd with MSVC)
authorJohn Emmas <johne53@tiscali.co.uk>
Wed, 17 Jul 2013 13:53:17 +0000 (14:53 +0100)
committerJohn Emmas <johne53@tiscali.co.uk>
Wed, 17 Jul 2013 13:53:17 +0000 (14:53 +0100)
libs/pbd/fallback_folders.cc [new file with mode: 0644]
libs/pbd/localeguard.cc [new file with mode: 0644]
libs/pbd/msvc/fpu.cc [new file with mode: 0644]
libs/pbd/msvc/mountpoint.cc [new file with mode: 0644]
libs/pbd/msvc/msvc_pbd.cc [new file with mode: 0644]
libs/pbd/msvc/msvc_poll.cc [new file with mode: 0644]
libs/pbd/pbd/fallback_folders.h [new file with mode: 0644]
libs/pbd/pbd/localeguard.h [new file with mode: 0644]
libs/pbd/pbd/msvc_pbd.h [new file with mode: 0644]

diff --git a/libs/pbd/fallback_folders.cc b/libs/pbd/fallback_folders.cc
new file mode 100644 (file)
index 0000000..deecd60
--- /dev/null
@@ -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/localeguard.cc b/libs/pbd/localeguard.cc
new file mode 100644 (file)
index 0000000..12093be
--- /dev/null
@@ -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/msvc/fpu.cc b/libs/pbd/msvc/fpu.cc
new file mode 100644 (file)
index 0000000..6997405
--- /dev/null
@@ -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 (file)
index 0000000..d30b244
--- /dev/null
@@ -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 (file)
index 0000000..45137da
--- /dev/null
@@ -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 (file)
index 0000000..e12ef2b
--- /dev/null
@@ -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/pbd/fallback_folders.h b/libs/pbd/pbd/fallback_folders.h
new file mode 100644 (file)
index 0000000..60935b4
--- /dev/null
@@ -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 (file)
index 0000000..20899b5
--- /dev/null
@@ -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/msvc_pbd.h b/libs/pbd/pbd/msvc_pbd.h
new file mode 100644 (file)
index 0000000..1c97130
--- /dev/null
@@ -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_