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.

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