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.

435 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. // (This file gets included by juce_win32_NativeCode.cpp, rather than being
  19. // compiled on its own).
  20. #if JUCE_INCLUDED_FILE
  21. #if ! JUCE_ONLY_BUILD_CORE_LIBRARY
  22. extern HWND juce_messageWindowHandle;
  23. #endif
  24. //==============================================================================
  25. #if ! JUCE_USE_INTRINSICS
  26. // In newer compilers, the inline versions of these are used (in juce_Atomic.h), but in
  27. // older ones we have to actually call the ops as win32 functions..
  28. long juce_InterlockedExchange (volatile long* a, long b) throw() { return InterlockedExchange (a, b); }
  29. long juce_InterlockedIncrement (volatile long* a) throw() { return InterlockedIncrement (a); }
  30. long juce_InterlockedDecrement (volatile long* a) throw() { return InterlockedDecrement (a); }
  31. long juce_InterlockedExchangeAdd (volatile long* a, long b) throw() { return InterlockedExchangeAdd (a, b); }
  32. long juce_InterlockedCompareExchange (volatile long* a, long b, long c) throw() { return InterlockedCompareExchange (a, b, c); }
  33. __int64 juce_InterlockedCompareExchange64 (volatile __int64* value, __int64 newValue, __int64 valueToCompare) throw()
  34. {
  35. jassertfalse; // This operation isn't available in old MS compiler versions!
  36. __int64 oldValue = *value;
  37. if (oldValue == valueToCompare)
  38. *value = newValue;
  39. return oldValue;
  40. }
  41. #endif
  42. //==============================================================================
  43. CriticalSection::CriticalSection() throw()
  44. {
  45. // (just to check the MS haven't changed this structure and broken things...)
  46. #if _MSC_VER >= 1400
  47. static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (internal));
  48. #else
  49. static_jassert (sizeof (CRITICAL_SECTION) <= 24);
  50. #endif
  51. InitializeCriticalSection ((CRITICAL_SECTION*) internal);
  52. }
  53. CriticalSection::~CriticalSection() throw()
  54. {
  55. DeleteCriticalSection ((CRITICAL_SECTION*) internal);
  56. }
  57. void CriticalSection::enter() const throw()
  58. {
  59. EnterCriticalSection ((CRITICAL_SECTION*) internal);
  60. }
  61. bool CriticalSection::tryEnter() const throw()
  62. {
  63. return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE;
  64. }
  65. void CriticalSection::exit() const throw()
  66. {
  67. LeaveCriticalSection ((CRITICAL_SECTION*) internal);
  68. }
  69. //==============================================================================
  70. WaitableEvent::WaitableEvent (const bool manualReset) throw()
  71. : internal (CreateEvent (0, manualReset ? TRUE : FALSE, FALSE, 0))
  72. {
  73. }
  74. WaitableEvent::~WaitableEvent() throw()
  75. {
  76. CloseHandle (internal);
  77. }
  78. bool WaitableEvent::wait (const int timeOutMillisecs) const throw()
  79. {
  80. return WaitForSingleObject (internal, timeOutMillisecs) == WAIT_OBJECT_0;
  81. }
  82. void WaitableEvent::signal() const throw()
  83. {
  84. SetEvent (internal);
  85. }
  86. void WaitableEvent::reset() const throw()
  87. {
  88. ResetEvent (internal);
  89. }
  90. //==============================================================================
  91. void JUCE_API juce_threadEntryPoint (void*);
  92. static unsigned int __stdcall threadEntryProc (void* userData)
  93. {
  94. #if ! JUCE_ONLY_BUILD_CORE_LIBRARY
  95. AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0),
  96. GetCurrentThreadId(), TRUE);
  97. #endif
  98. juce_threadEntryPoint (userData);
  99. _endthreadex (0);
  100. return 0;
  101. }
  102. void juce_CloseThreadHandle (void* handle)
  103. {
  104. CloseHandle ((HANDLE) handle);
  105. }
  106. void* juce_createThread (void* userData)
  107. {
  108. unsigned int threadId;
  109. return (void*) _beginthreadex (0, 0, &threadEntryProc, userData, 0, &threadId);
  110. }
  111. void juce_killThread (void* handle)
  112. {
  113. if (handle != 0)
  114. {
  115. #if JUCE_DEBUG
  116. OutputDebugString (_T("** Warning - Forced thread termination **\n"));
  117. #endif
  118. TerminateThread (handle, 0);
  119. }
  120. }
  121. void juce_setCurrentThreadName (const String& name)
  122. {
  123. #if JUCE_DEBUG && JUCE_MSVC
  124. struct
  125. {
  126. DWORD dwType;
  127. LPCSTR szName;
  128. DWORD dwThreadID;
  129. DWORD dwFlags;
  130. } info;
  131. info.dwType = 0x1000;
  132. info.szName = name.toCString();
  133. info.dwThreadID = GetCurrentThreadId();
  134. info.dwFlags = 0;
  135. __try
  136. {
  137. RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
  138. }
  139. __except (EXCEPTION_CONTINUE_EXECUTION)
  140. {}
  141. #else
  142. (void) name;
  143. #endif
  144. }
  145. Thread::ThreadID Thread::getCurrentThreadId()
  146. {
  147. return (ThreadID) (pointer_sized_int) GetCurrentThreadId();
  148. }
  149. // priority 1 to 10 where 5=normal, 1=low
  150. bool juce_setThreadPriority (void* threadHandle, int priority)
  151. {
  152. int pri = THREAD_PRIORITY_TIME_CRITICAL;
  153. if (priority < 1)
  154. pri = THREAD_PRIORITY_IDLE;
  155. else if (priority < 2)
  156. pri = THREAD_PRIORITY_LOWEST;
  157. else if (priority < 5)
  158. pri = THREAD_PRIORITY_BELOW_NORMAL;
  159. else if (priority < 7)
  160. pri = THREAD_PRIORITY_NORMAL;
  161. else if (priority < 9)
  162. pri = THREAD_PRIORITY_ABOVE_NORMAL;
  163. else if (priority < 10)
  164. pri = THREAD_PRIORITY_HIGHEST;
  165. if (threadHandle == 0)
  166. threadHandle = GetCurrentThread();
  167. return SetThreadPriority (threadHandle, pri) != FALSE;
  168. }
  169. void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)
  170. {
  171. SetThreadAffinityMask (GetCurrentThread(), affinityMask);
  172. }
  173. static HANDLE sleepEvent = 0;
  174. void juce_initialiseThreadEvents()
  175. {
  176. if (sleepEvent == 0)
  177. #if JUCE_DEBUG
  178. sleepEvent = CreateEvent (0, 0, 0, _T("Juce Sleep Event"));
  179. #else
  180. sleepEvent = CreateEvent (0, 0, 0, 0);
  181. #endif
  182. }
  183. void Thread::yield()
  184. {
  185. Sleep (0);
  186. }
  187. void JUCE_CALLTYPE Thread::sleep (const int millisecs)
  188. {
  189. if (millisecs >= 10)
  190. {
  191. Sleep (millisecs);
  192. }
  193. else
  194. {
  195. jassert (sleepEvent != 0);
  196. // unlike Sleep() this is guaranteed to return to the current thread after
  197. // the time expires, so we'll use this for short waits, which are more likely
  198. // to need to be accurate
  199. WaitForSingleObject (sleepEvent, millisecs);
  200. }
  201. }
  202. //==============================================================================
  203. static int lastProcessPriority = -1;
  204. // called by WindowDriver because Windows does wierd things to process priority
  205. // when you swap apps, and this forces an update when the app is brought to the front.
  206. void juce_repeatLastProcessPriority()
  207. {
  208. if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..)
  209. {
  210. DWORD p;
  211. switch (lastProcessPriority)
  212. {
  213. case Process::LowPriority: p = IDLE_PRIORITY_CLASS; break;
  214. case Process::NormalPriority: p = NORMAL_PRIORITY_CLASS; break;
  215. case Process::HighPriority: p = HIGH_PRIORITY_CLASS; break;
  216. case Process::RealtimePriority: p = REALTIME_PRIORITY_CLASS; break;
  217. default: jassertfalse; return; // bad priority value
  218. }
  219. SetPriorityClass (GetCurrentProcess(), p);
  220. }
  221. }
  222. void Process::setPriority (ProcessPriority prior)
  223. {
  224. if (lastProcessPriority != (int) prior)
  225. {
  226. lastProcessPriority = (int) prior;
  227. juce_repeatLastProcessPriority();
  228. }
  229. }
  230. bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger()
  231. {
  232. return IsDebuggerPresent() != FALSE;
  233. }
  234. bool JUCE_CALLTYPE Process::isRunningUnderDebugger()
  235. {
  236. return juce_isRunningUnderDebugger();
  237. }
  238. //==============================================================================
  239. void Process::raisePrivilege()
  240. {
  241. jassertfalse // xxx not implemented
  242. }
  243. void Process::lowerPrivilege()
  244. {
  245. jassertfalse // xxx not implemented
  246. }
  247. void Process::terminate()
  248. {
  249. #if JUCE_DEBUG && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
  250. _CrtDumpMemoryLeaks();
  251. #endif
  252. // bullet in the head in case there's a problem shutting down..
  253. ExitProcess (0);
  254. }
  255. //==============================================================================
  256. void* PlatformUtilities::loadDynamicLibrary (const String& name)
  257. {
  258. void* result = 0;
  259. JUCE_TRY
  260. {
  261. result = LoadLibrary (name);
  262. }
  263. JUCE_CATCH_ALL
  264. return result;
  265. }
  266. void PlatformUtilities::freeDynamicLibrary (void* h)
  267. {
  268. JUCE_TRY
  269. {
  270. if (h != 0)
  271. FreeLibrary ((HMODULE) h);
  272. }
  273. JUCE_CATCH_ALL
  274. }
  275. void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name)
  276. {
  277. return (h != 0) ? GetProcAddress ((HMODULE) h, name.toCString()) : 0;
  278. }
  279. //==============================================================================
  280. class InterProcessLock::Pimpl
  281. {
  282. public:
  283. Pimpl (const String& name, const int timeOutMillisecs)
  284. : handle (0), refCount (1)
  285. {
  286. handle = CreateMutex (0, TRUE, "Global\\" + name.replaceCharacter ('\\','/'));
  287. if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
  288. {
  289. if (timeOutMillisecs == 0)
  290. {
  291. close();
  292. return;
  293. }
  294. switch (WaitForSingleObject (handle, timeOutMillisecs < 0 ? INFINITE : timeOutMillisecs))
  295. {
  296. case WAIT_OBJECT_0:
  297. case WAIT_ABANDONED:
  298. break;
  299. case WAIT_TIMEOUT:
  300. default:
  301. close();
  302. break;
  303. }
  304. }
  305. }
  306. ~Pimpl()
  307. {
  308. close();
  309. }
  310. void close()
  311. {
  312. if (handle != 0)
  313. {
  314. ReleaseMutex (handle);
  315. CloseHandle (handle);
  316. handle = 0;
  317. }
  318. }
  319. HANDLE handle;
  320. int refCount;
  321. };
  322. InterProcessLock::InterProcessLock (const String& name_)
  323. : name (name_)
  324. {
  325. }
  326. InterProcessLock::~InterProcessLock()
  327. {
  328. }
  329. bool InterProcessLock::enter (const int timeOutMillisecs)
  330. {
  331. const ScopedLock sl (lock);
  332. if (pimpl == 0)
  333. {
  334. pimpl = new Pimpl (name, timeOutMillisecs);
  335. if (pimpl->handle == 0)
  336. pimpl = 0;
  337. }
  338. else
  339. {
  340. pimpl->refCount++;
  341. }
  342. return pimpl != 0;
  343. }
  344. void InterProcessLock::exit()
  345. {
  346. const ScopedLock sl (lock);
  347. // Trying to release the lock too many times!
  348. jassert (pimpl != 0);
  349. if (pimpl != 0 && --(pimpl->refCount) == 0)
  350. pimpl = 0;
  351. }
  352. #endif