iPlug2 - C++ Audio Plug-in Framework
IPlugAPP_main.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5 
6  See LICENSE.txt for more info.
7 
8  ==============================================================================
9 */
10 
11 #include "wdltypes.h"
12 #include "wdlstring.h"
13 
14 #include "IPlugPlatform.h"
15 #include "IPlugAPP_host.h"
16 
17 #include "config.h"
18 #include "resource.h"
19 
20 using namespace iplug;
21 
22 #pragma mark - WINDOWS
23 #if defined OS_WIN
24 #include <windows.h>
25 #include <commctrl.h>
26 
27 extern WDL_DLGRET MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
28 
29 HWND gHWND;
30 extern HINSTANCE gHINSTANCE;
31 UINT gScrollMessage;
32 
33 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nShowCmd)
34 {
35  try
36  {
37 #ifndef APP_ALLOW_MULTIPLE_INSTANCES
38  HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, BUNDLE_NAME); // BUNDLE_NAME used because it won't have spaces in it
39 
40  if (!hMutex)
41  hMutex = CreateMutex(0, 0, BUNDLE_NAME);
42  else
43  {
44  HWND hWnd = FindWindow(0, BUNDLE_NAME);
45  SetForegroundWindow(hWnd);
46  return 0; // should return 1?
47  }
48 #endif
49  gHINSTANCE = hInstance;
50 
51  InitCommonControls();
52  gScrollMessage = RegisterWindowMessage("MSWHEEL_ROLLMSG");
53 
54  IPlugAPPHost* pAppHost = IPlugAPPHost::Create();
55  pAppHost->Init();
56  pAppHost->TryToChangeAudio();
57 
58  HACCEL hAccel = LoadAccelerators(gHINSTANCE, MAKEINTRESOURCE(IDR_ACCELERATOR1));
59 
60  static UINT(WINAPI *__SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
61 
62  double scale = 1.;
63 
64  if (!__SetProcessDpiAwarenessContext)
65  {
66  HINSTANCE h = LoadLibrary("user32.dll");
67  if (h) *(void **)&__SetProcessDpiAwarenessContext = GetProcAddress(h, "SetProcessDpiAwarenessContext");
68  if (!__SetProcessDpiAwarenessContext)
69  *(void **)&__SetProcessDpiAwarenessContext = (void*)(INT_PTR)1;
70  }
71  if ((UINT_PTR)__SetProcessDpiAwarenessContext > (UINT_PTR)1)
72  {
73  __SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
74  }
75 
76  CreateDialog(gHINSTANCE, MAKEINTRESOURCE(IDD_DIALOG_MAIN), GetDesktopWindow(), IPlugAPPHost::MainDlgProc);
77 
78 #ifndef _DEBUG
79  HMENU menu = GetMenu(gHWND);
80  RemoveMenu(menu, 1, MF_BYPOSITION);
81  DrawMenuBar(gHWND);
82 #endif
83 
84  for(;;)
85  {
86  MSG msg= {0,};
87  int vvv = GetMessage(&msg, NULL, 0, 0);
88 
89  if (!vvv)
90  break;
91 
92  if (vvv < 0)
93  {
94  Sleep(10);
95  continue;
96  }
97 
98  if (!msg.hwnd)
99  {
100  DispatchMessage(&msg);
101  continue;
102  }
103 
104  if (gHWND && (TranslateAccelerator(gHWND, hAccel, &msg) || IsDialogMessage(gHWND, &msg)))
105  continue;
106 
107  // default processing for other dialogs
108  HWND hWndParent = NULL;
109  HWND temphwnd = msg.hwnd;
110 
111  do
112  {
113  if (GetClassLong(temphwnd, GCW_ATOM) == (INT)32770)
114  {
115  hWndParent = temphwnd;
116  if (!(GetWindowLong(temphwnd, GWL_STYLE) & WS_CHILD))
117  break; // not a child, exit
118  }
119  }
120  while (temphwnd = GetParent(temphwnd));
121 
122  if (hWndParent && IsDialogMessage(hWndParent,&msg))
123  continue;
124 
125  TranslateMessage(&msg);
126  DispatchMessage(&msg);
127  }
128 
129  // in case gHWND didnt get destroyed -- this corresponds to SWELLAPP_DESTROY roughly
130  if (gHWND)
131  DestroyWindow(gHWND);
132 
133 #ifndef APP_ALLOW_MULTIPLE_INSTANCES
134  ReleaseMutex(hMutex);
135 #endif
136  }
137  catch(...)
138  {
139  DBGMSG("another instance running\n");
140  }
141  return 0;
142 }
143 #pragma mark - MAC
144 #elif defined(OS_MAC)
145 #import <Cocoa/Cocoa.h>
146 #include "IPlugSWELL.h"
147 #include "IPlugPaths.h"
148 
149 HWND gHWND;
150 extern HMENU SWELL_app_stocksysmenu;
151 
152 int main(int argc, char *argv[])
153 {
154 #if APP_COPY_AUV3
155  //if invoked with an argument registerauv3 use plug-in kit to explicitly register auv3 app extension (doesn't happen from debugger)
156  if(strcmp(argv[2], "registerauv3"))
157  {
158  WDL_String appexPath(argv[0]);
159  appexPath.SetFormatted(1024, "pluginkit -a %s%s%s.appex", argv[0], "/../../Plugins/", appexPath.get_filepart());
160  if(system(appexPath.Get()) > -1)
161  NSLog(@"Registered audiounit app extension\n");
162  else
163  NSLog(@"Failed to register audiounit app extension\n");
164  }
165 #endif
166 
167  if(AppIsSandboxed())
168  DBGMSG("App is sandboxed, file system access etc restricted!\n");
169 
170  return NSApplicationMain(argc, (const char **) argv);
171 }
172 
173 INT_PTR SWELLAppMain(int msg, INT_PTR parm1, INT_PTR parm2)
174 {
175  IPlugAPPHost* pAppHost = nullptr;
176 
177  switch (msg)
178  {
179  case SWELLAPP_ONLOAD:
180  pAppHost = IPlugAPPHost::Create();
181  pAppHost->Init();
182  pAppHost->TryToChangeAudio();
183  break;
184  case SWELLAPP_LOADED:
185  {
186  pAppHost = IPlugAPPHost::sInstance.get();
187 
188  HMENU menu = SWELL_GetCurrentMenu();
189 
190  if (menu)
191  {
192  // work on a new menu
193  menu = SWELL_DuplicateMenu(menu);
194  HMENU src = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));
195 
196  for (int x = 0; x < GetMenuItemCount(src)-1; x++)
197  {
198  HMENU sm = GetSubMenu(src,x);
199 
200  if (sm)
201  {
202  char str[1024];
203  MENUITEMINFO mii = {sizeof(mii), MIIM_TYPE};
204  mii.dwTypeData = str;
205  mii.cch = sizeof(str);
206  str[0] = 0;
207  GetMenuItemInfo(src, x, TRUE, &mii);
208  MENUITEMINFO mi= {sizeof(mi), MIIM_STATE|MIIM_SUBMENU|MIIM_TYPE,MFT_STRING, 0, 0, SWELL_DuplicateMenu(sm), NULL, NULL, 0, str};
209  InsertMenuItem(menu, x+1, TRUE, &mi);
210  }
211  }
212  }
213 
214  if (menu)
215  {
216  HMENU sm = GetSubMenu(menu, 1);
217  DeleteMenu(sm, ID_QUIT, MF_BYCOMMAND); // remove QUIT from our file menu, since it is in the system menu on OSX
218  DeleteMenu(sm, ID_PREFERENCES, MF_BYCOMMAND); // remove PREFERENCES from the file menu, since it is in the system menu on OSX
219 
220  // remove any trailing separators
221  int a = GetMenuItemCount(sm);
222 
223  while (a > 0 && GetMenuItemID(sm, a-1) == 0)
224  DeleteMenu(sm, --a, MF_BYPOSITION);
225 
226  DeleteMenu(menu, 1, MF_BYPOSITION); // delete file menu
227  }
228 #ifndef _DEBUG
229  if (menu)
230  {
231  HMENU sm = GetSubMenu(menu, 1);
232  DeleteMenu(sm, ID_LIVE_EDIT, MF_BYCOMMAND);
233  DeleteMenu(sm, ID_SHOW_DRAWN, MF_BYCOMMAND);
234  DeleteMenu(sm, ID_SHOW_FPS, MF_BYCOMMAND);
235 
236  // remove any trailing separators
237  int a = GetMenuItemCount(sm);
238 
239  while (a > 0 && GetMenuItemID(sm, a-1) == 0)
240  DeleteMenu(sm, --a, MF_BYPOSITION);
241 
242  DeleteMenu(menu, 1, MF_BYPOSITION); // delete debug menu
243  }
244 #else
245  SetMenuItemModifier(menu, ID_LIVE_EDIT, MF_BYCOMMAND, 'E', FCONTROL);
246  SetMenuItemModifier(menu, ID_SHOW_DRAWN, MF_BYCOMMAND, 'D', FCONTROL);
247  SetMenuItemModifier(menu, ID_SHOW_BOUNDS, MF_BYCOMMAND, 'B', FCONTROL);
248  SetMenuItemModifier(menu, ID_SHOW_FPS, MF_BYCOMMAND, 'F', FCONTROL);
249 #endif
250 
251  HWND hwnd = CreateDialog(gHINST, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, IPlugAPPHost::MainDlgProc);
252 
253  if (menu)
254  {
255  SetMenu(hwnd, menu); // set the menu for the dialog to our menu (on Windows that menu is set from the .rc, but on SWELL
256  SWELL_SetDefaultModalWindowMenu(menu); // other windows will get the stock (bundle) menus
257  }
258 
259  break;
260  }
261  case SWELLAPP_ONCOMMAND:
262  // this is to catch commands coming from the system menu etc
263  if (gHWND && (parm1&0xffff))
264  SendMessage(gHWND, WM_COMMAND, parm1 & 0xffff, 0);
265  break;
266  case SWELLAPP_DESTROY:
267  if (gHWND)
268  DestroyWindow(gHWND);
269  break;
270  case SWELLAPP_PROCESSMESSAGE:
271  MSG* pMSG = (MSG*) parm1;
272  NSView* pContentView = (NSView*) pMSG->hwnd;
273  NSEvent* pEvent = (NSEvent*) parm2;
274  int etype = (int) [pEvent type];
275 
276  bool textField = [pContentView isKindOfClass:[NSText class]];
277 
278  if (!textField && etype == NSKeyDown)
279  {
280  int flag, code = SWELL_MacKeyToWindowsKey(pEvent, &flag);
281 
282  if (!(flag&~FVIRTKEY) && (code == VK_RETURN || code == VK_ESCAPE))
283  {
284  [pContentView keyDown: pEvent];
285  return 1;
286  }
287  }
288  break;
289  }
290  return 0;
291 }
292 
293 #define CBS_HASSTRINGS 0
294 #define SWELL_DLG_SCALE_AUTOGEN 1
295 #define SET_IDD_DIALOG_PREF_SCALE 1.5
296 #if PLUG_HOST_RESIZE
297 #define SWELL_DLG_FLAGS_AUTOGEN SWELL_DLG_WS_FLIPPED|SWELL_DLG_WS_RESIZABLE
298 #endif
299 #include "swell-dlggen.h"
300 #include "resources/main.rc_mac_dlg"
301 #include "swell-menugen.h"
302 #include "resources/main.rc_mac_menu"
303 
304 #pragma mark - LINUX
305 #elif defined(OS_LINUX)
306 //#include <IPlugSWELL.h>
307 //#include "swell-internal.h" // fixes problem with HWND forward decl
308 //
309 //HWND gHWND;
310 //UINT gScrollMessage;
311 //extern HMENU SWELL_app_stocksysmenu;
312 //
313 //int main(int argc, char **argv)
314 //{
315 // SWELL_initargs(&argc, &argv);
316 // SWELL_Internal_PostMessage_Init();
317 // SWELL_ExtendedAPI("APPNAME", (void*) "IGraphics Test");
318 //
319 // HMENU menu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));
320 // CreateDialog(gHINSTANCE, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, MainDlgProc);
321 // SetMenu(gHWND, menu);
322 //
323 // while (!gHWND->m_hashaddestroy)
324 // {
325 // SWELL_RunMessageLoop();
326 // Sleep(10);
327 // };
328 //
329 // if (gHWND)
330 // DestroyWindow(gHWND);
331 //
332 // return 0;
333 //}
334 //
335 //INT_PTR SWELLAppMain(int msg, INT_PTR parm1, INT_PTR parm2)
336 //{
337 // switch (msg)
338 // {
339 // case SWELLAPP_ONLOAD:
340 // break;
341 // case SWELLAPP_LOADED:
342 // {
343 // HMENU menu = SWELL_GetCurrentMenu();
344 //
345 // if (menu)
346 // {
347 // // work on a new menu
348 // menu = SWELL_DuplicateMenu(menu);
349 // HMENU src = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));
350 //
351 // for (auto x = 0; x < GetMenuItemCount(src)-1; x++)
352 // {
353 // HMENU sm = GetSubMenu(src,x);
354 // if (sm)
355 // {
356 // char str[1024];
357 // MENUITEMINFO mii = {sizeof(mii), MIIM_TYPE};
358 // mii.dwTypeData = str;
359 // mii.cch = sizeof(str);
360 // str[0] = 0;
361 // GetMenuItemInfo(src, x, TRUE, &mii);
362 // MENUITEMINFO mi= {sizeof(mi), MIIM_STATE|MIIM_SUBMENU|MIIM_TYPE,MFT_STRING, 0, 0, SWELL_DuplicateMenu(sm), NULL, NULL, 0, str};
363 // InsertMenuItem(menu, x+1, TRUE, &mi);
364 // }
365 // }
366 // }
367 //
368 // if (menu)
369 // {
370 // HMENU sm = GetSubMenu(menu, 1);
371 // DeleteMenu(sm, ID_QUIT, MF_BYCOMMAND); // remove QUIT from our file menu, since it is in the system menu on OSX
372 // DeleteMenu(sm, ID_PREFERENCES, MF_BYCOMMAND); // remove PREFERENCES from the file menu, since it is in the system menu on OSX
373 //
374 // // remove any trailing separators
375 // int a = GetMenuItemCount(sm);
376 //
377 // while (a > 0 && GetMenuItemID(sm, a-1) == 0)
378 // DeleteMenu(sm, --a, MF_BYPOSITION);
379 //
380 // DeleteMenu(menu, 1, MF_BYPOSITION); // delete file menu
381 // }
382 //
383 // // if we want to set any default modifiers for items in the menus, we can use:
384 // // SetMenuItemModifier(menu,commandID,MF_BYCOMMAND,'A',FCONTROL) etc.
385 //
386 // HWND hwnd = CreateDialog(gHINST,MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, MainDlgProc);
387 //
388 // if (menu)
389 // {
390 // SetMenu(hwnd, menu); // set the menu for the dialog to our menu (on Windows that menu is set from the .rc, but on SWELL
391 // SWELL_SetDefaultModalWindowMenu(menu); // other windows will get the stock (bundle) menus
392 // }
393 //
394 // break;
395 // }
396 // case SWELLAPP_ONCOMMAND:
397 // // this is to catch commands coming from the system menu etc
398 // if (gHWND && (parm1&0xffff))
399 // SendMessage(gHWND, WM_COMMAND, parm1 & 0xffff, 0);
400 // break;
401 // case SWELLAPP_DESTROY:
402 // if (gHWND)
403 // DestroyWindow(gHWND);
404 // break;
405 // case SWELLAPP_PROCESSMESSAGE: // can hook keyboard input here
406 // // parm1 = (MSG*), should we want it -- look in swell.h to see what the return values refer to
407 // break;
408 // }
409 // return 0;
410 //}
411 //
412 //#define CBS_HASSTRINGS 0
413 //#define SWELL_DLG_SCALE_AUTOGEN 1
414 //#define SET_IDD_DIALOG_PREF_SCALE 1.5
415 //#include "swell-dlggen.h"
416 //#include "resources/main.rc_mac_dlg"
417 //#include "swell-menugen.h"
418 //#include "resources/main.rc_mac_menu"
419 #endif
bool AppIsSandboxed()
Include to get consistently named preprocessor macros for different platforms and logging functionali...
Common paths useful for plug-ins.
A class that hosts an IPlug as a standalone app and provides Audio/Midi I/O.
Definition: IPlugAPP_host.h:81