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