'libs/ardour' - New files and changes needed for 'msvc_libardour'

This commit is contained in:
John Emmas
2013-08-09 17:53:37 +01:00
parent dc62ef6123
commit 64cc518e72
3 changed files with 380 additions and 5 deletions

View File

@@ -0,0 +1,99 @@
/*
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_libardour_h__
#define __msvc_libardour_h__
#include <limits.h>
#ifdef LIBARDOUR_IS_IN_WIN_STATIC_LIB // #define if your project uses libardour (under Windows) as a static library
#define LIBARDOUR_IS_IN_WINDLL 0
#endif
#if !defined(LIBARDOUR_IS_IN_WINDLL)
#if defined(COMPILER_MSVC) || defined(COMPILER_MINGW)
// If you need '__declspec' compatibility, add extra compilers to the above as necessary
#define LIBARDOUR_IS_IN_WINDLL 1
#else
#define LIBARDOUR_IS_IN_WINDLL 0
#endif
#endif
#if LIBARDOUR_IS_IN_WINDLL && !defined(LIBARDOUR_API)
#if defined(BUILDING_LIBARDOUR)
#define LIBARDOUR_API __declspec(dllexport)
#define LIBARDOUR_APICALLTYPE __stdcall
#elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point
#define LIBARDOUR_API __declspec(dllimport)
#define LIBARDOUR_APICALLTYPE __stdcall
#else
#error "Attempting to define __declspec with an incompatible compiler !"
#endif
#elif !defined(LIBARDOUR_API)
// Other compilers / platforms could be accommodated here
#define LIBARDOUR_API
#define LIBARDOUR_APICALLTYPE
#endif
#ifndef _MAX_PATH
#define _MAX_PATH 260
#endif
#ifndef PATH_MAX
#define PATH_MAX _MAX_PATH
#endif
namespace ARDOUR {
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
// LIBARDOUR_API char* LIBARDOUR_APICALLTYPE placeholder_for_non_msvc_specific_function(s);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
} // namespace ARDOUR
#ifdef COMPILER_MSVC
#include <rpc.h>
//#include <io.h>
#ifndef __THROW
#define __THROW throw()
#endif
#include <ardourext/sys/time.h>
namespace ARDOUR {
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
LIBARDOUR_API int LIBARDOUR_APICALLTYPE symlink(const char *dest, const char *shortcut, const char *working_directory = 0);
LIBARDOUR_API int LIBARDOUR_APICALLTYPE readlink(const char *__restrict shortcut, char *__restrict buf, size_t bufsize);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
} // namespace ARDOUR
#endif // COMPILER_MSVC
#endif // __mavc_libardour_h__

View File

@@ -0,0 +1,276 @@
/*
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.
*/
#if (defined(PLATFORM_WINDOWS) && !defined(COMPILER_CYGWIN))
#include <shlobj.h>
#include <glibmm.h>
#ifdef COMPILER_MSVC
#pragma warning(disable:4996)
#endif
#else
#include <glib.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <ardour/msvc_libardour.h>
namespace ARDOUR {
//***************************************************************
//
// placeholder_for_non_msvc_specific_function()
//
// Description
//
// Returns:
//
// On Success:
//
// On Failure:
//
/* LIBARDOUR_API char* LIBARDOUR_APICALLTYPE
placeholder_for_non_msvc_specific_function()
{
char *pRet = buffer;
return (pRet);
}
*/
} // namespace ARDOUR
#ifdef COMPILER_MSVC
#include <errno.h>
namespace ARDOUR {
//***************************************************************
//
// symlink()
//
// Emulates POSIX symlink() but creates a Windows shortcut. To
// create a Windows shortcut the supplied shortcut name must end
// in ".lnk"
// Note that you can only create a shortcut in a folder for which
// you have appropriate access rights. Note also that the folder
// must already exist. If it doesn't exist or if you don't have
// sufficient access rights to it, symlink() will generate an
// error (in common with its POSIX counterpart).
//
// Returns:
//
// On Success: Zero
// On Failure: -1 ('errno' will contain the specific error)
//
LIBARDOUR_API int LIBARDOUR_APICALLTYPE
symlink(const char *dest, const char *shortcut, const char *working_directory /*= NULL */)
{
IShellLinkA *pISL = NULL;
IPersistFile *ppf = NULL;
int ret = (-1);
if ((NULL == dest) || (NULL == shortcut) || (strlen(shortcut) < 5) || (strlen(dest) == 0))
_set_errno(EINVAL);
else if ((strlen(shortcut) > _MAX_PATH) || (strlen(dest) > _MAX_PATH))
_set_errno(ENAMETOOLONG);
else if (Glib::file_test(shortcut, Glib::FILE_TEST_EXISTS))
_set_errno(EEXIST);
else
{
HRESULT hRet = 0;
if (SUCCEEDED (hRet = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pISL)))
{
if (SUCCEEDED (pISL->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf)))
{
char sc_path_lower_case[_MAX_PATH];
WCHAR shortcut_path[_MAX_PATH];
// Fail if the path isn't a shortcut
strcpy(sc_path_lower_case, shortcut);
strlwr(sc_path_lower_case);
const char *p = strlen(sc_path_lower_case) + sc_path_lower_case - 4;
if (0 == strcmp(p, ".lnk"))
{
HRESULT hr;
// We're apparently been given valid Windows shortcut name
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, shortcut, -1, shortcut_path, _MAX_PATH);
// Create the shortcut
if (FAILED (hr = ppf->Load(shortcut_path, STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE)))
hr = ppf->Save(shortcut_path, TRUE);
if (S_OK == hr)
{
// Set its target path
if (S_OK == pISL->SetPath(dest))
{
// Set its working directory
if (working_directory)
p = working_directory;
else
p = "";
if (S_OK == pISL->SetWorkingDirectory(p))
{
// Set its 'Show' command
if (S_OK == pISL->SetShowCmd(SW_SHOWNORMAL))
{
// And finally, set its icon to the same file as the target.
// For the time being, don't fail if the target has no icon.
if (Glib::file_test(dest, Glib::FILE_TEST_IS_DIR))
pISL->SetIconLocation("%SystemRoot%\\system32\\shell32.dll", 1);
else
pISL->SetIconLocation(dest, 0);
if (S_OK == ppf->Save(shortcut_path, FALSE))
{
Sleep(1500);
ret = 0;
// _set_errno(0);
}
else
_set_errno(EACCES);
}
else
_set_errno(EACCES);
}
else
_set_errno(EACCES);
}
else
_set_errno(EACCES);
}
else
_set_errno(EBADF);
}
else
_set_errno(EACCES);
}
else
_set_errno(EBADF);
}
else
{
if (E_POINTER == hRet)
_set_errno(EINVAL);
else
_set_errno(EIO);
}
}
return (ret);
}
//***************************************************************
//
// readlink()
//
// Emulates POSIX readlink() but using Windows shortcuts
// Doesn't (currently) resolve shortcuts to shortcuts. This would
// be quite simple to incorporate but we'd need to check for
// recursion (i.e. a shortcut that points to an earlier shortcut
// in the same chain).
//
// Returns:
//
// On Success: Zero
// On Failure: -1 ('errno' will contain the specific error)
//
LIBARDOUR_API int LIBARDOUR_APICALLTYPE
readlink(const char *__restrict shortcut, char *__restrict buf, size_t bufsize)
{
IShellLinkA *pISL = NULL;
IPersistFile *ppf = NULL;
int ret = (-1);
if ((NULL == shortcut) || (NULL == buf) || (strlen(shortcut) < 5) || (bufsize == 0))
_set_errno(EINVAL);
else if ((bufsize > _MAX_PATH) || (strlen(shortcut) > _MAX_PATH))
_set_errno(ENAMETOOLONG);
else
{
HRESULT hRet = 0;
if (SUCCEEDED (hRet = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pISL)))
{
if (SUCCEEDED (pISL->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf)))
{
char target_path[_MAX_PATH];
WCHAR shortcut_path[_MAX_PATH];
// Fail if the path isn't a shortcut
strcpy(target_path, shortcut); // Use 'target_path' temporarily
strlwr(target_path);
const char *p = strlen(target_path) + target_path - 4;
if (0 == strcmp(p, ".lnk"))
{
// We're apparently pointing to a valid Windows shortcut
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, shortcut, -1, shortcut_path, _MAX_PATH);
// Load the shortcut into our persistent file
if (SUCCEEDED (ppf->Load(shortcut_path, 0)))
{
// Read the target information from the shortcut object
if (S_OK == (pISL->GetPath (target_path, _MAX_PATH, NULL, SLGP_UNCPRIORITY)))
{
strncpy(buf, target_path, bufsize);
ret = ((ret = strlen(buf)) > bufsize) ? bufsize : ret;
// _set_errno(0);
}
else
_set_errno(EACCES);
}
else
_set_errno(EBADF);
}
else
_set_errno(EINVAL);
}
else
_set_errno(EBADF);
}
else
{
if (E_POINTER == hRet)
_set_errno(EINVAL);
else
_set_errno(EIO);
}
if (ppf)
ppf->Release();
if (pISL)
pISL->Release();
}
return (ret);
}
} // namespace ARDOUR
#endif // COMPILER_MSVC

View File

@@ -24,7 +24,7 @@
#endif
#if !defined(RUBBERBAND_IS_IN_WINDLL)
#if defined(_MSC_VER) || defined(__MINGW__) || defined(_MINGW32__)
#if defined(COMPILER_MSVC) || defined(COMPILER_MINGW)
// If you need '__declspec' compatibility, add extra compilers to the above as necessary
#define RUBBERBAND_IS_IN_WINDLL 1
#else
@@ -36,7 +36,7 @@
#if defined(BUILDING_RUBBERBAND)
#define RUBBERBAND_API __declspec(dllexport)
#define RUBBERBAND_APICALLTYPE __stdcall
#elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MINGW32__)
#elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point
#define RUBBERBAND_API __declspec(dllimport)
#define RUBBERBAND_APICALLTYPE __stdcall
#else
@@ -54,7 +54,7 @@
#if defined(BUILDING_GETOPT)
#define GETOPT_API __declspec(dllexport)
#define GETOPT_APICALLTYPE __cdecl
#elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MINGW32__)
#elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point
#define GETOPT_API __declspec(dllimport)
#define GETOPT_APICALLTYPE __cdecl
#else
@@ -62,7 +62,7 @@
#endif
#endif // GETOPT_API
#ifdef _MSC_VER
#ifdef COMPILER_MSVC
#include <rpc.h>
#ifndef __THROW
@@ -84,5 +84,5 @@ extern "C" {
} // namespace Rubberband
#endif // _MSC_VER
#endif // COMPILER_MSVC
#endif // __msvc_rubberband_h__