Audio plugin host https://kx.studio/carla
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.

373 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. extern bool isIOSAppActive;
  18. struct AppInactivityCallback // NB: careful, this declaration is duplicated in other modules
  19. {
  20. virtual ~AppInactivityCallback() {}
  21. virtual void appBecomingInactive() = 0;
  22. };
  23. // This is an internal list of callbacks (but currently used between modules)
  24. Array<AppInactivityCallback*> appBecomingInactiveCallbacks;
  25. } // (juce namespace)
  26. @interface JuceAppStartupDelegate : NSObject <UIApplicationDelegate>
  27. {
  28. }
  29. - (void) applicationDidFinishLaunching: (UIApplication*) application;
  30. - (void) applicationWillTerminate: (UIApplication*) application;
  31. - (void) applicationDidEnterBackground: (UIApplication*) application;
  32. - (void) applicationWillEnterForeground: (UIApplication*) application;
  33. - (void) applicationDidBecomeActive: (UIApplication*) application;
  34. - (void) applicationWillResignActive: (UIApplication*) application;
  35. @end
  36. @implementation JuceAppStartupDelegate
  37. - (void) applicationDidFinishLaunching: (UIApplication*) application
  38. {
  39. ignoreUnused (application);
  40. initialiseJuce_GUI();
  41. if (JUCEApplicationBase* app = JUCEApplicationBase::createInstance())
  42. {
  43. if (! app->initialiseApp())
  44. exit (app->shutdownApp());
  45. }
  46. else
  47. {
  48. jassertfalse; // you must supply an application object for an iOS app!
  49. }
  50. }
  51. - (void) applicationWillTerminate: (UIApplication*) application
  52. {
  53. ignoreUnused (application);
  54. JUCEApplicationBase::appWillTerminateByForce();
  55. }
  56. - (void) applicationDidEnterBackground: (UIApplication*) application
  57. {
  58. ignoreUnused (application);
  59. if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
  60. app->suspended();
  61. }
  62. - (void) applicationWillEnterForeground: (UIApplication*) application
  63. {
  64. ignoreUnused (application);
  65. if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
  66. app->resumed();
  67. }
  68. - (void) applicationDidBecomeActive: (UIApplication*) application
  69. {
  70. ignoreUnused (application);
  71. isIOSAppActive = true;
  72. }
  73. - (void) applicationWillResignActive: (UIApplication*) application
  74. {
  75. ignoreUnused (application);
  76. isIOSAppActive = false;
  77. for (int i = appBecomingInactiveCallbacks.size(); --i >= 0;)
  78. appBecomingInactiveCallbacks.getReference(i)->appBecomingInactive();
  79. }
  80. @end
  81. namespace juce
  82. {
  83. int juce_iOSMain (int argc, const char* argv[]);
  84. int juce_iOSMain (int argc, const char* argv[])
  85. {
  86. return UIApplicationMain (argc, const_cast<char**> (argv), nil, @"JuceAppStartupDelegate");
  87. }
  88. //==============================================================================
  89. void LookAndFeel::playAlertSound()
  90. {
  91. //xxx
  92. //AudioServicesPlaySystemSound ();
  93. }
  94. //==============================================================================
  95. class iOSMessageBox;
  96. } // (juce namespace)
  97. @interface JuceAlertBoxDelegate : NSObject <UIAlertViewDelegate>
  98. {
  99. @public
  100. iOSMessageBox* owner;
  101. }
  102. - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex;
  103. @end
  104. namespace juce
  105. {
  106. class iOSMessageBox
  107. {
  108. public:
  109. iOSMessageBox (const String& title, const String& message,
  110. NSString* button1, NSString* button2, NSString* button3,
  111. ModalComponentManager::Callback* cb, const bool async)
  112. : result (0), resultReceived (false), delegate (nil), alert (nil),
  113. callback (cb), isYesNo (button3 != nil), isAsync (async)
  114. {
  115. delegate = [[JuceAlertBoxDelegate alloc] init];
  116. delegate->owner = this;
  117. alert = [[UIAlertView alloc] initWithTitle: juceStringToNS (title)
  118. message: juceStringToNS (message)
  119. delegate: delegate
  120. cancelButtonTitle: button1
  121. otherButtonTitles: button2, button3, nil];
  122. [alert retain];
  123. [alert show];
  124. }
  125. ~iOSMessageBox()
  126. {
  127. [alert release];
  128. [delegate release];
  129. }
  130. int getResult()
  131. {
  132. jassert (callback == nullptr);
  133. JUCE_AUTORELEASEPOOL
  134. {
  135. while (! (alert.hidden || resultReceived))
  136. [[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
  137. }
  138. return result;
  139. }
  140. void buttonClicked (const int buttonIndex) noexcept
  141. {
  142. result = buttonIndex;
  143. resultReceived = true;
  144. if (callback != nullptr)
  145. callback->modalStateFinished (result);
  146. if (isAsync)
  147. delete this;
  148. }
  149. private:
  150. int result;
  151. bool resultReceived;
  152. JuceAlertBoxDelegate* delegate;
  153. UIAlertView* alert;
  154. ScopedPointer<ModalComponentManager::Callback> callback;
  155. const bool isYesNo, isAsync;
  156. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (iOSMessageBox)
  157. };
  158. } // (juce namespace)
  159. @implementation JuceAlertBoxDelegate
  160. - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex
  161. {
  162. owner->buttonClicked ((int) buttonIndex);
  163. alertView.hidden = true;
  164. }
  165. @end
  166. namespace juce
  167. {
  168. //==============================================================================
  169. #if JUCE_MODAL_LOOPS_PERMITTED
  170. void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType /*iconType*/,
  171. const String& title, const String& message,
  172. Component* /*associatedComponent*/)
  173. {
  174. JUCE_AUTORELEASEPOOL
  175. {
  176. iOSMessageBox mb (title, message, @"OK", nil, nil, nullptr, false);
  177. ignoreUnused (mb.getResult());
  178. }
  179. }
  180. #endif
  181. void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType /*iconType*/,
  182. const String& title, const String& message,
  183. Component* /*associatedComponent*/,
  184. ModalComponentManager::Callback* callback)
  185. {
  186. new iOSMessageBox (title, message, @"OK", nil, nil, callback, true);
  187. }
  188. bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType /*iconType*/,
  189. const String& title, const String& message,
  190. Component* /*associatedComponent*/,
  191. ModalComponentManager::Callback* callback)
  192. {
  193. ScopedPointer<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"OK",
  194. nil, callback, callback != nullptr));
  195. if (callback == nullptr)
  196. return mb->getResult() == 1;
  197. mb.release();
  198. return false;
  199. }
  200. int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType /*iconType*/,
  201. const String& title, const String& message,
  202. Component* /*associatedComponent*/,
  203. ModalComponentManager::Callback* callback)
  204. {
  205. ScopedPointer<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"Yes", @"No", callback, callback != nullptr));
  206. if (callback == nullptr)
  207. return mb->getResult();
  208. mb.release();
  209. return 0;
  210. }
  211. //==============================================================================
  212. bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray&, bool)
  213. {
  214. jassertfalse; // no such thing on iOS!
  215. return false;
  216. }
  217. bool DragAndDropContainer::performExternalDragDropOfText (const String&)
  218. {
  219. jassertfalse; // no such thing on iOS!
  220. return false;
  221. }
  222. //==============================================================================
  223. void Desktop::setScreenSaverEnabled (const bool isEnabled)
  224. {
  225. [[UIApplication sharedApplication] setIdleTimerDisabled: ! isEnabled];
  226. }
  227. bool Desktop::isScreenSaverEnabled()
  228. {
  229. return ! [[UIApplication sharedApplication] isIdleTimerDisabled];
  230. }
  231. //==============================================================================
  232. bool juce_areThereAnyAlwaysOnTopWindows()
  233. {
  234. return false;
  235. }
  236. //==============================================================================
  237. Image juce_createIconForFile (const File&)
  238. {
  239. return Image::null;
  240. }
  241. //==============================================================================
  242. void SystemClipboard::copyTextToClipboard (const String& text)
  243. {
  244. [[UIPasteboard generalPasteboard] setValue: juceStringToNS (text)
  245. forPasteboardType: @"public.text"];
  246. }
  247. String SystemClipboard::getTextFromClipboard()
  248. {
  249. if (NSString* text = [[UIPasteboard generalPasteboard] valueForPasteboardType: @"public.text"])
  250. return nsStringToJuce (text);
  251. return String();
  252. }
  253. //==============================================================================
  254. bool MouseInputSource::SourceList::addSource()
  255. {
  256. addSource (sources.size(), false);
  257. return true;
  258. }
  259. bool Desktop::canUseSemiTransparentWindows() noexcept
  260. {
  261. return true;
  262. }
  263. Point<float> MouseInputSource::getCurrentRawMousePosition()
  264. {
  265. return juce_lastMousePos;
  266. }
  267. void MouseInputSource::setRawMousePosition (Point<float>)
  268. {
  269. }
  270. double Desktop::getDefaultMasterScale()
  271. {
  272. return 1.0;
  273. }
  274. Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
  275. {
  276. return Orientations::convertToJuce ([[UIApplication sharedApplication] statusBarOrientation]);
  277. }
  278. void Desktop::Displays::findDisplays (float masterScale)
  279. {
  280. JUCE_AUTORELEASEPOOL
  281. {
  282. UIScreen* s = [UIScreen mainScreen];
  283. Display d;
  284. d.userArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s bounds])) / masterScale;
  285. d.totalArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s bounds])) / masterScale;
  286. d.isMain = true;
  287. d.scale = masterScale;
  288. if ([s respondsToSelector: @selector (scale)])
  289. d.scale *= s.scale;
  290. d.dpi = 160 * d.scale;
  291. displays.add (d);
  292. }
  293. }