The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

478 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. // (This file gets included by juce_win32_NativeCode.cpp, rather than being
  24. // compiled on its own).
  25. #if JUCE_INCLUDED_FILE
  26. extern void juce_updateMultiMonitorInfo() throw();
  27. extern void juce_initialiseThreadEvents() throw();
  28. //==============================================================================
  29. void Logger::outputDebugString (const String& text) throw()
  30. {
  31. OutputDebugString (text + T("\n"));
  32. }
  33. void Logger::outputDebugPrintf (const tchar* format, ...) throw()
  34. {
  35. String text;
  36. va_list args;
  37. va_start (args, format);
  38. text.vprintf(format, args);
  39. outputDebugString (text);
  40. }
  41. //==============================================================================
  42. static int64 hiResTicksPerSecond;
  43. static double hiResTicksScaleFactor;
  44. //==============================================================================
  45. #if JUCE_USE_INTRINSICS
  46. // CPU info functions using intrinsics...
  47. #pragma intrinsic (__cpuid)
  48. #pragma intrinsic (__rdtsc)
  49. /*static unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0) throw()
  50. {
  51. int info [4];
  52. __cpuid (info, 1);
  53. if (familyModel != 0)
  54. *familyModel = info [0];
  55. if (extFeatures != 0)
  56. *extFeatures = info[1];
  57. return info[3];
  58. }*/
  59. const String SystemStats::getCpuVendor() throw()
  60. {
  61. int info [4];
  62. __cpuid (info, 0);
  63. char v [12];
  64. memcpy (v, info + 1, 4);
  65. memcpy (v + 4, info + 3, 4);
  66. memcpy (v + 8, info + 2, 4);
  67. return String (v, 12);
  68. }
  69. #else
  70. //==============================================================================
  71. // CPU info functions using old fashioned inline asm...
  72. /*static juce_noinline unsigned int getCPUIDWord (int* familyModel = 0, int* extFeatures = 0)
  73. {
  74. unsigned int cpu = 0;
  75. unsigned int ext = 0;
  76. unsigned int family = 0;
  77. #if JUCE_GCC
  78. unsigned int dummy = 0;
  79. #endif
  80. #ifndef __MINGW32__
  81. __try
  82. #endif
  83. {
  84. #if JUCE_GCC
  85. __asm__ ("cpuid" : "=a" (family), "=b" (ext), "=c" (dummy),"=d" (cpu) : "a" (1));
  86. #else
  87. __asm
  88. {
  89. mov eax, 1
  90. cpuid
  91. mov cpu, edx
  92. mov family, eax
  93. mov ext, ebx
  94. }
  95. #endif
  96. }
  97. #ifndef __MINGW32__
  98. __except (EXCEPTION_EXECUTE_HANDLER)
  99. {
  100. return 0;
  101. }
  102. #endif
  103. if (familyModel != 0)
  104. *familyModel = family;
  105. if (extFeatures != 0)
  106. *extFeatures = ext;
  107. return cpu;
  108. }*/
  109. static void juce_getCpuVendor (char* const v)
  110. {
  111. int vendor[4];
  112. zeromem (vendor, 16);
  113. #ifdef JUCE_64BIT
  114. #else
  115. #ifndef __MINGW32__
  116. __try
  117. #endif
  118. {
  119. #if JUCE_GCC
  120. unsigned int dummy = 0;
  121. __asm__ ("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]),"=d" (vendor[1]) : "a" (0));
  122. #else
  123. __asm
  124. {
  125. mov eax, 0
  126. cpuid
  127. mov [vendor], ebx
  128. mov [vendor + 4], edx
  129. mov [vendor + 8], ecx
  130. }
  131. #endif
  132. }
  133. #ifndef __MINGW32__
  134. __except (EXCEPTION_EXECUTE_HANDLER)
  135. {
  136. *v = 0;
  137. }
  138. #endif
  139. #endif
  140. memcpy (v, vendor, 16);
  141. }
  142. const String SystemStats::getCpuVendor() throw()
  143. {
  144. char v [16];
  145. juce_getCpuVendor (v);
  146. return String (v, 16);
  147. }
  148. #endif
  149. //==============================================================================
  150. struct CPUFlags
  151. {
  152. bool hasMMX : 1;
  153. bool hasSSE : 1;
  154. bool hasSSE2 : 1;
  155. bool has3DNow : 1;
  156. };
  157. static CPUFlags cpuFlags;
  158. bool SystemStats::hasMMX() throw()
  159. {
  160. return cpuFlags.hasMMX;
  161. }
  162. bool SystemStats::hasSSE() throw()
  163. {
  164. return cpuFlags.hasSSE;
  165. }
  166. bool SystemStats::hasSSE2() throw()
  167. {
  168. return cpuFlags.hasSSE2;
  169. }
  170. bool SystemStats::has3DNow() throw()
  171. {
  172. return cpuFlags.has3DNow;
  173. }
  174. void SystemStats::initialiseStats() throw()
  175. {
  176. juce_initialiseThreadEvents();
  177. cpuFlags.hasMMX = IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE) != 0;
  178. cpuFlags.hasSSE = IsProcessorFeaturePresent (PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
  179. cpuFlags.hasSSE2 = IsProcessorFeaturePresent (PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0;
  180. #ifdef PF_AMD3D_INSTRUCTIONS_AVAILABLE
  181. cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_AMD3D_INSTRUCTIONS_AVAILABLE) != 0;
  182. #else
  183. cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_3DNOW_INSTRUCTIONS_AVAILABLE) != 0;
  184. #endif
  185. LARGE_INTEGER f;
  186. QueryPerformanceFrequency (&f);
  187. hiResTicksPerSecond = f.QuadPart;
  188. hiResTicksScaleFactor = 1000.0 / hiResTicksPerSecond;
  189. String s (SystemStats::getJUCEVersion());
  190. #ifdef JUCE_DEBUG
  191. const MMRESULT res = timeBeginPeriod (1);
  192. jassert (res == TIMERR_NOERROR);
  193. #else
  194. timeBeginPeriod (1);
  195. #endif
  196. #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
  197. _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  198. #endif
  199. }
  200. //==============================================================================
  201. SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() throw()
  202. {
  203. OSVERSIONINFO info;
  204. info.dwOSVersionInfoSize = sizeof (info);
  205. GetVersionEx (&info);
  206. if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
  207. {
  208. switch (info.dwMajorVersion)
  209. {
  210. case 5:
  211. return (info.dwMinorVersion == 0) ? Win2000 : WinXP;
  212. case 6:
  213. return WinVista;
  214. default:
  215. jassertfalse // !! not a supported OS!
  216. break;
  217. }
  218. }
  219. else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  220. {
  221. jassert (info.dwMinorVersion != 0); // !! still running on Windows 95??
  222. return Win98;
  223. }
  224. return UnknownOS;
  225. }
  226. const String SystemStats::getOperatingSystemName() throw()
  227. {
  228. const char* name = "Unknown OS";
  229. switch (getOperatingSystemType())
  230. {
  231. case WinVista:
  232. name = "Windows Vista";
  233. break;
  234. case WinXP:
  235. name = "Windows XP";
  236. break;
  237. case Win2000:
  238. name = "Windows 2000";
  239. break;
  240. case Win98:
  241. name = "Windows 98";
  242. break;
  243. default:
  244. jassertfalse // !! new type of OS?
  245. break;
  246. }
  247. return name;
  248. }
  249. bool SystemStats::isOperatingSystem64Bit() throw()
  250. {
  251. #ifdef _WIN64
  252. return true;
  253. #else
  254. typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
  255. LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (L"kernel32"), "IsWow64Process");
  256. BOOL isWow64 = FALSE;
  257. return (fnIsWow64Process != 0)
  258. && fnIsWow64Process (GetCurrentProcess(), &isWow64)
  259. && (isWow64 != FALSE);
  260. #endif
  261. }
  262. //==============================================================================
  263. int SystemStats::getMemorySizeInMegabytes() throw()
  264. {
  265. MEMORYSTATUS mem;
  266. GlobalMemoryStatus (&mem);
  267. return (int) (mem.dwTotalPhys / (1024 * 1024)) + 1;
  268. }
  269. int SystemStats::getNumCpus() throw()
  270. {
  271. SYSTEM_INFO systemInfo;
  272. GetSystemInfo (&systemInfo);
  273. return systemInfo.dwNumberOfProcessors;
  274. }
  275. //==============================================================================
  276. uint32 juce_millisecondsSinceStartup() throw()
  277. {
  278. return (uint32) GetTickCount();
  279. }
  280. int64 Time::getHighResolutionTicks() throw()
  281. {
  282. LARGE_INTEGER ticks;
  283. QueryPerformanceCounter (&ticks);
  284. const int64 mainCounterAsHiResTicks = (GetTickCount() * hiResTicksPerSecond) / 1000;
  285. const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart;
  286. // fix for a very obscure PCI hardware bug that can make the counter
  287. // sometimes jump forwards by a few seconds..
  288. static int64 hiResTicksOffset = 0;
  289. const int64 offsetDrift = abs64 (newOffset - hiResTicksOffset);
  290. if (offsetDrift > (hiResTicksPerSecond >> 1))
  291. hiResTicksOffset = newOffset;
  292. return ticks.QuadPart + hiResTicksOffset;
  293. }
  294. double Time::getMillisecondCounterHiRes() throw()
  295. {
  296. return getHighResolutionTicks() * hiResTicksScaleFactor;
  297. }
  298. int64 Time::getHighResolutionTicksPerSecond() throw()
  299. {
  300. return hiResTicksPerSecond;
  301. }
  302. int64 SystemStats::getClockCycleCounter() throw()
  303. {
  304. #if JUCE_USE_INTRINSICS
  305. // MS intrinsics version...
  306. return __rdtsc();
  307. #elif JUCE_GCC
  308. // GNU inline asm version...
  309. unsigned int hi = 0, lo = 0;
  310. __asm__ __volatile__ (
  311. "xor %%eax, %%eax \n\
  312. xor %%edx, %%edx \n\
  313. rdtsc \n\
  314. movl %%eax, %[lo] \n\
  315. movl %%edx, %[hi]"
  316. :
  317. : [hi] "m" (hi),
  318. [lo] "m" (lo)
  319. : "cc", "eax", "ebx", "ecx", "edx", "memory");
  320. return (int64) ((((uint64) hi) << 32) | lo);
  321. #else
  322. // MSVC inline asm version...
  323. unsigned int hi = 0, lo = 0;
  324. __asm
  325. {
  326. xor eax, eax
  327. xor edx, edx
  328. rdtsc
  329. mov lo, eax
  330. mov hi, edx
  331. }
  332. return (int64) ((((uint64) hi) << 32) | lo);
  333. #endif
  334. }
  335. int SystemStats::getCpuSpeedInMegaherz() throw()
  336. {
  337. const int64 cycles = SystemStats::getClockCycleCounter();
  338. const uint32 millis = Time::getMillisecondCounter();
  339. int lastResult = 0;
  340. for (;;)
  341. {
  342. int n = 1000000;
  343. while (--n > 0) {}
  344. const uint32 millisElapsed = Time::getMillisecondCounter() - millis;
  345. const int64 cyclesNow = SystemStats::getClockCycleCounter();
  346. if (millisElapsed > 80)
  347. {
  348. const int newResult = (int) (((cyclesNow - cycles) / millisElapsed) / 1000);
  349. if (millisElapsed > 500 || (lastResult == newResult && newResult > 100))
  350. return newResult;
  351. lastResult = newResult;
  352. }
  353. }
  354. }
  355. //==============================================================================
  356. bool Time::setSystemTimeToThisTime() const throw()
  357. {
  358. SYSTEMTIME st;
  359. st.wDayOfWeek = 0;
  360. st.wYear = (WORD) getYear();
  361. st.wMonth = (WORD) (getMonth() + 1);
  362. st.wDay = (WORD) getDayOfMonth();
  363. st.wHour = (WORD) getHours();
  364. st.wMinute = (WORD) getMinutes();
  365. st.wSecond = (WORD) getSeconds();
  366. st.wMilliseconds = (WORD) (millisSinceEpoch % 1000);
  367. // do this twice because of daylight saving conversion problems - the
  368. // first one sets it up, the second one kicks it in.
  369. return SetLocalTime (&st) != 0
  370. && SetLocalTime (&st) != 0;
  371. }
  372. int SystemStats::getPageSize() throw()
  373. {
  374. SYSTEM_INFO systemInfo;
  375. GetSystemInfo (&systemInfo);
  376. return systemInfo.dwPageSize;
  377. }
  378. #endif