diff --git a/.idea/LipSync.iml b/.idea/LipSync.iml index a1cde36..30ebdaf 100644 --- a/.idea/LipSync.iml +++ b/.idea/LipSync.iml @@ -145,8 +145,8 @@ + - diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d9eca9..c032bbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,12 +14,7 @@ set(Boost_USE_STATIC_RUNTIME ON) # Use static C++ runtime find_package(Boost REQUIRED COMPONENTS filesystem locale system) include_directories(${Boost_INCLUDE_DIRS}) -set(SOURCE_FILES src/main.cpp src/audio_input/WaveFileReader.cpp src/audio_input/WaveFileReader.h src/audio_input/ChannelDownmixer.cpp src/audio_input/ChannelDownmixer.h src/audio_input/AudioStream.h src/audio_input/SampleRateConverter.cpp src/audio_input/SampleRateConverter.h src/audio_input/wave_file_writing.cpp src/audio_input/wave_file_writing.h src/audio_input/io_tools.h src/platform_tools.h src/phone_extraction.cpp src/phone_extraction.h src/Phone.cpp src/Phone.h src/centiseconds.cpp src/centiseconds.h src/tools.cpp src/tools.h src/Shape.cpp src/Shape.h src/mouth_animation.cpp src/mouth_animation.h) -if(WIN32) - set(SOURCE_FILES "${SOURCE_FILES};src/platform_tools_win.cpp") -else() - message(FATAL_ERROR "Target platform not supported.") -endif() +set(SOURCE_FILES src/main.cpp src/audio_input/WaveFileReader.cpp src/audio_input/WaveFileReader.h src/audio_input/ChannelDownmixer.cpp src/audio_input/ChannelDownmixer.h src/audio_input/AudioStream.h src/audio_input/SampleRateConverter.cpp src/audio_input/SampleRateConverter.h src/audio_input/wave_file_writing.cpp src/audio_input/wave_file_writing.h src/audio_input/io_tools.h src/platform_tools.cpp src/platform_tools.h src/phone_extraction.cpp src/phone_extraction.h src/Phone.cpp src/Phone.h src/centiseconds.cpp src/centiseconds.h src/tools.cpp src/tools.h src/Shape.cpp src/Shape.h src/mouth_animation.cpp src/mouth_animation.h) include_directories("lib/sphinxbase-5prealpha-2015-08-05/include" "lib/pocketsphinx-5prealpha-2015-08-05/include" "lib/cppformat") FILE(GLOB_RECURSE SPHINX_BASE "lib/sphinxbase-5prealpha-2015-08-05/src/libsphinxbase/*.c") diff --git a/src/platform_tools.cpp b/src/platform_tools.cpp new file mode 100644 index 0000000..72249d6 --- /dev/null +++ b/src/platform_tools.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include + +#include "platform_tools.h" + +using boost::filesystem::path; + +constexpr int InitialBufferSize = 256; + +#if (BOOST_OS_CYGWIN || BOOST_OS_WINDOWS) + + #include + + path getBinPathImpl() { + std::vector buffer(InitialBufferSize); + + // Try to get the executable path with a buffer of MAX_PATH characters. + DWORD result = GetModuleFileNameW(0, buffer.data(), buffer.size()); + + // As long the function returns the buffer size, it is indicating that the buffer + // was too small. Keep doubling the buffer size until it fits. + while (result == buffer.size()) { + buffer.resize(buffer.size() * 2); + result = GetModuleFileNameW(0, buffer.data(), buffer.size()); + } + + // If the function returned 0, something went wrong + if (result == 0) { + DWORD error = GetLastError(); + throw std::runtime_error(fmt::format("`GetModuleFileNameW` failed. Error code: {0}", error)); + } + + return path(buffer.data()); + } + +#elif (BOOST_OS_MACOS) + + #include + + path getBinPathImpl() { + std::vector buffer(InitialBufferSize); + uint32_t size = buffer.size(); + int result = _NSGetExecutablePath(buffer.data(), &size); + if (result == -1) { + // Insufficient buffer. Resize. + buffer.resize(size); + result = _NSGetExecutablePath(buffer.data(), &size); + } + if (result != 0) { + throw std::runtime_error(fmt::format("`_NSGetExecutablePath` failed. Error code: {0}", result)); + } + return path(buffer.data()); + } + +#elif (BOOST_OS_SOLARIS) + + #include + + path getBinPathImpl() { + const char* executableName = getexecname(); + if (!executableName) { + throw std::runtime_error("`getexecname` failed.")); + } + return path(executableName); + } + +#elif (BOOST_OS_BSD) + + #include + #include + + path getBinPathImpl() { + // Determine required buffer size + std::array mib = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t size = 0; + sysctl(mib.data(), mib.size(), nullptr, &size, nullptr, 0); + + // Get path + std::vector buffer(size); + int result = sysctl(mib.data(), mib.size(), buffer.data(), &size, nullptr, 0); + if (result == -1) { + throw std::runtime_error(fmt::format("`sysctl` failed. Error code: {0}", errno)); + } + + return path(std::string(buffer, size)); + } + +#elif (BOOST_OS_LINUX) + + #include + #include + + path getBinPathImpl() { + // Determine required buffer size + stat info; + const char* selfPath = "/proc/self/exe"; + int result = lstat(selfPath, &stat); + if (result == -1) { + throw std::runtime_error(fmt::format("`lstat` failed. Error code: {0}", errno)); + } + + // Get path + std::vector buffer(info.st_size); + result = readlink(selfPath, buffer.data(), buffer.size()); + if (result == -1) { + throw std::runtime_error(fmt::format("`readlink` failed. Error code: {0}", errno)); + } + + return path(std::string(buffer, buffer.size())); + } + +#else + + #error "Unsupported platform." + +#endif + +path getBinPath() { + try { + static path binPath(boost::filesystem::canonical(getBinPathImpl()).make_preferred()); + return binPath; + } catch (...) { + std::throw_with_nested(std::runtime_error("Could not determine path of bin directory.") ); + } +} + +path getBinDirectory() { + return getBinPath().parent_path(); +} diff --git a/src/platform_tools.h b/src/platform_tools.h index 55d27ea..ee5abc2 100644 --- a/src/platform_tools.h +++ b/src/platform_tools.h @@ -3,6 +3,7 @@ #include +boost::filesystem::path getBinPath(); boost::filesystem::path getBinDirectory(); #endif //LIPSYNC_PLATFORM_TOOLS_H diff --git a/src/platform_tools_win.cpp b/src/platform_tools_win.cpp deleted file mode 100644 index 1dda5cf..0000000 --- a/src/platform_tools_win.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include "tools.h" -#include "platform_tools.h" - -boost::filesystem::path getBinDirectory() { - std::vector executablePath(MAX_PATH); - - // Try to get the executable path with a buffer of MAX_PATH characters. - DWORD result = GetModuleFileNameW(0, executablePath.data(), executablePath.size()); - - // As long the function returns the buffer size, it is indicating that the buffer - // was too small. Keep doubling the buffer size until it fits. - while(result == executablePath.size()) { - executablePath.resize(executablePath.size() * 2); - result = GetModuleFileNameW(0, executablePath.data(), executablePath.size()); - } - - // If the function returned 0, something went wrong - if (result == 0) { - throw std::runtime_error("Could not determine path of bin directory."); - } - - return boost::filesystem::path(executablePath.data()).parent_path(); -}