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.

396 lines
10KB

  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. // (This file gets included by juce_win32_NativeCode.cpp, rather than being
  24. // compiled on its own).
  25. #if JUCE_INCLUDED_FILE
  26. #if ! JUCE_ONLY_BUILD_CORE_LIBRARY
  27. extern HWND juce_messageWindowHandle;
  28. #endif
  29. //==============================================================================
  30. CriticalSection::CriticalSection() throw()
  31. {
  32. // (just to check the MS haven't changed this structure and broken things...)
  33. #if _MSC_VER >= 1400
  34. static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (internal));
  35. #else
  36. static_jassert (sizeof (CRITICAL_SECTION) <= 24);
  37. #endif
  38. InitializeCriticalSection ((CRITICAL_SECTION*) internal);
  39. }
  40. CriticalSection::~CriticalSection() throw()
  41. {
  42. DeleteCriticalSection ((CRITICAL_SECTION*) internal);
  43. }
  44. void CriticalSection::enter() const throw()
  45. {
  46. EnterCriticalSection ((CRITICAL_SECTION*) internal);
  47. }
  48. bool CriticalSection::tryEnter() const throw()
  49. {
  50. return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE;
  51. }
  52. void CriticalSection::exit() const throw()
  53. {
  54. LeaveCriticalSection ((CRITICAL_SECTION*) internal);
  55. }
  56. //==============================================================================
  57. WaitableEvent::WaitableEvent() throw()
  58. : internal (CreateEvent (0, FALSE, FALSE, 0))
  59. {
  60. }
  61. WaitableEvent::~WaitableEvent() throw()
  62. {
  63. CloseHandle (internal);
  64. }
  65. bool WaitableEvent::wait (const int timeOutMillisecs) const throw()
  66. {
  67. return WaitForSingleObject (internal, timeOutMillisecs) == WAIT_OBJECT_0;
  68. }
  69. void WaitableEvent::signal() const throw()
  70. {
  71. SetEvent (internal);
  72. }
  73. void WaitableEvent::reset() const throw()
  74. {
  75. ResetEvent (internal);
  76. }
  77. //==============================================================================
  78. void JUCE_API juce_threadEntryPoint (void*);
  79. static unsigned int __stdcall threadEntryProc (void* userData) throw()
  80. {
  81. #if ! JUCE_ONLY_BUILD_CORE_LIBRARY
  82. AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0),
  83. GetCurrentThreadId(), TRUE);
  84. #endif
  85. juce_threadEntryPoint (userData);
  86. _endthreadex (0);
  87. return 0;
  88. }
  89. void juce_CloseThreadHandle (void* handle) throw()
  90. {
  91. CloseHandle ((HANDLE) handle);
  92. }
  93. void* juce_createThread (void* userData) throw()
  94. {
  95. unsigned int threadId;
  96. return (void*) _beginthreadex (0, 0,
  97. &threadEntryProc,
  98. userData,
  99. 0, &threadId);
  100. }
  101. void juce_killThread (void* handle) throw()
  102. {
  103. if (handle != 0)
  104. {
  105. #ifdef JUCE_DEBUG
  106. OutputDebugString (_T("** Warning - Forced thread termination **\n"));
  107. #endif
  108. TerminateThread (handle, 0);
  109. }
  110. }
  111. void juce_setCurrentThreadName (const String& name) throw()
  112. {
  113. #if defined (JUCE_DEBUG) && JUCE_MSVC
  114. struct
  115. {
  116. DWORD dwType;
  117. LPCSTR szName;
  118. DWORD dwThreadID;
  119. DWORD dwFlags;
  120. } info;
  121. info.dwType = 0x1000;
  122. info.szName = name;
  123. info.dwThreadID = GetCurrentThreadId();
  124. info.dwFlags = 0;
  125. #define MS_VC_EXCEPTION 0x406d1388
  126. __try
  127. {
  128. RaiseException (MS_VC_EXCEPTION, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
  129. }
  130. __except (EXCEPTION_CONTINUE_EXECUTION)
  131. {}
  132. #else
  133. (void) name;
  134. #endif
  135. }
  136. Thread::ThreadID Thread::getCurrentThreadId() throw()
  137. {
  138. return (ThreadID) (pointer_sized_int) GetCurrentThreadId();
  139. }
  140. // priority 1 to 10 where 5=normal, 1=low
  141. void juce_setThreadPriority (void* threadHandle, int priority) throw()
  142. {
  143. int pri = THREAD_PRIORITY_TIME_CRITICAL;
  144. if (priority < 1)
  145. pri = THREAD_PRIORITY_IDLE;
  146. else if (priority < 2)
  147. pri = THREAD_PRIORITY_LOWEST;
  148. else if (priority < 5)
  149. pri = THREAD_PRIORITY_BELOW_NORMAL;
  150. else if (priority < 7)
  151. pri = THREAD_PRIORITY_NORMAL;
  152. else if (priority < 9)
  153. pri = THREAD_PRIORITY_ABOVE_NORMAL;
  154. else if (priority < 10)
  155. pri = THREAD_PRIORITY_HIGHEST;
  156. if (threadHandle == 0)
  157. threadHandle = GetCurrentThread();
  158. SetThreadPriority (threadHandle, pri);
  159. }
  160. void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw()
  161. {
  162. SetThreadAffinityMask (GetCurrentThread(), affinityMask);
  163. }
  164. static HANDLE sleepEvent = 0;
  165. void juce_initialiseThreadEvents() throw()
  166. {
  167. if (sleepEvent == 0)
  168. #ifdef JUCE_DEBUG
  169. sleepEvent = CreateEvent (0, 0, 0, _T("Juce Sleep Event"));
  170. #else
  171. sleepEvent = CreateEvent (0, 0, 0, 0);
  172. #endif
  173. }
  174. void Thread::yield() throw()
  175. {
  176. Sleep (0);
  177. }
  178. void JUCE_CALLTYPE Thread::sleep (const int millisecs) throw()
  179. {
  180. if (millisecs >= 10)
  181. {
  182. Sleep (millisecs);
  183. }
  184. else
  185. {
  186. jassert (sleepEvent != 0);
  187. // unlike Sleep() this is guaranteed to return to the current thread after
  188. // the time expires, so we'll use this for short waits, which are more likely
  189. // to need to be accurate
  190. WaitForSingleObject (sleepEvent, millisecs);
  191. }
  192. }
  193. //==============================================================================
  194. static int lastProcessPriority = -1;
  195. // called by WindowDriver because Windows does wierd things to process priority
  196. // when you swap apps, and this forces an update when the app is brought to the front.
  197. void juce_repeatLastProcessPriority() throw()
  198. {
  199. if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..)
  200. {
  201. DWORD p;
  202. switch (lastProcessPriority)
  203. {
  204. case Process::LowPriority:
  205. p = IDLE_PRIORITY_CLASS;
  206. break;
  207. case Process::NormalPriority:
  208. p = NORMAL_PRIORITY_CLASS;
  209. break;
  210. case Process::HighPriority:
  211. p = HIGH_PRIORITY_CLASS;
  212. break;
  213. case Process::RealtimePriority:
  214. p = REALTIME_PRIORITY_CLASS;
  215. break;
  216. default:
  217. jassertfalse // bad priority value
  218. return;
  219. }
  220. SetPriorityClass (GetCurrentProcess(), p);
  221. }
  222. }
  223. void Process::setPriority (ProcessPriority prior)
  224. {
  225. if (lastProcessPriority != (int) prior)
  226. {
  227. lastProcessPriority = (int) prior;
  228. juce_repeatLastProcessPriority();
  229. }
  230. }
  231. bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger() throw()
  232. {
  233. return IsDebuggerPresent() != FALSE;
  234. }
  235. bool JUCE_CALLTYPE Process::isRunningUnderDebugger() throw()
  236. {
  237. return juce_isRunningUnderDebugger();
  238. }
  239. //==============================================================================
  240. void Process::raisePrivilege()
  241. {
  242. jassertfalse // xxx not implemented
  243. }
  244. void Process::lowerPrivilege()
  245. {
  246. jassertfalse // xxx not implemented
  247. }
  248. void Process::terminate()
  249. {
  250. #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS
  251. _CrtDumpMemoryLeaks();
  252. #endif
  253. // bullet in the head in case there's a problem shutting down..
  254. ExitProcess (0);
  255. }
  256. //==============================================================================
  257. void* PlatformUtilities::loadDynamicLibrary (const String& name)
  258. {
  259. void* result = 0;
  260. JUCE_TRY
  261. {
  262. result = (void*) LoadLibrary (name);
  263. }
  264. JUCE_CATCH_ALL
  265. return result;
  266. }
  267. void PlatformUtilities::freeDynamicLibrary (void* h)
  268. {
  269. JUCE_TRY
  270. {
  271. if (h != 0)
  272. FreeLibrary ((HMODULE) h);
  273. }
  274. JUCE_CATCH_ALL
  275. }
  276. void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name)
  277. {
  278. return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name)
  279. : 0;
  280. }
  281. //==============================================================================
  282. InterProcessLock::InterProcessLock (const String& name_) throw()
  283. : internal (0),
  284. name (name_),
  285. reentrancyLevel (0)
  286. {
  287. }
  288. InterProcessLock::~InterProcessLock() throw()
  289. {
  290. exit();
  291. }
  292. bool InterProcessLock::enter (const int timeOutMillisecs) throw()
  293. {
  294. if (reentrancyLevel++ == 0)
  295. {
  296. internal = CreateMutex (0, TRUE, name);
  297. if (internal != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
  298. {
  299. if (timeOutMillisecs == 0
  300. || WaitForSingleObject (internal, (timeOutMillisecs < 0) ? INFINITE : timeOutMillisecs)
  301. == WAIT_TIMEOUT)
  302. {
  303. ReleaseMutex (internal);
  304. CloseHandle (internal);
  305. internal = 0;
  306. }
  307. }
  308. }
  309. return (internal != 0);
  310. }
  311. void InterProcessLock::exit() throw()
  312. {
  313. if (--reentrancyLevel == 0 && internal != 0)
  314. {
  315. ReleaseMutex (internal);
  316. CloseHandle (internal);
  317. internal = 0;
  318. }
  319. }
  320. #endif