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.

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