@@ -82,3 +82,79 @@ jobs: | |||||
with: | with: | ||||
name: macOS artifacts | name: macOS artifacts | ||||
path: ${{runner.workspace}}/build/bin/ | path: ${{runner.workspace}}/build/bin/ | ||||
cmake_win32: | |||||
runs-on: windows-2019 | |||||
steps: | |||||
- name: Set environment | |||||
run: | | |||||
echo "release_arch=Win32" >> "${Env:GITHUB_ENV}" | |||||
echo "vcpkg_triplet=x86-windows-static" >> "${Env:GITHUB_ENV}" | |||||
echo "vcpkg_git_commit_id=a3db16a4475b963cacf0260068c497fb72c8f3c0" >> "${Env:GITHUB_ENV}" | |||||
- name: Restore from cache and install vcpkg | |||||
uses: lukka/run-vcpkg@v6 | |||||
with: | |||||
setupOnly: true | |||||
vcpkgTriplet: ${{env.vcpkg_triplet}} | |||||
vcpkgGitCommitId: ${{env.vcpkg_git_commit_id}} | |||||
#- name: Install packages | |||||
# run: | | |||||
# & "${Env:VCPKG_ROOT}/vcpkg" install "cairo:${Env:vcpkg_triplet}" | |||||
- uses: actions/checkout@v2 | |||||
with: | |||||
submodules: recursive | |||||
- name: Create Build Environment | |||||
working-directory: ${{runner.workspace}} | |||||
run: cmake -E make_directory build | |||||
- name: Configure CMake | |||||
working-directory: ${{runner.workspace}}/build | |||||
run: | | |||||
cmake "${Env:GITHUB_WORKSPACE}" -G"Visual Studio 16 2019" -A"${Env:release_arch}" -DCMAKE_BUILD_TYPE="${Env:BUILD_TYPE}" -DVCPKG_TARGET_TRIPLET="${Env:vcpkg_triplet}" -DCMAKE_TOOLCHAIN_FILE="${Env:VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" | |||||
- name: Build all | |||||
working-directory: ${{runner.workspace}}/build | |||||
run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2 | |||||
- name: Show built files | |||||
working-directory: ${{runner.workspace}}/build/bin | |||||
run: tree | |||||
- uses: actions/upload-artifact@v2 | |||||
with: | |||||
name: Win32 artifacts | |||||
path: ${{runner.workspace}}/build/bin/ | |||||
cmake_win64: | |||||
runs-on: windows-2019 | |||||
steps: | |||||
- name: Set environment | |||||
run: | | |||||
echo "release_arch=x64" >> "${Env:GITHUB_ENV}" | |||||
echo "vcpkg_triplet=x64-windows-static" >> "${Env:GITHUB_ENV}" | |||||
echo "vcpkg_git_commit_id=a3db16a4475b963cacf0260068c497fb72c8f3c0" >> "${Env:GITHUB_ENV}" | |||||
- name: Restore from cache and install vcpkg | |||||
uses: lukka/run-vcpkg@v6 | |||||
with: | |||||
setupOnly: true | |||||
vcpkgTriplet: ${{env.vcpkg_triplet}} | |||||
vcpkgGitCommitId: ${{env.vcpkg_git_commit_id}} | |||||
#- name: Install packages | |||||
# run: | | |||||
# & "${Env:VCPKG_ROOT}/vcpkg" install "cairo:${Env:vcpkg_triplet}" | |||||
- uses: actions/checkout@v2 | |||||
with: | |||||
submodules: recursive | |||||
- name: Create Build Environment | |||||
working-directory: ${{runner.workspace}} | |||||
run: cmake -E make_directory build | |||||
- name: Configure CMake | |||||
working-directory: ${{runner.workspace}}/build | |||||
run: | | |||||
cmake "${Env:GITHUB_WORKSPACE}" -G"Visual Studio 16 2019" -A"${Env:release_arch}" -DCMAKE_BUILD_TYPE="${Env:BUILD_TYPE}" -DVCPKG_TARGET_TRIPLET="${Env:vcpkg_triplet}" -DCMAKE_TOOLCHAIN_FILE="${Env:VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" | |||||
- name: Build all | |||||
working-directory: ${{runner.workspace}}/build | |||||
run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2 | |||||
- name: Show built files | |||||
working-directory: ${{runner.workspace}}/build/bin | |||||
run: tree | |||||
- uses: actions/upload-artifact@v2 | |||||
with: | |||||
name: Win64 artifacts | |||||
path: ${{runner.workspace}}/build/bin/ |
@@ -10,6 +10,8 @@ | |||||
.kdev_include_paths | .kdev_include_paths | ||||
.kdev4/ | .kdev4/ | ||||
.DS_Store | .DS_Store | ||||
.vs/ | |||||
CMakeSettings.json | |||||
bin/ | bin/ | ||||
build/ | build/ | ||||
@@ -293,7 +293,8 @@ function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC) | |||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} | COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} | ||||
"$<TARGET_FILE:lv2_ttl_generator>" | "$<TARGET_FILE:lv2_ttl_generator>" | ||||
"$<TARGET_FILE:${NAME}-lv2>" | "$<TARGET_FILE:${NAME}-lv2>" | ||||
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2") | |||||
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2" | |||||
DEPENDS lv2_ttl_generator) | |||||
endfunction() | endfunction() | ||||
# dpf__build_vst2 | # dpf__build_vst2 | ||||
@@ -488,6 +489,22 @@ function(dpf__add_dgl_system_libs) | |||||
# target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XCURSOR") | # target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XCURSOR") | ||||
#endif() | #endif() | ||||
endif() | endif() | ||||
if(MSVC) | |||||
file(MAKE_DIRECTORY "${DPF_ROOT_DIR}/khronos/GL") | |||||
foreach(_gl_header "glext.h") | |||||
if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}") | |||||
file(DOWNLOAD "https://www.khronos.org/registry/OpenGL/api/GL/${_gl_header}" "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}" SHOW_PROGRESS) | |||||
endif() | |||||
endforeach() | |||||
foreach(_khr_header "khrplatform.h") | |||||
if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}") | |||||
file(DOWNLOAD "https://www.khronos.org/registry/EGL/api/KHR/${_khr_header}" "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}" SHOW_PROGRESS) | |||||
endif() | |||||
endforeach() | |||||
target_include_directories(dgl-system-libs-definitions INTERFACE "${DPF_ROOT_DIR}/khronos") | |||||
endif() | |||||
target_link_libraries(dgl-system-libs INTERFACE dgl-system-libs-definitions) | target_link_libraries(dgl-system-libs INTERFACE dgl-system-libs-definitions) | ||||
endfunction() | endfunction() | ||||
@@ -498,14 +515,7 @@ endfunction() | |||||
# | # | ||||
function(dpf__add_executable NAME) | function(dpf__add_executable NAME) | ||||
add_executable("${NAME}" ${ARGN}) | add_executable("${NAME}" ${ARGN}) | ||||
set_target_properties("${NAME}" PROPERTIES | |||||
POSITION_INDEPENDENT_CODE TRUE | |||||
C_VISIBILITY_PRESET "hidden" | |||||
CXX_VISIBILITY_PRESET "hidden" | |||||
VISIBILITY_INLINES_HIDDEN TRUE) | |||||
if (MINGW) | |||||
target_compile_options("${NAME}" PUBLIC "-mstackrealign") | |||||
endif() | |||||
dpf__set_target_defaults("${NAME}") | |||||
endfunction() | endfunction() | ||||
# dpf__add_module | # dpf__add_module | ||||
@@ -515,17 +525,7 @@ endfunction() | |||||
# | # | ||||
function(dpf__add_module NAME) | function(dpf__add_module NAME) | ||||
add_library("${NAME}" MODULE ${ARGN}) | add_library("${NAME}" MODULE ${ARGN}) | ||||
set_target_properties("${NAME}" PROPERTIES | |||||
POSITION_INDEPENDENT_CODE TRUE | |||||
C_VISIBILITY_PRESET "hidden" | |||||
CXX_VISIBILITY_PRESET "hidden" | |||||
VISIBILITY_INLINES_HIDDEN TRUE) | |||||
if ((NOT WIN32 AND NOT APPLE) OR MINGW) | |||||
target_link_libraries("${NAME}" PRIVATE "-Wl,--no-undefined") | |||||
endif() | |||||
if (MINGW) | |||||
target_compile_options("${NAME}" PUBLIC "-mstackrealign") | |||||
endif() | |||||
dpf__set_target_defaults("${NAME}") | |||||
endfunction() | endfunction() | ||||
# dpf__add_static_library | # dpf__add_static_library | ||||
@@ -535,14 +535,30 @@ endfunction() | |||||
# | # | ||||
function(dpf__add_static_library NAME) | function(dpf__add_static_library NAME) | ||||
add_library("${NAME}" STATIC ${ARGN}) | add_library("${NAME}" STATIC ${ARGN}) | ||||
dpf__set_target_defaults("${NAME}") | |||||
endfunction() | |||||
# dpf__set_target_defaults | |||||
# ------------------------------------------------------------------------------ | |||||
# | |||||
# Set default properties which must apply to all DPF-defined targets. | |||||
# | |||||
function(dpf__set_target_defaults NAME) | |||||
set_target_properties("${NAME}" PROPERTIES | set_target_properties("${NAME}" PROPERTIES | ||||
POSITION_INDEPENDENT_CODE TRUE | POSITION_INDEPENDENT_CODE TRUE | ||||
C_VISIBILITY_PRESET "hidden" | C_VISIBILITY_PRESET "hidden" | ||||
CXX_VISIBILITY_PRESET "hidden" | CXX_VISIBILITY_PRESET "hidden" | ||||
VISIBILITY_INLINES_HIDDEN TRUE) | VISIBILITY_INLINES_HIDDEN TRUE) | ||||
if(WIN32) | |||||
target_compile_definitions("${NAME}" PUBLIC "NOMINMAX") | |||||
endif() | |||||
if (MINGW) | if (MINGW) | ||||
target_compile_options("${NAME}" PUBLIC "-mstackrealign") | target_compile_options("${NAME}" PUBLIC "-mstackrealign") | ||||
endif() | endif() | ||||
if (MSVC) | |||||
target_compile_options("${NAME}" PUBLIC "/UTF-8") | |||||
target_compile_definitions("${NAME}" PUBLIC "_CRT_SECURE_NO_WARNINGS") | |||||
endif() | |||||
endfunction() | endfunction() | ||||
# dpf__add_plugin_main | # dpf__add_plugin_main | ||||
@@ -597,7 +613,7 @@ function(dpf__add_lv2_ttl_generator) | |||||
return() | return() | ||||
endif() | endif() | ||||
add_executable(lv2_ttl_generator "${DPF_ROOT_DIR}/utils/lv2-ttl-generator/lv2_ttl_generator.c") | add_executable(lv2_ttl_generator "${DPF_ROOT_DIR}/utils/lv2-ttl-generator/lv2_ttl_generator.c") | ||||
if(NOT WINDOWS AND NOT APPLE AND NOT HAIKU) | |||||
if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU)) | |||||
target_link_libraries(lv2_ttl_generator "dl") | target_link_libraries(lv2_ttl_generator "dl") | ||||
endif() | endif() | ||||
endfunction() | endfunction() | ||||
@@ -33,6 +33,11 @@ | |||||
# include <stdint.h> | # include <stdint.h> | ||||
#endif | #endif | ||||
#if defined(DISTRHO_OS_WINDOWS) && defined(_MSC_VER) | |||||
#include <basetsd.h> | |||||
typedef SSIZE_T ssize_t; | |||||
#endif | |||||
#if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) | #if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) | ||||
namespace std { | namespace std { | ||||
inline float fmin(float __x, float __y) | inline float fmin(float __x, float __y) | ||||
@@ -94,12 +99,12 @@ static inline | |||||
void d_debug(const char* const fmt, ...) noexcept | void d_debug(const char* const fmt, ...) noexcept | ||||
{ | { | ||||
try { | try { | ||||
::va_list args; | |||||
::va_start(args, fmt); | |||||
va_list args; | |||||
va_start(args, fmt); | |||||
std::fprintf(stdout, "\x1b[30;1m"); | std::fprintf(stdout, "\x1b[30;1m"); | ||||
std::vfprintf(stdout, fmt, args); | std::vfprintf(stdout, fmt, args); | ||||
std::fprintf(stdout, "\x1b[0m\n"); | std::fprintf(stdout, "\x1b[0m\n"); | ||||
::va_end(args); | |||||
va_end(args); | |||||
} catch (...) {} | } catch (...) {} | ||||
} | } | ||||
#endif | #endif | ||||
@@ -111,11 +116,11 @@ static inline | |||||
void d_stdout(const char* const fmt, ...) noexcept | void d_stdout(const char* const fmt, ...) noexcept | ||||
{ | { | ||||
try { | try { | ||||
::va_list args; | |||||
::va_start(args, fmt); | |||||
va_list args; | |||||
va_start(args, fmt); | |||||
std::vfprintf(stdout, fmt, args); | std::vfprintf(stdout, fmt, args); | ||||
std::fprintf(stdout, "\n"); | std::fprintf(stdout, "\n"); | ||||
::va_end(args); | |||||
va_end(args); | |||||
} catch (...) {} | } catch (...) {} | ||||
} | } | ||||
@@ -126,11 +131,11 @@ static inline | |||||
void d_stderr(const char* const fmt, ...) noexcept | void d_stderr(const char* const fmt, ...) noexcept | ||||
{ | { | ||||
try { | try { | ||||
::va_list args; | |||||
::va_start(args, fmt); | |||||
va_list args; | |||||
va_start(args, fmt); | |||||
std::vfprintf(stderr, fmt, args); | std::vfprintf(stderr, fmt, args); | ||||
std::fprintf(stderr, "\n"); | std::fprintf(stderr, "\n"); | ||||
::va_end(args); | |||||
va_end(args); | |||||
} catch (...) {} | } catch (...) {} | ||||
} | } | ||||
@@ -141,12 +146,12 @@ static inline | |||||
void d_stderr2(const char* const fmt, ...) noexcept | void d_stderr2(const char* const fmt, ...) noexcept | ||||
{ | { | ||||
try { | try { | ||||
::va_list args; | |||||
::va_start(args, fmt); | |||||
va_list args; | |||||
va_start(args, fmt); | |||||
std::fprintf(stderr, "\x1b[31m"); | std::fprintf(stderr, "\x1b[31m"); | ||||
std::vfprintf(stderr, fmt, args); | std::vfprintf(stderr, fmt, args); | ||||
std::fprintf(stderr, "\x1b[0m\n"); | std::fprintf(stderr, "\x1b[0m\n"); | ||||
::va_end(args); | |||||
va_end(args); | |||||
} catch (...) {} | } catch (...) {} | ||||
} | } | ||||
@@ -651,14 +651,18 @@ public: | |||||
"abcdefghijklmnopqrstuvwxyz" | "abcdefghijklmnopqrstuvwxyz" | ||||
"0123456789+/"; | "0123456789+/"; | ||||
#ifndef _MSC_VER | |||||
const std::size_t kTmpBufSize = std::min(d_nextPowerOf2(static_cast<uint32_t>(dataSize/3)), 65536U); | const std::size_t kTmpBufSize = std::min(d_nextPowerOf2(static_cast<uint32_t>(dataSize/3)), 65536U); | ||||
#else | |||||
constexpr std::size_t kTmpBufSize = 65536U; | |||||
#endif | |||||
const uchar* bytesToEncode((const uchar*)data); | const uchar* bytesToEncode((const uchar*)data); | ||||
uint i=0, j=0; | uint i=0, j=0; | ||||
uint charArray3[3], charArray4[4]; | uint charArray3[3], charArray4[4]; | ||||
char strBuf[kTmpBufSize+1]; | |||||
char strBuf[kTmpBufSize + 1]; | |||||
strBuf[kTmpBufSize] = '\0'; | strBuf[kTmpBufSize] = '\0'; | ||||
std::size_t strBufIndex = 0; | std::size_t strBufIndex = 0; | ||||
@@ -55,7 +55,7 @@ | |||||
# if HAVE_CPP11_SUPPORT | # if HAVE_CPP11_SUPPORT | ||||
# define DISTRHO_PROPER_CPP11_SUPPORT | # define DISTRHO_PROPER_CPP11_SUPPORT | ||||
# endif | # endif | ||||
#elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) | |||||
#elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) || (defined(_MSC_VER) && _MSVC_LANG >= 201103L) | |||||
# define DISTRHO_PROPER_CPP11_SUPPORT | # define DISTRHO_PROPER_CPP11_SUPPORT | ||||
# if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407 && ! defined(__clang__)) || (defined(__clang__) && ! __has_extension(cxx_override_control)) | # if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407 && ! defined(__clang__)) || (defined(__clang__) && ! __has_extension(cxx_override_control)) | ||||
# define override // gcc4.7+ only | # define override // gcc4.7+ only | ||||
@@ -74,7 +74,7 @@ | |||||
#if defined(__GNUC__) | #if defined(__GNUC__) | ||||
# define DISTRHO_DEPRECATED __attribute__((deprecated)) | # define DISTRHO_DEPRECATED __attribute__((deprecated)) | ||||
#elif defined(_MSC_VER) | #elif defined(_MSC_VER) | ||||
# define DISTRHO_DEPRECATED __declspec(deprecated) | |||||
# define DISTRHO_DEPRECATED [[deprecated]] /* Note: __declspec(deprecated) it not applicable to enum members */ | |||||
#else | #else | ||||
# define DISTRHO_DEPRECATED | # define DISTRHO_DEPRECATED | ||||
#endif | #endif | ||||
@@ -48,9 +48,9 @@ extern Window* d_lastUiWindow; | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
UI* createUiWrapper(void* dspPtr, uintptr_t winId, double scaleFactor, const char* bundlePath); | |||||
UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scaleFactor, const char* const bundlePath); | |||||
#else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
UI* createUiWrapper(void* dspPtr, Window* window); | |||||
UI* createUiWrapper(void* const dspPtr, Window* const window); | |||||
#endif | #endif | ||||
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | ||||
@@ -289,7 +289,7 @@ protected: | |||||
// reserve atom space | // reserve atom space | ||||
const size_t atomSize = sizeof(LV2_Atom) + msgSize; | const size_t atomSize = sizeof(LV2_Atom) + msgSize; | ||||
char atomBuf[atomSize]; | |||||
char* const atomBuf = (char*)malloc(atomSize); | |||||
std::memset(atomBuf, 0, atomSize); | std::memset(atomBuf, 0, atomSize); | ||||
// set atom info | // set atom info | ||||
@@ -302,6 +302,9 @@ protected: | |||||
// send to DSP side | // send to DSP side | ||||
fWriteFunction(fController, eventInPortIndex, atomSize, fURIDs.atomEventTransfer, atom); | fWriteFunction(fController, eventInPortIndex, atomSize, fURIDs.atomEventTransfer, atom); | ||||
// free atom space | |||||
free(atomBuf); | |||||
} | } | ||||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | ||||
@@ -35,6 +35,10 @@ | |||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
#ifndef DSSI_PLUGIN_EXPORT | |||||
# define DSSI_PLUGIN_EXPORT LADSPA_PLUGIN_EXPORT | |||||
#endif | |||||
/* | /* | ||||
There is a need for an API that supports hosted MIDI soft synths | There is a need for an API that supports hosted MIDI soft synths | ||||
with GUIs in Linux audio applications. In time the GMPI initiative | with GUIs in Linux audio applications. In time the GMPI initiative | ||||
@@ -411,7 +415,7 @@ typedef struct _DSSI_Descriptor { | |||||
* of a distinct plugin type. | * of a distinct plugin type. | ||||
*/ | */ | ||||
const DSSI_Descriptor *dssi_descriptor(unsigned long Index); | |||||
DSSI_PLUGIN_EXPORT const DSSI_Descriptor *dssi_descriptor(unsigned long Index); | |||||
typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); | typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); | ||||
@@ -30,6 +30,14 @@ | |||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
#ifndef LADSPA_PLUGIN_EXPORT | |||||
# ifdef _WIN32 | |||||
# define LADSPA_PLUGIN_EXPORT __declspec(dllexport) | |||||
# else | |||||
# define LADSPA_PLUGIN_EXPORT __attribute__((visibility("default"))) | |||||
# endif | |||||
#endif | |||||
/*****************************************************************************/ | /*****************************************************************************/ | ||||
/* Overview: | /* Overview: | ||||
@@ -586,7 +594,7 @@ typedef struct _LADSPA_Descriptor { | |||||
returning NULL, so the plugin count can be determined by checking | returning NULL, so the plugin count can be determined by checking | ||||
for the least index that results in NULL being returned. */ | for the least index that results in NULL being returned. */ | ||||
const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); | |||||
LADSPA_PLUGIN_EXPORT const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); | |||||
/* Datatype corresponding to the ladspa_descriptor() function. */ | /* Datatype corresponding to the ladspa_descriptor() function. */ | ||||
typedef const LADSPA_Descriptor * | typedef const LADSPA_Descriptor * | ||||
@@ -15,6 +15,7 @@ | |||||
*/ | */ | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | |||||
#include <string.h> | #include <string.h> | ||||
#ifdef _WIN32 | #ifdef _WIN32 | ||||
@@ -30,6 +31,11 @@ | |||||
typedef void (*TTL_Generator_Function)(const char* basename); | typedef void (*TTL_Generator_Function)(const char* basename); | ||||
static int isPathSeparator(char c); | |||||
static char* makeNormalPath(const char* path); | |||||
// TODO support Unicode paths on the Windows platform | |||||
int main(int argc, char* argv[]) | int main(int argc, char* argv[]) | ||||
{ | { | ||||
if (argc != 2) | if (argc != 2) | ||||
@@ -38,10 +44,12 @@ int main(int argc, char* argv[]) | |||||
return 1; | return 1; | ||||
} | } | ||||
const char* path = argv[1]; | |||||
#ifdef TTL_GENERATOR_WINDOWS | #ifdef TTL_GENERATOR_WINDOWS | ||||
const HMODULE handle = LoadLibraryA(argv[1]); | |||||
const HMODULE handle = LoadLibraryA(path); | |||||
#else | #else | ||||
void* const handle = dlopen(argv[1], RTLD_LAZY); | |||||
void* const handle = dlopen(path, RTLD_LAZY); | |||||
#endif | #endif | ||||
if (! handle) | if (! handle) | ||||
@@ -62,31 +70,32 @@ int main(int argc, char* argv[]) | |||||
if (ttlFn != NULL) | if (ttlFn != NULL) | ||||
{ | { | ||||
char basename[strlen(argv[1])+1]; | |||||
// convert the paths to a normalized form, such that path separators are | |||||
// replaced with '/', and duplicate separators are removed | |||||
char* normalPath = makeNormalPath(path); | |||||
#ifdef TTL_GENERATOR_WINDOWS | |||||
char* base2 = strrchr(argv[1], '\\'); | |||||
#else | |||||
char* base2 = strrchr(argv[1], '/'); | |||||
#endif | |||||
if (base2 != NULL) | |||||
{ | |||||
strcpy(basename, base2+1); | |||||
basename[strrchr(base2, '.')-base2-1] = '\0'; | |||||
} | |||||
else if (argv[1][0] == '.' && argv[1][1] == '/') | |||||
{ | |||||
strcpy(basename, argv[1]+2); | |||||
basename[strrchr(basename, '.')-basename] = '\0'; | |||||
} | |||||
// get rid of any "./" prefixes | |||||
path = normalPath; | |||||
while (path[0] == '.' && path[1] == '/') | |||||
path += 2; | |||||
// extract the file name part | |||||
char* basename = strrchr(path, '/'); | |||||
if (basename != NULL) | |||||
basename += 1; | |||||
else | else | ||||
{ | |||||
strcpy(basename, argv[1]); | |||||
} | |||||
basename = (char*)path; | |||||
// remove the file extension | |||||
char* dotPos = strrchr(basename, '.'); | |||||
if (dotPos) | |||||
*dotPos = '\0'; | |||||
printf("Generate ttl data for '%s', basename: '%s'\n", argv[1], basename); | |||||
printf("Generate ttl data for '%s', basename: '%s'\n", path, basename); | |||||
ttlFn(basename); | ttlFn(basename); | ||||
free(normalPath); | |||||
} | } | ||||
else | else | ||||
printf("Failed to find 'lv2_generate_ttl' function\n"); | printf("Failed to find 'lv2_generate_ttl' function\n"); | ||||
@@ -99,3 +108,31 @@ int main(int argc, char* argv[]) | |||||
return 0; | return 0; | ||||
} | } | ||||
static int isPathSeparator(char c) | |||||
{ | |||||
#ifdef TTL_GENERATOR_WINDOWS | |||||
return c == '/' || c == '\\'; | |||||
#else | |||||
return c == '/'; | |||||
#endif | |||||
} | |||||
static char* makeNormalPath(const char* path) | |||||
{ | |||||
size_t i, j; | |||||
size_t len = strlen(path); | |||||
char* result = (char*)malloc(len + 1); | |||||
int isSep, wasSep = 0; | |||||
for (i = 0, j = 0; i < len; ++i) | |||||
{ | |||||
isSep = isPathSeparator(path[i]); | |||||
if (!isSep) | |||||
result[j++] = path[i]; | |||||
else if (!wasSep) | |||||
result[j++] = '/'; | |||||
wasSep = isSep; | |||||
} | |||||
result[j] = '\0'; | |||||
return result; | |||||
} |