X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Fcross.cc;h=5d35d5a4bbcb28da70ca7b77f0ceec678c1a826e;hp=d84c17c55b25318ef5b32a0a06eda8ee23ac1d16;hb=5eb8b5c3a1566aef638e9d9df03b88d320735092;hpb=cb990adba9c57e5107ef2aa9716cf0a26c1df83d diff --git a/src/lib/cross.cc b/src/lib/cross.cc index d84c17c55..5d35d5a4b 100644 --- a/src/lib/cross.cc +++ b/src/lib/cross.cc @@ -1,27 +1,33 @@ /* - Copyright (C) 2012-2014 Carl Hetherington + Copyright (C) 2012-2018 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of DCP-o-matic. + + DCP-o-matic 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, + DCP-o-matic 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. + along with DCP-o-matic. If not, see . */ -#include -#include #include "cross.h" #include "compose.hpp" #include "log.h" +#include "dcpomatic_log.h" +#include "config.h" +#include "exceptions.h" +extern "C" { +#include +} +#include #ifdef DCPOMATIC_LINUX #include #include @@ -30,6 +36,8 @@ #include #undef DATADIR #include +#include +#include #endif #ifdef DCPOMATIC_OSX #include @@ -42,25 +50,22 @@ #include #include #endif -#include "exceptions.h" +#include #include "i18n.h" -#define LOG_GENERAL(...) log->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); -#define LOG_ERROR(...) log->log (String::compose (__VA_ARGS__), Log::TYPE_ERROR); -#define LOG_ERROR_NC(...) log->log (__VA_ARGS__, Log::TYPE_ERROR); - using std::pair; using std::list; using std::ifstream; using std::string; using std::wstring; using std::make_pair; +using std::runtime_error; using boost::shared_ptr; /** @param s Number of seconds to sleep for */ void -dcpomatic_sleep (int s) +dcpomatic_sleep_seconds (int s) { #ifdef DCPOMATIC_POSIX sleep (s); @@ -70,12 +75,23 @@ dcpomatic_sleep (int s) #endif } +void +dcpomatic_sleep_milliseconds (int ms) +{ +#ifdef DCPOMATIC_POSIX + usleep (ms * 1000); +#endif +#ifdef DCPOMATIC_WINDOWS + Sleep (ms); +#endif +} + /** @return A string of CPU information (model name etc.) */ string cpu_info () { string info; - + #ifdef DCPOMATIC_LINUX /* This use of ifstream is ok; the filename can never be non-Latin @@ -99,7 +115,7 @@ cpu_info () if (sysctlbyname ("machdep.cpu.brand_string", buffer, &N, 0, 0) == 0) { info = buffer; } -#endif +#endif #ifdef DCPOMATIC_WINDOWS HKEY key; @@ -124,11 +140,11 @@ cpu_info () } info = string (value.begin(), value.end()); - + RegCloseKey (key); -#endif - +#endif + return info; } @@ -140,9 +156,9 @@ app_contents () uint32_t size = 1024; char buffer[size]; if (_NSGetExecutablePath (buffer, &size)) { - throw StringError ("_NSGetExecutablePath failed"); + throw runtime_error ("_NSGetExecutablePath failed"); } - + boost::filesystem::path path (buffer); path = boost::filesystem::canonical (path); path = path.parent_path (); @@ -151,8 +167,30 @@ app_contents () } #endif +boost::filesystem::path +shared_path () +{ +#ifdef DCPOMATIC_LINUX + char const * p = getenv ("DCPOMATIC_LINUX_SHARE_PREFIX"); + if (p) { + return p; + } + return boost::filesystem::canonical (LINUX_SHARE_PREFIX); +#endif +#ifdef DCPOMATIC_WINDOWS + wchar_t dir[512]; + GetModuleFileName (GetModuleHandle (0), dir, sizeof (dir)); + PathRemoveFileSpec (dir); + boost::filesystem::path path = dir; + return path.parent_path(); +#endif +#ifdef DCPOMATIC_OSX + return app_contents() / "Resources"; +#endif +} + void -run_ffprobe (boost::filesystem::path content, boost::filesystem::path out, shared_ptr log) +run_ffprobe (boost::filesystem::path content, boost::filesystem::path out) { #ifdef DCPOMATIC_WINDOWS SECURITY_ATTRIBUTES security; @@ -219,7 +257,7 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out, share CloseHandle (child_stderr_read); #endif -#ifdef DCPOMATIC_LINUX +#ifdef DCPOMATIC_LINUX string ffprobe = "ffprobe \"" + content.string() + "\" 2> \"" + out.string() + "\""; LOG_GENERAL (N_("Probing with %1"), ffprobe); system (ffprobe.c_str ()); @@ -229,8 +267,8 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out, share boost::filesystem::path path = app_contents(); path /= "MacOS"; path /= "ffprobe"; - - string ffprobe = path.string() + " \"" + content.string() + "\" 2> \"" + out.string() + "\""; + + string ffprobe = "\"" + path.string() + "\" \"" + content.string() + "\" 2> \"" + out.string() + "\""; LOG_GENERAL (N_("Probing with %1"), ffprobe); system (ffprobe.c_str ()); #endif @@ -240,13 +278,13 @@ list > mount_info () { list > m; - + #ifdef DCPOMATIC_LINUX FILE* f = setmntent ("/etc/mtab", "r"); if (!f) { return m; } - + while (true) { struct mntent* mnt = getmntent (f); if (!mnt) { @@ -269,13 +307,21 @@ openssl_path () wchar_t dir[512]; GetModuleFileName (GetModuleHandle (0), dir, sizeof (dir)); PathRemoveFileSpec (dir); - + boost::filesystem::path path = dir; path /= "openssl.exe"; return path; -#else - /* We assume that it's on the path for Linux and OS X */ - return "openssl"; +#endif + +#ifdef DCPOMATIC_OSX + boost::filesystem::path path = app_contents(); + path /= "MacOS"; + path /= "openssl"; + return path; +#endif + +#ifdef DCPOMATIC_LINUX + return "dcpomatic2_openssl"; #endif } @@ -301,32 +347,192 @@ dcpomatic_fseek (FILE* stream, int64_t offset, int whence) { #ifdef DCPOMATIC_WINDOWS return _fseeki64 (stream, offset, whence); -#else +#else return fseek (stream, offset, whence); -#endif +#endif } void Waker::nudge () { #ifdef DCPOMATIC_WINDOWS + boost::mutex::scoped_lock lm (_mutex); SetThreadExecutionState (ES_SYSTEM_REQUIRED); -#endif +#endif } Waker::Waker () { #ifdef DCPOMATIC_OSX + boost::mutex::scoped_lock lm (_mutex); /* We should use this */ // IOPMAssertionCreateWithName (kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, CFSTR ("Encoding DCP"), &_assertion_id); /* but it's not available on 10.5, so we use this */ IOPMAssertionCreate (kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, &_assertion_id); -#endif +#endif } Waker::~Waker () { -#ifdef DCPOMATIC_OSX +#ifdef DCPOMATIC_OSX + boost::mutex::scoped_lock lm (_mutex); IOPMAssertionRelease (_assertion_id); -#endif +#endif +} + +void +start_tool (boost::filesystem::path dcpomatic, string executable, +#ifdef DCPOMATIC_OSX + string app +#else + string +#endif + ) +{ +#if defined(DCPOMATIC_LINUX) || defined(DCPOMATIC_WINDOWS) + boost::filesystem::path batch = dcpomatic.parent_path() / executable; +#endif + +#ifdef DCPOMATIC_OSX + boost::filesystem::path batch = dcpomatic.parent_path (); + batch = batch.parent_path (); // MacOS + batch = batch.parent_path (); // Contents + batch = batch.parent_path (); // DCP-o-matic.app + batch = batch.parent_path (); // Applications + batch /= app; + batch /= "Contents"; + batch /= "MacOS"; + batch /= executable; +#endif + +#if defined(DCPOMATIC_LINUX) || defined(DCPOMATIC_OSX) + pid_t pid = fork (); + if (pid == 0) { + int const r = system (batch.string().c_str()); + exit (WEXITSTATUS (r)); + } +#endif + +#ifdef DCPOMATIC_WINDOWS + STARTUPINFO startup_info; + ZeroMemory (&startup_info, sizeof (startup_info)); + startup_info.cb = sizeof (startup_info); + + PROCESS_INFORMATION process_info; + ZeroMemory (&process_info, sizeof (process_info)); + + wchar_t cmd[512]; + MultiByteToWideChar (CP_UTF8, 0, batch.string().c_str(), -1, cmd, sizeof(cmd)); + CreateProcess (0, cmd, 0, 0, FALSE, 0, 0, 0, &startup_info, &process_info); +#endif +} + +void +start_batch_converter (boost::filesystem::path dcpomatic) +{ + start_tool (dcpomatic, "dcpomatic2_batch", "DCP-o-matic\\ 2\\ Batch\\ Converter.app"); +} + +void +start_player (boost::filesystem::path dcpomatic) +{ + start_tool (dcpomatic, "dcpomatic2_player", "DCP-o-matic\\ 2\\ Player.app"); +} + +uint64_t +thread_id () +{ +#ifdef DCPOMATIC_WINDOWS + return (uint64_t) GetCurrentThreadId (); +#else + return (uint64_t) pthread_self (); +#endif +} + +int +avio_open_boost (AVIOContext** s, boost::filesystem::path file, int flags) +{ +#ifdef DCPOMATIC_WINDOWS + int const length = (file.string().length() + 1) * 2; + char* utf8 = new char[length]; + WideCharToMultiByte (CP_UTF8, 0, file.c_str(), -1, utf8, length, 0, 0); + int const r = avio_open (s, utf8, flags); + delete[] utf8; + return r; +#else + return avio_open (s, file.c_str(), flags); +#endif +} + +#ifdef DCPOMATIC_WINDOWS +void +maybe_open_console () +{ + if (Config::instance()->win32_console ()) { + AllocConsole(); + + HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); + int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT); + FILE* hf_out = _fdopen(hCrt, "w"); + setvbuf(hf_out, NULL, _IONBF, 1); + *stdout = *hf_out; + + HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); + hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT); + FILE* hf_in = _fdopen(hCrt, "r"); + setvbuf(hf_in, NULL, _IONBF, 128); + *stdin = *hf_in; + } +} +#endif + +boost::filesystem::path +home_directory () +{ +#if defined(DCPOMATIC_LINUX) || defined(DCPOMATIC_OSX) + return getenv("HOME"); +#endif +#ifdef DCPOMATIC_WINDOWS + return boost::filesystem::path(getenv("HOMEDRIVE")) / boost::filesystem::path(getenv("HOMEPATH")); +#endif +} + +string +command_and_read (string cmd) +{ +#ifdef DCPOMATIC_LINUX + FILE* pipe = popen (cmd.c_str(), "r"); + if (!pipe) { + throw runtime_error ("popen failed"); + } + + string result; + char buffer[128]; + try { + while (fgets(buffer, sizeof(buffer), pipe)) { + result += buffer; + } + } catch (...) { + pclose (pipe); + throw; + } + + pclose (pipe); + return result; +#endif + + return ""; +} + +/** @return true if this process is a 32-bit one running on a 64-bit-capable OS */ +bool +running_32_on_64 () +{ +#ifdef DCPOMATIC_WINDOWS + BOOL p; + IsWow64Process (GetCurrentProcess(), &p); + return p; +#endif + /* XXX: assuming nobody does this on Linux / OS X */ + return false; }