13
0

JOHNE source files (needed for building libpbd with MSVC)

This commit is contained in:
John Emmas 2013-07-17 14:53:17 +01:00
parent 57f9a4c344
commit 110972e59a
9 changed files with 2359 additions and 0 deletions

View File

@ -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

34
libs/pbd/localeguard.cc Normal file
View File

@ -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);
}
}

124
libs/pbd/msvc/fpu.cc Normal file
View File

@ -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

166
libs/pbd/msvc/mountpoint.cc Normal file
View File

@ -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

895
libs/pbd/msvc/msvc_pbd.cc Normal file
View File

@ -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

215
libs/pbd/msvc/msvc_poll.cc Normal file
View File

@ -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

View File

@ -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__ */

View File

@ -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__ */

235
libs/pbd/pbd/msvc_pbd.h Normal file
View File

@ -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_