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.

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