You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
5.5KB

  1. #include "system.hpp"
  2. #include "string.hpp"
  3. #include <thread>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #if defined ARCH_LIN || defined ARCH_MAC
  7. #include <pthread.h>
  8. #include <sched.h>
  9. #include <execinfo.h> // for backtrace and backtrace_symbols
  10. #include <unistd.h> // for execl
  11. #include <sys/utsname.h>
  12. #endif
  13. #if defined ARCH_WIN
  14. #include <windows.h>
  15. #include <shellapi.h>
  16. #include <processthreadsapi.h>
  17. #include <dbghelp.h>
  18. #endif
  19. namespace rack {
  20. namespace system {
  21. std::list<std::string> listEntries(const std::string &path) {
  22. std::list<std::string> filenames;
  23. DIR *dir = opendir(path.c_str());
  24. if (dir) {
  25. struct dirent *d;
  26. while ((d = readdir(dir))) {
  27. std::string filename = d->d_name;
  28. if (filename == "." || filename == "..")
  29. continue;
  30. filenames.push_back(path + "/" + filename);
  31. }
  32. closedir(dir);
  33. }
  34. filenames.sort();
  35. return filenames;
  36. }
  37. bool isFile(const std::string &path) {
  38. struct stat statbuf;
  39. if (stat(path.c_str(), &statbuf))
  40. return false;
  41. return S_ISREG(statbuf.st_mode);
  42. }
  43. bool isDirectory(const std::string &path) {
  44. struct stat statbuf;
  45. if (stat(path.c_str(), &statbuf))
  46. return false;
  47. return S_ISDIR(statbuf.st_mode);
  48. }
  49. void copyFile(const std::string &srcPath, const std::string &destPath) {
  50. // Open files
  51. FILE *source = fopen(srcPath.c_str(), "rb");
  52. if (!source)
  53. return;
  54. DEFER({
  55. fclose(source);
  56. });
  57. FILE *dest = fopen(destPath.c_str(), "wb");
  58. if (!dest)
  59. return;
  60. DEFER({
  61. fclose(dest);
  62. });
  63. // Copy buffer
  64. const int bufferSize = (1<<15);
  65. char buffer[bufferSize];
  66. while (1) {
  67. size_t size = fread(buffer, 1, bufferSize, source);
  68. if (size == 0)
  69. break;
  70. size = fwrite(buffer, 1, size, dest);
  71. if (size == 0)
  72. break;
  73. }
  74. }
  75. void createDirectory(const std::string &path) {
  76. #if defined ARCH_WIN
  77. std::wstring pathW = string::toWstring(path);
  78. CreateDirectoryW(pathW.c_str(), NULL);
  79. #else
  80. mkdir(path.c_str(), 0755);
  81. #endif
  82. }
  83. int getLogicalCoreCount() {
  84. // TODO Return the physical cores, not logical cores.
  85. return std::thread::hardware_concurrency();
  86. }
  87. void setThreadName(const std::string &name) {
  88. #if defined ARCH_LIN
  89. pthread_setname_np(pthread_self(), name.c_str());
  90. #elif defined ARCH_WIN
  91. // Unsupported on Windows
  92. #endif
  93. }
  94. void setThreadRealTime(bool realTime) {
  95. #if defined ARCH_LIN
  96. int err;
  97. int policy;
  98. struct sched_param param;
  99. if (realTime) {
  100. // Round-robin scheduler policy
  101. policy = SCHED_RR;
  102. param.sched_priority = sched_get_priority_max(policy);
  103. }
  104. else {
  105. // Default scheduler policy
  106. policy = 0;
  107. param.sched_priority = 0;
  108. }
  109. err = pthread_setschedparam(pthread_self(), policy, &param);
  110. assert(!err);
  111. // pthread_getschedparam(pthread_self(), &policy, &param);
  112. // DEBUG("policy %d priority %d", policy, param.sched_priority);
  113. #elif defined ARCH_MAC
  114. // Not yet implemented
  115. #elif defined ARCH_WIN
  116. // Set process class first
  117. if (realTime) {
  118. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  119. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  120. }
  121. else {
  122. SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
  123. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  124. }
  125. #endif
  126. }
  127. std::string getStackTrace() {
  128. int stackLen = 128;
  129. void *stack[stackLen];
  130. std::string s;
  131. #if defined ARCH_LIN || defined ARCH_MAC
  132. stackLen = backtrace(stack, stackLen);
  133. char **strings = backtrace_symbols(stack, stackLen);
  134. for (int i = 1; i < stackLen; i++) {
  135. s += string::f("%d: %s\n", stackLen - i - 1, strings[i]);
  136. }
  137. free(strings);
  138. #elif defined ARCH_WIN
  139. HANDLE process = GetCurrentProcess();
  140. SymInitialize(process, NULL, true);
  141. stackLen = CaptureStackBackTrace(0, stackLen, stack, NULL);
  142. SYMBOL_INFO *symbol = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 256, 1);
  143. symbol->MaxNameLen = 255;
  144. symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  145. for (int i = 1; i < stackLen; i++) {
  146. SymFromAddr(process, (DWORD64) stack[i], 0, symbol);
  147. s += string::f("%d: %s 0x%0x\n", stackLen - i - 1, symbol->Name, symbol->Address);
  148. }
  149. free(symbol);
  150. #endif
  151. return s;
  152. }
  153. void openBrowser(const std::string &url) {
  154. #if defined ARCH_LIN
  155. std::string command = "xdg-open \"" + url + "\"";
  156. (void) std::system(command.c_str());
  157. #endif
  158. #if defined ARCH_MAC
  159. std::string command = "open \"" + url + "\"";
  160. std::system(command.c_str());
  161. #endif
  162. #if defined ARCH_WIN
  163. std::wstring urlW = string::toWstring(url);
  164. ShellExecuteW(NULL, L"open", urlW.c_str(), NULL, NULL, SW_SHOWNORMAL);
  165. #endif
  166. }
  167. void openFolder(const std::string &path) {
  168. #if defined ARCH_LIN
  169. std::string command = "xdg-open \"" + path + "\"";
  170. (void) std::system(command.c_str());
  171. #endif
  172. #if defined ARCH_WIN
  173. std::wstring pathW = string::toWstring(path);
  174. ShellExecuteW(NULL, L"explorer", pathW.c_str(), NULL, NULL, SW_SHOWNORMAL);
  175. #endif
  176. }
  177. void runProcessAsync(const std::string &path) {
  178. #if defined ARCH_WIN
  179. STARTUPINFOW startupInfo;
  180. PROCESS_INFORMATION processInfo;
  181. std::memset(&startupInfo, 0, sizeof(startupInfo));
  182. startupInfo.cb = sizeof(startupInfo);
  183. std::memset(&processInfo, 0, sizeof(processInfo));
  184. std::wstring pathW = string::toWstring(path);
  185. CreateProcessW(pathW.c_str(), NULL,
  186. NULL, NULL, false, 0, NULL, NULL,
  187. &startupInfo, &processInfo);
  188. #endif
  189. }
  190. std::string getOperatingSystemInfo() {
  191. #if defined ARCH_LIN || defined ARCH_MAC
  192. struct utsname u;
  193. uname(&u);
  194. return string::f("%s %s %s %s", u.sysname, u.release, u.version, u.machine);
  195. #elif defined ARCH_WIN
  196. OSVERSIONINFOW info;
  197. ZeroMemory(&info, sizeof(info));
  198. info.dwOSVersionInfoSize = sizeof(info);
  199. GetVersionExW(&info);
  200. return string::f("Windows %u.%u", info.dwMajorVersion, info.dwMinorVersion);
  201. #endif
  202. }
  203. } // namespace system
  204. } // namespace rack