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.

510 lines
13KB

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