16#include "IPlugAPP_host.h"
30#define STB_IMAGE_WRITE_IMPLEMENTATION
31#include "../../Dependencies/IGraphics/STB/stb_image_write.h"
33extern WDL_DLGRET MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
36extern HINSTANCE gHINSTANCE;
40bool SaveWindowScreenshot(HWND hwnd,
const char* path)
47 if (!GetClientRect(hwnd, &clientRect))
50 int width = clientRect.right - clientRect.left;
51 int height = clientRect.bottom - clientRect.top;
53 if (width <= 0 || height <= 0)
57 HDC hdcWindow = GetDC(hwnd);
61 HDC hdcMem = CreateCompatibleDC(hdcWindow);
64 ReleaseDC(hwnd, hdcWindow);
70 bmi.bmiHeader.biSize =
sizeof(BITMAPINFOHEADER);
71 bmi.bmiHeader.biWidth = width;
72 bmi.bmiHeader.biHeight = -height;
73 bmi.bmiHeader.biPlanes = 1;
74 bmi.bmiHeader.biBitCount = 32;
75 bmi.bmiHeader.biCompression = BI_RGB;
77 void* pBits =
nullptr;
78 HBITMAP hBitmap = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, &pBits,
nullptr, 0);
80 if (!hBitmap || !pBits)
83 ReleaseDC(hwnd, hdcWindow);
87 HGDIOBJ hOldBitmap = SelectObject(hdcMem, hBitmap);
92#ifndef PW_RENDERFULLCONTENT
93 #define PW_RENDERFULLCONTENT 0x00000002
95 BOOL captured = PrintWindow(hwnd, hdcMem, PW_CLIENTONLY | PW_RENDERFULLCONTENT);
100 captured = BitBlt(hdcMem, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY);
103 SelectObject(hdcMem, hOldBitmap);
105 ReleaseDC(hwnd, hdcWindow);
109 DeleteObject(hBitmap);
114 uint8_t* pixels =
static_cast<uint8_t*
>(pBits);
115 for (
int i = 0; i < width * height; i++)
118 uint8_t temp = pixels[i * 4 + 0];
119 pixels[i * 4 + 0] = pixels[i * 4 + 2];
120 pixels[i * 4 + 2] = temp;
122 pixels[i * 4 + 3] = 255;
126 int result = stbi_write_png(path, width, height, 4, pixels, width * 4);
128 DeleteObject(hBitmap);
133int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam,
int nShowCmd)
137#ifndef APP_ALLOW_MULTIPLE_INSTANCES
138 HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, BUNDLE_NAME);
141 hMutex = CreateMutex(0, 0, BUNDLE_NAME);
144 HWND hWnd = FindWindow(0, BUNDLE_NAME);
145 SetForegroundWindow(hWnd);
149 gHINSTANCE = hInstance;
151 InitCommonControls();
152 gScrollMessage = RegisterWindowMessage(
"MSWHEEL_ROLLMSG");
157 if (lpszCmdParam && lpszCmdParam[0])
159 char* args = _strdup(lpszCmdParam);
160 char* token = strtok(args,
" ");
163 if (strcmp(token,
"--screenshot") == 0)
165 token = strtok(
nullptr,
" ");
169 else if (strcmp(token,
"--no-io") == 0)
173 token = strtok(
nullptr,
" ");
183 pAppHost->TryToChangeAudio();
185 HACCEL hAccel = LoadAccelerators(gHINSTANCE, MAKEINTRESOURCE(IDR_ACCELERATOR1));
187 static UINT(WINAPI *__SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
189 if (!__SetProcessDpiAwarenessContext)
191 HINSTANCE h = LoadLibrary(
"user32.dll");
192 if (h) *(
void **)&__SetProcessDpiAwarenessContext = GetProcAddress(h,
"SetProcessDpiAwarenessContext");
193 if (!__SetProcessDpiAwarenessContext)
194 *(
void **)&__SetProcessDpiAwarenessContext = (
void*)(INT_PTR)1;
196 if ((UINT_PTR)__SetProcessDpiAwarenessContext > (UINT_PTR)1)
198 __SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
201 CreateDialog(gHINSTANCE, MAKEINTRESOURCE(IDD_DIALOG_MAIN), GetDesktopWindow(), IPlugAPPHost::MainDlgProc);
203#if !defined _DEBUG || defined NO_IGRAPHICS
204 HMENU menu = GetMenu(gHWND);
205 RemoveMenu(menu, 1, MF_BYPOSITION);
212 int vvv = GetMessage(&msg, NULL, 0, 0);
225 DispatchMessage(&msg);
229 if (gHWND && (TranslateAccelerator(gHWND, hAccel, &msg) || IsDialogMessage(gHWND, &msg)))
233 HWND hWndParent = NULL;
234 HWND temphwnd = msg.hwnd;
238 if (GetClassLong(temphwnd, GCW_ATOM) == (INT)32770)
240 hWndParent = temphwnd;
241 if (!(GetWindowLong(temphwnd, GWL_STYLE) & WS_CHILD))
245 while (temphwnd = GetParent(temphwnd));
247 if (hWndParent && IsDialogMessage(hWndParent,&msg))
250 TranslateMessage(&msg);
251 DispatchMessage(&msg);
256 DestroyWindow(gHWND);
258#ifndef APP_ALLOW_MULTIPLE_INSTANCES
259 ReleaseMutex(hMutex);
262 catch(std::exception e)
264 DBGMSG(
"Exception: %s", e.what());
271#import <Cocoa/Cocoa.h>
274#include "IPlugSWELL.h"
280typedef CGImageRef (*CGWindowListCreateImageFunc)(CGRect, uint32_t, uint32_t, uint32_t);
283extern "C" bool SaveWindowScreenshot(
void* hwnd,
const char* path)
288 NSView* view = (__bridge NSView*)hwnd;
289 NSWindow* window = [view window];
296 static CGWindowListCreateImageFunc pCGWindowListCreateImage =
nullptr;
297 if (!pCGWindowListCreateImage)
299 void* handle = dlopen(
"/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics", RTLD_LAZY);
301 pCGWindowListCreateImage = (CGWindowListCreateImageFunc)dlsym(handle,
"CGWindowListCreateImage");
304 if (!pCGWindowListCreateImage)
308 CGWindowID windowID = (CGWindowID)[window windowNumber];
311 CGImageRef cgImage = pCGWindowListCreateImage(
313 kCGWindowListOptionIncludingWindow,
315 kCGWindowImageBoundsIgnoreFraming
322 NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
323 CGImageRelease(cgImage);
328 NSData* pngData = [bitmap representationUsingType:NSBitmapImageFileTypePNG properties:@{}];
332 NSString* filePath = [NSString stringWithUTF8String:path];
333 return [pngData writeToFile:filePath atomically:YES];
335extern HMENU SWELL_app_stocksysmenu;
337static WDL_String gScreenshotPath;
338static bool gNoIO =
false;
340int main(
int argc,
char *argv[])
344 if (argc > 2 && std::string_view(argv[2]) ==
"registerauv3")
346 WDL_String appexPath;
347 appexPath.SetFormatted(1024,
"pluginkit -a %s%s%s.appex", argv[0],
"/../../Plugins/", appexPath.get_filepart());
348 if (system(appexPath.Get()) > -1)
349 NSLog(
@"Registered audiounit app extension\n");
351 NSLog(
@"Failed to register audiounit app extension\n");
356 for (
int i = 1; i < argc; i++)
358 if (strcmp(argv[i],
"--screenshot") == 0 && i + 1 < argc)
360 gScreenshotPath.Set(argv[i + 1]);
363 else if (strcmp(argv[i],
"--no-io") == 0)
369 if (AppIsSandboxed())
370 DBGMSG(
"App is sandboxed, file system access etc restricted!\n");
372 return NSApplicationMain(argc, (
const char**) argv);
375INT_PTR SWELLAppMain(
int msg, INT_PTR parm1, INT_PTR parm2)
381 case SWELLAPP_ONLOAD:
383 pAppHost = IPlugAPPHost::Create();
386 if (gScreenshotPath.GetLength() > 0)
397 pAppHost->TryToChangeAudio();
400 case SWELLAPP_LOADED:
402 pAppHost = IPlugAPPHost::sInstance.get();
404 HMENU menu = SWELL_GetCurrentMenu();
409 menu = SWELL_DuplicateMenu(menu);
410 HMENU src = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));
412 for (
int x = 0; x < GetMenuItemCount(src)-1; x++)
414 HMENU sm = GetSubMenu(src,x);
419 MENUITEMINFO mii = {
sizeof(mii), MIIM_TYPE};
420 mii.dwTypeData = str;
421 mii.cch =
sizeof(str);
423 GetMenuItemInfo(src, x, TRUE, &mii);
424 MENUITEMINFO mi= {
sizeof(mi), MIIM_STATE|MIIM_SUBMENU|MIIM_TYPE,MFT_STRING, 0, 0, SWELL_DuplicateMenu(sm), NULL, NULL, 0, str};
425 InsertMenuItem(menu, x+1, TRUE, &mi);
432 HMENU sm = GetSubMenu(menu, 1);
433 DeleteMenu(sm, ID_QUIT, MF_BYCOMMAND);
434 DeleteMenu(sm, ID_PREFERENCES, MF_BYCOMMAND);
437 int a = GetMenuItemCount(sm);
439 while (a > 0 && GetMenuItemID(sm, a-1) == 0)
440 DeleteMenu(sm, --a, MF_BYPOSITION);
442 DeleteMenu(menu, 1, MF_BYPOSITION);
445 SetMenuItemModifier(menu, ID_SCREENSHOT, MF_BYCOMMAND,
'S', FCONTROL | FSHIFT);
447#if !defined _DEBUG || defined NO_IGRAPHICS
450 HMENU sm = GetSubMenu(menu, 1);
451 DeleteMenu(sm, ID_LIVE_EDIT, MF_BYCOMMAND);
452 DeleteMenu(sm, ID_SHOW_BOUNDS, MF_BYCOMMAND);
453 DeleteMenu(sm, ID_SHOW_DRAWN, MF_BYCOMMAND);
454 DeleteMenu(sm, ID_SHOW_FPS, MF_BYCOMMAND);
457 int a = GetMenuItemCount(sm);
459 while (a > 0 && GetMenuItemID(sm, a-1) == 0)
460 DeleteMenu(sm, --a, MF_BYPOSITION);
463 if (GetMenuItemCount(sm) == 0)
464 DeleteMenu(menu, 1, MF_BYPOSITION);
467 SetMenuItemModifier(menu, ID_LIVE_EDIT, MF_BYCOMMAND,
'E', FCONTROL);
468 SetMenuItemModifier(menu, ID_SHOW_DRAWN, MF_BYCOMMAND,
'D', FCONTROL);
469 SetMenuItemModifier(menu, ID_SHOW_BOUNDS, MF_BYCOMMAND,
'B', FCONTROL);
470 SetMenuItemModifier(menu, ID_SHOW_FPS, MF_BYCOMMAND,
'F', FCONTROL);
473 HWND hwnd = CreateDialog(gHINST, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, IPlugAPPHost::MainDlgProc);
478 SWELL_SetDefaultModalWindowMenu(menu);
483 case SWELLAPP_ONCOMMAND:
485 if (gHWND && (parm1&0xffff))
486 SendMessage(gHWND, WM_COMMAND, parm1 & 0xffff, 0);
488 case SWELLAPP_DESTROY:
490 DestroyWindow(gHWND);
492 case SWELLAPP_PROCESSMESSAGE:
493 MSG* pMSG = (MSG*) parm1;
494 NSView* pContentView = (NSView*) pMSG->hwnd;
495 NSEvent* pEvent = (NSEvent*) parm2;
496 int etype = (int) [pEvent type];
498 bool textField = [pContentView isKindOfClass:[NSText
class]];
500 if (!textField && etype == NSKeyDown)
502 int flag, code = SWELL_MacKeyToWindowsKey(pEvent, &flag);
504 if (!(flag&~FVIRTKEY) && (code == VK_RETURN || code == VK_ESCAPE))
506 [pContentView keyDown: pEvent];
515#define CBS_HASSTRINGS 0
516#define SWELL_DLG_SCALE_AUTOGEN 1
517#define SET_IDD_DIALOG_PREF_SCALE 1.5
519#define SWELL_DLG_FLAGS_AUTOGEN SWELL_DLG_WS_FLIPPED|SWELL_DLG_WS_RESIZABLE
521#include "swell-dlggen.h"
522#include "resources/main.rc_mac_dlg"
523#include "swell-menugen.h"
524#include "resources/main.rc_mac_menu"
527#elif defined(OS_LINUX)
Common paths useful for plug-ins.
A class that hosts an IPlug as a standalone app and provides Audio/Midi I/O.
void SetScreenshotPath(const char *path)
Set screenshot path for CLI screenshot mode.
void SetNoIO(bool noIO)
Set no-I/O mode (disables audio and MIDI initialization)
bool IsScreenshotMode() const
Check if in screenshot mode.