1#include "UserInteractions.h" 2#include <CoreFoundation/CoreFoundation.h> 3#include <CoreServices/CoreServices.h> 4#include <ApplicationServices/ApplicationServices.h> 5#include <AppKit/AppKit.h> 6 7#include <iostream> 8#include <sstream> 9#include <unistd.h> 10 11namespace Surge 12{ 13 14namespace UserInteractions 15{ 16 17void promptError(const std::string &message, const std::string &title, SurgeGUIEditor *guiEditor) 18{ 19 CFStringRef cfT = 20 CFStringCreateWithCString(kCFAllocatorDefault, title.c_str(), kCFStringEncodingUTF8); 21 CFStringRef cfM = 22 CFStringCreateWithCString(kCFAllocatorDefault, message.c_str(), kCFStringEncodingUTF8); 23 24 SInt32 nRes = 0; 25 CFUserNotificationRef pDlg = NULL; 26 const void *keys[] = {kCFUserNotificationAlertHeaderKey, kCFUserNotificationAlertMessageKey}; 27 const void *vals[] = {cfT, cfM}; 28 29 CFDictionaryRef dict = 30 CFDictionaryCreate(0, keys, vals, sizeof(keys) / sizeof(*keys), 31 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 32 33 pDlg = CFUserNotificationCreate(kCFAllocatorDefault, 0, kCFUserNotificationStopAlertLevel, 34 &nRes, dict); 35 36 CFRelease(cfT); 37 CFRelease(cfM); 38} 39 40void promptInfo(const std::string &message, const std::string &title, SurgeGUIEditor *guiEditor) 41{ 42 CFStringRef cfT = 43 CFStringCreateWithCString(kCFAllocatorDefault, title.c_str(), kCFStringEncodingUTF8); 44 CFStringRef cfM = 45 CFStringCreateWithCString(kCFAllocatorDefault, message.c_str(), kCFStringEncodingUTF8); 46 47 SInt32 nRes = 0; 48 CFUserNotificationRef pDlg = NULL; 49 const void *keys[] = {kCFUserNotificationAlertHeaderKey, kCFUserNotificationAlertMessageKey}; 50 const void *vals[] = {cfT, cfM}; 51 52 CFDictionaryRef dict = 53 CFDictionaryCreate(0, keys, vals, sizeof(keys) / sizeof(*keys), 54 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 55 56 pDlg = CFUserNotificationCreate(kCFAllocatorDefault, 0, kCFUserNotificationNoteAlertLevel, 57 &nRes, dict); 58 59 CFRelease(cfT); 60 CFRelease(cfM); 61} 62 63MessageResult promptOKCancel(const std::string &message, const std::string &title, 64 SurgeGUIEditor *guiEditor) 65{ 66 CFStringRef cfT = 67 CFStringCreateWithCString(kCFAllocatorDefault, title.c_str(), kCFStringEncodingUTF8); 68 CFStringRef cfM = 69 CFStringCreateWithCString(kCFAllocatorDefault, message.c_str(), kCFStringEncodingUTF8); 70 71 CFOptionFlags responseFlags; 72 CFUserNotificationDisplayAlert(0, kCFUserNotificationPlainAlertLevel, 0, 0, 0, cfT, cfM, 73 CFSTR("OK"), CFSTR("Cancel"), 0, &responseFlags); 74 75 CFRelease(cfT); 76 CFRelease(cfM); 77 78 if ((responseFlags & 0x3) != kCFUserNotificationDefaultResponse) 79 return UserInteractions::CANCEL; 80 return UserInteractions::OK; 81} 82 83void openURL(const std::string &url_str) 84{ 85 CFURLRef url = CFURLCreateWithBytes(NULL, // allocator 86 (UInt8 *)url_str.c_str(), // URLBytes 87 url_str.length(), // length 88 kCFStringEncodingASCII, // encoding 89 NULL // baseURL 90 ); 91 LSOpenCFURLRef(url, 0); 92 CFRelease(url); 93} 94 95void showHTML(const std::string &html) 96{ 97 // Why does mktemp crash on macos I wonder? 98 std::ostringstream fns; 99 fns << "/var/tmp/surge-data." << rand() << ".html"; 100 101 FILE *f = fopen(fns.str().c_str(), "w"); 102 if (f) 103 { 104 fprintf(f, "%s", html.c_str()); 105 fclose(f); 106 std::string url = std::string("file://") + fns.str(); 107 openURL(url); 108 } 109} 110 111void openFolderInFileBrowser(const std::string &folder) 112{ 113 std::string url = "file://" + folder; 114 UserInteractions::openURL(url); 115} 116 117void promptFileOpenDialog(const std::string &initialDirectory, const std::string &filterSuffix, 118 const std::string &filterDescription, 119 std::function<void(std::string)> callbackOnOpen, 120 bool canSelectDirectories, bool canCreateDirectories, 121 SurgeGUIEditor *guiEditor) 122{ 123 // FIXME TODO - support the filterSuffix and initialDirectory 124 NSOpenPanel *panel = [NSOpenPanel openPanel]; 125 [panel setCanChooseDirectories:canSelectDirectories]; 126 [panel setCanCreateDirectories:canCreateDirectories]; 127 [panel 128 setDirectoryURL:[NSURL 129 fileURLWithPath:[NSString 130 stringWithUTF8String:(initialDirectory.c_str())]]]; 131 132 // Logic and others have wierd window ordering which can mean this somethimes pops behind. 133 // See #1001. 134 [panel makeKeyAndOrderFront:panel]; 135 [panel setLevel:CGShieldingWindowLevel()]; 136 137 [panel beginWithCompletionHandler:^(NSInteger result) { 138 if (result == NSFileHandlingPanelOKButton) 139 { 140 NSURL *theDoc = [[panel URLs] objectAtIndex:0]; 141 NSString *path = [theDoc path]; 142 std::string pstring([path UTF8String]); 143 callbackOnOpen(pstring); 144 } 145 }]; 146} 147 148}; 149 150}; 151