summaryrefslogtreecommitdiff
path: root/vstgui.sf/vstgui/cfileselector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vstgui.sf/vstgui/cfileselector.cpp')
-rw-r--r--vstgui.sf/vstgui/cfileselector.cpp1156
1 files changed, 1156 insertions, 0 deletions
diff --git a/vstgui.sf/vstgui/cfileselector.cpp b/vstgui.sf/vstgui/cfileselector.cpp
new file mode 100644
index 0000000..0a715ea
--- /dev/null
+++ b/vstgui.sf/vstgui/cfileselector.cpp
@@ -0,0 +1,1156 @@
+//-----------------------------------------------------------------------------
+// VST Plug-Ins SDK
+// VSTGUI: Graphical User Interface Framework for VST plugins :
+//
+// Version 3.0 $Date: 2006/01/31 10:03:38 $
+//
+//-----------------------------------------------------------------------------
+// VSTGUI LICENSE
+// © 2004, Steinberg Media Technologies, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#if !PLUGGUI
+#include "AudioEffectX.h"
+#endif
+
+#ifndef __cfileselector__
+#include "cfileselector.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// CFileSelector Implementation
+//-----------------------------------------------------------------------------
+#define stringAnyType "Any Type (*.*)"
+#define stringAllTypes "All Types: ("
+#define stringSelect "Select"
+#define stringCancel "Cancel"
+#define stringLookIn "Look in"
+#define kPathMax 1024
+
+#if WINDOWS
+#include <stdio.h>
+
+static UINT_PTR APIENTRY SelectDirectoryHook (HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK SelectDirectoryButtonProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+WNDPROC fpOldSelectDirectoryButtonProc;
+static UINT_PTR APIENTRY WinSaveHook (HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static bool bFolderSelected;
+static bool bDidCancel;
+static char selDirPath[kPathMax];
+#if PLUGGUI
+ extern HINSTANCE ghInst;
+ inline HINSTANCE GetInstance () { return ghInst; }
+#else
+ extern void* hInstance;
+ inline HINSTANCE GetInstance () { return (HINSTANCE)hInstance; }
+#endif
+#endif
+
+BEGIN_NAMESPACE_VSTGUI
+
+//-----------------------------------------------------------------------------
+CFileSelector::CFileSelector (void* ptr)
+: ptr (ptr)
+, vstFileSelect (0)
+{}
+
+//-----------------------------------------------------------------------------
+CFileSelector::~CFileSelector ()
+{
+ if (vstFileSelect)
+ {
+ #if VST
+ if (ptr && ((AudioEffectX*)ptr)->canHostDo ("closeFileSelector"))
+ ((AudioEffectX*)ptr)->closeFileSelector (vstFileSelect);
+ else
+ #endif
+ {
+ if (vstFileSelect->reserved == 1 && vstFileSelect->returnPath)
+ {
+ delete []vstFileSelect->returnPath;
+ vstFileSelect->returnPath = 0;
+ vstFileSelect->sizeReturnPath = 0;
+ }
+ if (vstFileSelect->returnMultiplePaths)
+ {
+ for (long i = 0; i < vstFileSelect->nbReturnPath; i++)
+ {
+ delete []vstFileSelect->returnMultiplePaths[i];
+ vstFileSelect->returnMultiplePaths[i] = 0;
+ }
+ delete[] vstFileSelect->returnMultiplePaths;
+ vstFileSelect->returnMultiplePaths = 0;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+long CFileSelector::run (VstFileSelect *vstFileSelect)
+{
+ this->vstFileSelect = vstFileSelect;
+ vstFileSelect->nbReturnPath = 0;
+ if (vstFileSelect->returnPath)
+ vstFileSelect->returnPath[0] = 0;
+
+ #if !PLUGGUI
+ if (ptr
+ #if MACX
+ && vstFileSelect->command != kVstFileSave
+ #endif
+ && ((AudioEffectX*)ptr)->canHostDo ("openFileSelector") && ((AudioEffectX*)ptr)->canHostDo ("closeFileSelector"))
+ {
+ if (((AudioEffectX*)ptr)->openFileSelector (vstFileSelect))
+ return vstFileSelect->nbReturnPath;
+ }
+ else
+ #endif
+ {
+#if WINDOWS
+ char filter[512];
+ char filePathBuffer[kPathMax];
+ strcpy (filePathBuffer, "");
+ char* filePath = filePathBuffer;
+ char fileName[kPathMax];
+ strcpy (fileName, "");
+ filter[0] = 0;
+ filePath[0] = 0;
+ fileName[0] = 0;
+
+ //-----------------------------------------
+ if (vstFileSelect->command == kVstFileLoad ||
+ vstFileSelect->command == kVstMultipleFilesLoad ||
+ vstFileSelect->command == kVstDirectorySelect)
+ {
+ char* multiBuffer = 0;
+ if (vstFileSelect->command == kVstMultipleFilesLoad)
+ {
+ multiBuffer = new char [kPathMax * 100];
+ strcpy (multiBuffer, "");
+ filePath = multiBuffer;
+ }
+
+ if (vstFileSelect->command != kVstDirectorySelect)
+ {
+ char allBuffer [kPathMax] = {0};
+ char* p = filter;
+ char* p2 = allBuffer;
+
+ const char* ext;
+ const char* extensions [100];
+ long i, j, extCount = 0;
+ char string[24];
+
+ for (long ty = 0; ty < vstFileSelect->nbFileTypes; ty++)
+ {
+ for (i = 0; i < 2 ; i++)
+ {
+ if (i == 0)
+ {
+ ext = vstFileSelect->fileTypes[ty].dosType;
+
+ strcpy (p, vstFileSelect->fileTypes[ty].name);
+ strcat (p, " (.");
+ strcat (p, ext);
+ strcat (p, ")");
+ p += strlen (p) + 1;
+
+ strcpy (string, "*.");
+ strcat (string, ext);
+ strcpy (p, string);
+ p += strlen (p);
+ }
+ else
+ {
+ if (!strcmp (vstFileSelect->fileTypes[ty].dosType, vstFileSelect->fileTypes[ty].unixType) || !strcmp (vstFileSelect->fileTypes[ty].unixType, ""))
+ break; // for
+ ext = vstFileSelect->fileTypes[ty].unixType;
+ strcpy (string, ";*.");
+ strcat (string, ext);
+ strcpy (p, string);
+ p += strlen (p);
+ }
+ bool found = false;
+ for (j = 0; j < extCount;j ++)
+ {
+ if (strcmp (ext, extensions [j]) == 0)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found && extCount < 100)
+ extensions [extCount++] = ext;
+ }
+ p ++;
+ } // end for filetype
+
+ if (extCount > 1)
+ {
+ for (i = 0; i < extCount ;i ++)
+ {
+ ext = extensions [i];
+ strcpy (string, "*.");
+ strcat (string, ext);
+
+ if (p2 != allBuffer)
+ {
+ strcpy (p2, ";");
+ p2++;
+ }
+ strcpy (p2, string);
+ p2 += strlen (p2);
+ }
+
+ // add the : All types
+ strcpy (p, stringAllTypes);
+ strcat (p, allBuffer);
+ strcat (p, ")");
+ p += strlen (p) + 1;
+ strcpy (p, allBuffer);
+ p += strlen (p) + 1;
+ }
+
+ strcpy (p, stringAnyType);
+ p += strlen (p) + 1;
+ strcpy (p, "*.*");
+ p += strlen (p) + 1;
+
+ *p++ = 0;
+ *p++ = 0;
+ }
+
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = sizeof (OPENFILENAME);
+ HWND owner = 0;
+ #if !PLUGGUI
+ if (ptr && ((AudioEffectX*)ptr)->getEditor () && ((AEffGUIEditor*)((AudioEffectX*)ptr)->getEditor ())->getFrame ())
+ owner = (HWND)((AEffGUIEditor*)((AudioEffectX*)ptr)->getEditor ())->getFrame ()->getSystemWindow ();
+ #endif
+ ofn.hwndOwner = owner;
+
+ if (vstFileSelect->command == kVstDirectorySelect)
+ ofn.lpstrFilter = "HideFileFilter\0*.___\0\0"; // to hide files
+ else
+ ofn.lpstrFilter = filter[0] ? filter : 0;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.lpstrFile = filePath;
+ if (vstFileSelect->command == kVstMultipleFilesLoad)
+ ofn.nMaxFile = 100 * kPathMax - 1;
+ else
+ ofn.nMaxFile = sizeof (filePathBuffer) - 1;
+
+ ofn.lpstrFileTitle = fileName;
+ ofn.nMaxFileTitle = 64;
+ ofn.lpstrInitialDir = vstFileSelect->initialPath;
+ ofn.lpstrTitle = vstFileSelect->title;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK;
+ if (vstFileSelect->command == kVstDirectorySelect)
+ {
+ ofn.Flags &= ~OFN_FILEMUSTEXIST;
+ ofn.lpfnHook = SelectDirectoryHook;
+ }
+
+ if (vstFileSelect->command == kVstMultipleFilesLoad)
+ ofn.Flags |= OFN_ALLOWMULTISELECT;
+
+ vstFileSelect->nbReturnPath = 0;
+ bDidCancel = true;
+
+ if (GetOpenFileName (&ofn) ||
+ ((vstFileSelect->command == kVstDirectorySelect) && !bDidCancel && strlen (selDirPath) != 0))
+ {
+ switch (vstFileSelect->command)
+ {
+ case kVstFileLoad:
+ vstFileSelect->nbReturnPath = 1;
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char[strlen (ofn.lpstrFile) + 1];
+ vstFileSelect->sizeReturnPath = (long)strlen (ofn.lpstrFile) + 1;
+ }
+ strcpy (vstFileSelect->returnPath, ofn.lpstrFile);
+ break;
+
+ case kVstMultipleFilesLoad:
+ {
+ char string[kPathMax], directory[kPathMax];
+ char *previous = ofn.lpstrFile;
+ size_t len;
+ bool dirFound = false;
+ bool first = true;
+ directory[0] = 0; // !!
+ vstFileSelect->returnMultiplePaths = new char*[kPathMax];
+ long i = 0;
+ while (1)
+ {
+ if (*previous != 0)
+ { // something found
+ if (!dirFound)
+ {
+ dirFound = true;
+ strcpy (directory, previous);
+ len = strlen (previous) + 1; // including 0
+ previous += len;
+
+ if (*previous == 0)
+ { // 1 selected file only
+ vstFileSelect->returnMultiplePaths[i] = new char [strlen (directory) + 1];
+ strcpy (vstFileSelect->returnMultiplePaths[i++], directory);
+ }
+ else
+ {
+ if (directory[strlen (directory) - 1] != '\\')
+ strcat (directory, "\\");
+ }
+ }
+ else
+ {
+ sprintf (string, "%s%s", directory, previous);
+ len = strlen (previous) + 1; // including 0
+ previous += len;
+
+ vstFileSelect->returnMultiplePaths[i] = new char [strlen (string) + 1];
+ strcpy (vstFileSelect->returnMultiplePaths[i++], string);
+ }
+ }
+ else
+ break;
+ }
+ vstFileSelect->nbReturnPath = i;
+ } break;
+
+ case kVstDirectorySelect:
+ vstFileSelect->nbReturnPath = 1;
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char[strlen (selDirPath) + 1];
+ vstFileSelect->sizeReturnPath = (long)strlen (selDirPath) + 1;
+ }
+ strcpy (vstFileSelect->returnPath, selDirPath);
+ }
+ if (multiBuffer)
+ delete []multiBuffer;
+ return vstFileSelect->nbReturnPath;
+ }
+ if (multiBuffer)
+ delete []multiBuffer;
+ }
+
+ //-----------------------------------------
+ else if (vstFileSelect->command == kVstFileSave)
+ {
+ char* p = filter;
+ for (long ty = 0; ty < vstFileSelect->nbFileTypes; ty++)
+ {
+ const char* ext = vstFileSelect->fileTypes[ty].dosType;
+ if (ext)
+ {
+ strcpy (p, vstFileSelect->fileTypes[ty].name);
+ strcat (p, " (.");
+ strcat (p, ext);
+ strcat (p, ")");
+ p += strlen (p) + 1;
+
+ char string[24];
+ strcpy (string, "*.");
+ strcat (string, ext);
+ strcpy (p, string);
+ p += strlen (p) + 1;
+ }
+ }
+ *p++ = 0;
+ *p++ = 0;
+
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = sizeof (OPENFILENAME);
+ HWND owner = 0;
+ #if !PLUGGUI
+ if (((AudioEffectX*)ptr)->getEditor () && ((AEffGUIEditor*)((AudioEffectX*)ptr)->getEditor ())->getFrame ())
+ owner = (HWND)((AEffGUIEditor*)((AudioEffectX*)ptr)->getEditor ())->getFrame ()->getSystemWindow ();
+ #endif
+ ofn.hwndOwner = owner;
+ ofn.hInstance = GetInstance ();
+ ofn.lpstrFilter = filter[0] ? filter : 0;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = filePath;
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nMaxFile = sizeof (filePathBuffer) - 1;
+ ofn.lpstrFileTitle = fileName;
+ ofn.nMaxFileTitle = 64;
+ ofn.lpstrInitialDir = vstFileSelect->initialPath;
+ ofn.lpstrTitle = vstFileSelect->title;
+ ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_ENABLEHOOK;
+
+ if (vstFileSelect->nbFileTypes >= 1)
+ ofn.lpstrDefExt = vstFileSelect->fileTypes[0].dosType;
+
+ // add a template view
+ ofn.lCustData = (DWORD)0;
+ ofn.lpfnHook = WinSaveHook;
+
+ if (GetSaveFileName (&ofn))
+ {
+ vstFileSelect->nbReturnPath = 1;
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char[strlen (ofn.lpstrFile) + 1];
+ vstFileSelect->sizeReturnPath = (long)strlen (ofn.lpstrFile) + 1;
+ }
+ strcpy (vstFileSelect->returnPath, ofn.lpstrFile);
+
+ return vstFileSelect->nbReturnPath;
+ }
+ #if _DEBUG
+ else
+ {
+ DWORD err = CommDlgExtendedError (); // for breakpoint
+ }
+ #endif
+ }
+
+#elif MAC
+#if TARGET_API_MAC_CARBON
+ #if MACX
+ // new approach for supporting long filenames on mac os x is to use unix path mode
+ // if vstFileSelect->future[0] is 1 on entry and 0 on exit the resulting paths are UTF8 encoded paths
+ bool unixPathMode = (vstFileSelect->future[0] == 1);
+ #endif
+ NavEventUPP eventUPP = NewNavEventUPP (CFileSelector::navEventProc);
+ if (vstFileSelect->command == kVstFileSave)
+ {
+ NavDialogCreationOptions dialogOptions;
+ NavGetDefaultDialogCreationOptions (&dialogOptions);
+ dialogOptions.windowTitle = CFStringCreateWithCString (NULL, vstFileSelect->title[0] ? vstFileSelect->title : "Select a Destination", kCFStringEncodingUTF8);
+ CFStringRef defSaveName = 0;
+ #if MACX
+ if (unixPathMode && vstFileSelect->initialPath)
+ {
+ char* name = strrchr (vstFileSelect->initialPath, '/');
+ if (name && name[1] != 0)
+ {
+ defSaveName = dialogOptions.saveFileName = CFStringCreateWithCString (NULL, name+1, kCFStringEncodingUTF8);
+ name[0] = 0;
+ dialogOptions.optionFlags |= kNavPreserveSaveFileExtension;
+ }
+ else if (name == 0)
+ {
+ defSaveName = dialogOptions.saveFileName = CFStringCreateWithCString (NULL, vstFileSelect->initialPath, kCFStringEncodingUTF8);
+ dialogOptions.optionFlags |= kNavPreserveSaveFileExtension;
+ vstFileSelect->initialPath = 0;
+ }
+ }
+ else
+ #endif
+ if (vstFileSelect->initialPath && ((FSSpec*)vstFileSelect->initialPath)->name)
+ {
+ FSSpec* defaultSpec = (FSSpec*)vstFileSelect->initialPath;
+ defSaveName = CFStringCreateWithPascalString (NULL, defaultSpec->name, kCFStringEncodingASCII);
+ if (defSaveName)
+ {
+ dialogOptions.saveFileName = defSaveName;
+ dialogOptions.optionFlags |= kNavPreserveSaveFileExtension;
+ }
+ *defaultSpec->name = 0;
+ }
+ NavDialogRef dialogRef;
+ if (NavCreatePutFileDialog (&dialogOptions, NULL, kNavGenericSignature, eventUPP, this, &dialogRef) == noErr)
+ {
+ AEDesc defaultLocation;
+ AEDesc* defLocPtr = 0;
+ if (vstFileSelect->initialPath)
+ {
+ #if MACX
+ if (unixPathMode)
+ {
+ FSRef fsRef;
+ if (FSPathMakeRef ((const unsigned char*)vstFileSelect->initialPath, &fsRef, NULL) == noErr)
+ {
+ if (AECreateDesc (typeFSRef, &fsRef, sizeof(FSRef), &defaultLocation) == noErr)
+ defLocPtr = &defaultLocation;
+ }
+ }
+ else
+ #endif
+ {
+ FSSpec* defaultSpec = (FSSpec*)vstFileSelect->initialPath;
+ if (defaultSpec->parID && defaultSpec->vRefNum)
+ {
+ if (AECreateDesc (typeFSS, defaultSpec, sizeof(FSSpec), &defaultLocation) == noErr)
+ defLocPtr = &defaultLocation;
+ }
+ }
+ }
+ if (defLocPtr)
+ NavCustomControl (dialogRef, kNavCtlSetLocation, (void*)defLocPtr);
+ NavDialogRun (dialogRef);
+
+ if (defLocPtr)
+ AEDisposeDesc (defLocPtr);
+
+ NavReplyRecord navReply;
+ if (NavDialogGetReply (dialogRef, &navReply) == noErr)
+ {
+ FSRef parentFSRef;
+ AEKeyword theAEKeyword;
+ DescType typeCode;
+ Size actualSize;
+ // get the FSRef referring to the parent directory
+ if (AEGetNthPtr(&navReply.selection, 1, typeFSRef,
+ &theAEKeyword, &typeCode, &parentFSRef, sizeof(FSRef), &actualSize) == noErr)
+ {
+ #if MACX
+ if (unixPathMode)
+ {
+ bool success = true;
+ vstFileSelect->nbReturnPath = 1;
+ if (vstFileSelect->returnPath == 0)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [PATH_MAX];
+ }
+ if (FSRefMakePath (&parentFSRef, (unsigned char*)vstFileSelect->returnPath, PATH_MAX) == noErr)
+ {
+ char saveFileName [PATH_MAX];
+ if (CFStringGetCString (navReply.saveFileName, saveFileName, PATH_MAX, kCFStringEncodingUTF8))
+ {
+ strcat (vstFileSelect->returnPath, "/");
+ strcat (vstFileSelect->returnPath, saveFileName);
+ vstFileSelect->future[0] = 0;
+ }
+ else
+ success = false;
+ }
+ else
+ success = false;
+ if (!success && vstFileSelect->reserved)
+ {
+ vstFileSelect->nbReturnPath = 0;
+ delete [] vstFileSelect->returnPath;
+ }
+ }
+ else
+ #endif
+ {
+ FSSpec spec;
+ FSCatalogInfoBitmap infoBitmap = kFSCatInfoNone;
+ FSGetCatalogInfo (&parentFSRef, infoBitmap, NULL, NULL, &spec, NULL);
+ CInfoPBRec pbRec = {0};
+ pbRec.dirInfo.ioDrDirID = spec.parID;
+ pbRec.dirInfo.ioVRefNum = spec.vRefNum;
+ pbRec.dirInfo.ioNamePtr = spec.name;
+ if (PBGetCatInfoSync (&pbRec) == noErr)
+ {
+ spec.parID = pbRec.dirInfo.ioDrDirID;
+ // the cfstring -> pascalstring can fail if the filename length > 63 (FSSpec sucks)
+ if (CFStringGetPascalString (navReply.saveFileName, (unsigned char*)&spec.name, sizeof (spec.name), kCFStringEncodingASCII))
+ {
+ vstFileSelect->nbReturnPath = 1;
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [sizeof (FSSpec)];
+ }
+ memcpy (vstFileSelect->returnPath, &spec, sizeof (FSSpec));
+ }
+ }
+ }
+ }
+ NavDisposeReply (&navReply);
+ }
+ if (defSaveName)
+ CFRelease (defSaveName);
+ NavDialogDispose (dialogRef);
+ DisposeNavEventUPP (eventUPP);
+ return vstFileSelect->nbReturnPath;
+ }
+ if (defSaveName)
+ CFRelease (defSaveName);
+ }
+ else if (vstFileSelect->command == kVstDirectorySelect)
+ {
+ NavDialogCreationOptions dialogOptions;
+ NavGetDefaultDialogCreationOptions (&dialogOptions);
+ dialogOptions.windowTitle = CFStringCreateWithCString (NULL, vstFileSelect->title[0] ? vstFileSelect->title : "Select Directory", kCFStringEncodingUTF8);
+ NavDialogRef dialogRef;
+ if (NavCreateChooseFolderDialog (&dialogOptions, eventUPP, NULL, this, &dialogRef) == noErr)
+ {
+ AEDesc defaultLocation;
+ AEDesc* defLocPtr = 0;
+ if (vstFileSelect->initialPath)
+ {
+ #if MACX
+ if (unixPathMode)
+ {
+ FSRef fsRef;
+ if (FSPathMakeRef ((const unsigned char*)vstFileSelect->initialPath, &fsRef, NULL) == noErr)
+ {
+ if (AECreateDesc (typeFSRef, &fsRef, sizeof(FSRef), &defaultLocation) == noErr)
+ defLocPtr = &defaultLocation;
+ }
+ }
+ else
+ #endif
+ {
+ FSSpec* defaultSpec = (FSSpec*)vstFileSelect->initialPath;
+ if (defaultSpec->parID && defaultSpec->vRefNum)
+ if (AECreateDesc (typeFSS, defaultSpec, sizeof(FSSpec), &defaultLocation) == noErr)
+ defLocPtr = &defaultLocation;
+ }
+ }
+ if (defLocPtr)
+ NavCustomControl (dialogRef, kNavCtlSetLocation, (void*)defLocPtr);
+ NavDialogRun (dialogRef);
+ if (defLocPtr)
+ AEDisposeDesc (defLocPtr);
+ NavReplyRecord navReply;
+ if (NavDialogGetReply (dialogRef, &navReply) == noErr)
+ {
+ FSRef parentFSRef;
+ AEKeyword theAEKeyword;
+ DescType typeCode;
+ Size actualSize;
+ if (AEGetNthPtr(&navReply.selection, 1, typeFSRef,
+ &theAEKeyword, &typeCode, &parentFSRef, sizeof(FSRef), &actualSize) == noErr)
+ {
+ #if MACX
+ if (unixPathMode)
+ {
+ vstFileSelect->nbReturnPath = 1;
+ if (vstFileSelect->returnPath == 0)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [PATH_MAX];
+ }
+ if (FSRefMakePath (&parentFSRef, (unsigned char*)vstFileSelect->returnPath, PATH_MAX) != noErr)
+ {
+ vstFileSelect->nbReturnPath = 0;
+ if (vstFileSelect->reserved)
+ delete [] vstFileSelect->returnPath;
+ }
+ else
+ vstFileSelect->future[0] = 0;
+ }
+ else
+ #endif
+ {
+ FSSpec spec;
+ FSCatalogInfoBitmap infoBitmap = kFSCatInfoNone;
+ FSGetCatalogInfo (&parentFSRef, infoBitmap, NULL, NULL, &spec, NULL);
+ vstFileSelect->nbReturnPath = 1;
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [sizeof (FSSpec)];
+ }
+ memcpy (vstFileSelect->returnPath, &spec, sizeof (FSSpec));
+ }
+ }
+
+ NavDisposeReply (&navReply);
+ }
+ NavDialogDispose (dialogRef);
+ DisposeNavEventUPP (eventUPP);
+ return vstFileSelect->nbReturnPath;
+ }
+ }
+ else // FileLoad
+ {
+ NavDialogCreationOptions dialogOptions;
+ NavGetDefaultDialogCreationOptions (&dialogOptions);
+ if (vstFileSelect->command == kVstFileLoad)
+ {
+ dialogOptions.windowTitle = CFStringCreateWithCString (NULL, vstFileSelect->title[0] ? vstFileSelect->title : "Select a File to Open", kCFStringEncodingUTF8);
+ dialogOptions.optionFlags &= ~kNavAllowMultipleFiles;
+ }
+ else
+ {
+ dialogOptions.windowTitle = CFStringCreateWithCString (NULL, vstFileSelect->title[0] ? vstFileSelect->title : "Select Files to Open", kCFStringEncodingUTF8);
+ dialogOptions.optionFlags |= kNavAllowMultipleFiles;
+ }
+ NavObjectFilterUPP objectFilterUPP = NewNavObjectFilterUPP (CFileSelector::navObjectFilterProc);
+ NavDialogRef dialogRef;
+ if (NavCreateGetFileDialog (&dialogOptions, NULL, eventUPP, NULL, objectFilterUPP, this, &dialogRef) == noErr)
+ {
+ AEDesc defaultLocation;
+ AEDesc* defLocPtr = 0;
+ if (vstFileSelect->initialPath)
+ {
+ #if MACX
+ if (unixPathMode)
+ {
+ FSRef fsRef;
+ if (FSPathMakeRef ((const unsigned char*)vstFileSelect->initialPath, &fsRef, NULL) == noErr)
+ {
+ if (AECreateDesc (typeFSRef, &fsRef, sizeof(FSRef), &defaultLocation) == noErr)
+ defLocPtr = &defaultLocation;
+ }
+ }
+ else
+ #endif
+ {
+ FSSpec* defaultSpec = (FSSpec*)vstFileSelect->initialPath;
+ if (defaultSpec->parID && defaultSpec->vRefNum)
+ if (AECreateDesc (typeFSS, defaultSpec, sizeof(FSSpec), &defaultLocation) == noErr)
+ defLocPtr = &defaultLocation;
+ }
+ }
+ if (defLocPtr)
+ NavCustomControl (dialogRef, kNavCtlSetLocation, (void*)defLocPtr);
+
+ NavDialogRun (dialogRef);
+
+ if (defLocPtr)
+ AEDisposeDesc (defLocPtr);
+
+ NavReplyRecord navReply;
+ if (NavDialogGetReply (dialogRef, &navReply) == noErr)
+ {
+ FSRef parentFSRef;
+ AEKeyword theAEKeyword;
+ DescType typeCode;
+ Size actualSize;
+ if (vstFileSelect->command == kVstFileLoad)
+ {
+ if (AEGetNthPtr(&navReply.selection, 1, typeFSRef,
+ &theAEKeyword, &typeCode, &parentFSRef, sizeof(FSRef), &actualSize) == noErr)
+ {
+ #if MACX
+ if (unixPathMode)
+ {
+ vstFileSelect->nbReturnPath = 1;
+ if (vstFileSelect->returnPath == 0)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [PATH_MAX];
+ }
+ if (FSRefMakePath (&parentFSRef, (unsigned char*)vstFileSelect->returnPath, PATH_MAX) != noErr)
+ {
+ vstFileSelect->nbReturnPath = 0;
+ if (vstFileSelect->reserved)
+ delete [] vstFileSelect->returnPath;
+ }
+ else
+ vstFileSelect->future[0] = 0;
+ }
+ else
+ #endif
+ {
+ FSSpec spec;
+ FSCatalogInfoBitmap infoBitmap = kFSCatInfoNone;
+ FSGetCatalogInfo (&parentFSRef, infoBitmap, NULL, NULL, &spec, NULL);
+ vstFileSelect->nbReturnPath = 1;
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [sizeof (FSSpec)];
+ }
+ memcpy (vstFileSelect->returnPath, &spec, sizeof (FSSpec));
+ }
+ }
+ }
+ else
+ {
+ long nbReturnPath;
+ AECountItems (&navReply.selection, &nbReturnPath);
+ vstFileSelect->nbReturnPath = nbReturnPath;
+ vstFileSelect->returnMultiplePaths = new char* [vstFileSelect->nbReturnPath];
+ int index = 1;
+ while (AEGetNthPtr(&navReply.selection, index++, typeFSRef,
+ &theAEKeyword, &typeCode, &parentFSRef, sizeof(FSRef), &actualSize) == noErr)
+ {
+ #if MACX
+ if (unixPathMode)
+ {
+ vstFileSelect->returnMultiplePaths[index-2] = new char[PATH_MAX];
+ FSRefMakePath (&parentFSRef, (unsigned char*)vstFileSelect->returnMultiplePaths[index-2], PATH_MAX);
+ vstFileSelect->future[0] = 0;
+ }
+ else
+ #endif
+ {
+ FSSpec spec;
+ FSCatalogInfoBitmap infoBitmap = kFSCatInfoNone;
+ FSGetCatalogInfo (&parentFSRef, infoBitmap, NULL, NULL, &spec, NULL);
+ vstFileSelect->returnMultiplePaths[index-2] = new char[sizeof (FSSpec)];
+ memcpy (vstFileSelect->returnMultiplePaths[index-2], &spec, sizeof (FSSpec));
+ }
+ }
+ }
+ }
+ DisposeNavObjectFilterUPP (objectFilterUPP);
+ DisposeNavEventUPP (eventUPP);
+ NavDialogDispose (dialogRef);
+ return vstFileSelect->nbReturnPath;
+ }
+ DisposeNavObjectFilterUPP (objectFilterUPP);
+ }
+ DisposeNavEventUPP (eventUPP);
+#else
+ StandardFileReply reply;
+ if (vstFileSelect->command == kVstFileSave)
+ {
+ unsigned char defName[64];
+ defName[0] = 0;
+ StandardPutFile ("\pSelect a Destination", defName, &reply);
+ if (reply.sfGood && reply.sfFile.name[0] != 0)
+ {
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [301];
+ }
+ memcpy (vstFileSelect->returnPath, &reply.sfFile, 300);
+ vstFileSelect->nbReturnPath = 1;
+ return 1;
+ }
+ }
+
+ else if (vstFileSelect->command == kVstDirectorySelect)
+ {
+ #if USENAVSERVICES
+ if (NavServicesAvailable ())
+ {
+ NavReplyRecord navReply;
+ NavDialogOptions dialogOptions;
+ short ret = false;
+ AEDesc defLoc;
+ defLoc.descriptorType = typeFSS;
+ defLoc.dataHandle = NewHandle (sizeof (FSSpec));
+ FSSpec finalFSSpec;
+ finalFSSpec.parID = 0; // *dirID;
+ finalFSSpec.vRefNum = 0; // *volume;
+ finalFSSpec.name[0] = 0;
+
+ NavGetDefaultDialogOptions (&dialogOptions);
+ dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
+ dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
+ strcpy ((char* )dialogOptions.message, "Select Directory");
+ c2pstr ((char* )dialogOptions.message);
+ NavChooseFolder (&defLoc, &navReply, &dialogOptions, 0 /* eventUPP */, 0, 0);
+ DisposeHandle (defLoc.dataHandle);
+
+ AEDesc resultDesc;
+ AEKeyword keyword;
+ resultDesc.dataHandle = 0L;
+
+ if (navReply.validRecord && AEGetNthDesc (&navReply.selection, 1, typeFSS, &keyword, &resultDesc) == noErr)
+ {
+ ret = true;
+ vstFileSelect->nbReturnPath = 1;
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [sizeof (FSSpec)];
+ }
+ memcpy (vstFileSelect->returnPath, *resultDesc.dataHandle, sizeof (FSSpec));
+ }
+ NavDisposeReply (&navReply);
+ return vstFileSelect->nbReturnPath;
+ }
+ else
+ #endif
+ {
+ // Can't select a Folder; the Application does not support it, and Navigational Services are not available...
+ return 0;
+ }
+ }
+
+ else
+ {
+ SFTypeList typelist;
+ long numFileTypes = vstFileSelect->nbFileTypes;
+ //seem not to work... if (numFileTypes <= 0)
+ {
+ numFileTypes = -1; // all files
+ typelist[0] = 'AIFF';
+ }
+ /*else
+ {
+ if (numFileTypes > 4)
+ numFileTypes = 4;
+ for (long i = 0; i < numFileTypes; i++)
+ memcpy (&typelist[i], vstFileSelect->fileTypes[i].macType, 4);
+ }*/
+ StandardGetFile (0L, numFileTypes, typelist, &reply);
+ if (reply.sfGood)
+ {
+ if (!vstFileSelect->returnPath)
+ {
+ vstFileSelect->reserved = 1;
+ vstFileSelect->returnPath = new char [301];
+ }
+ memcpy (vstFileSelect->returnPath, &reply.sfFile, 300);
+ vstFileSelect->nbReturnPath = 1;
+ return 1;
+ }
+ }
+#endif // TARGET_API_MAC_CARBON
+#else
+ //CAlert::alert ("The current Host application doesn't support FileSelector !", "Warning");
+#endif
+ }
+ return 0;
+}
+
+#if MAC && TARGET_API_MAC_CARBON
+//-----------------------------------------------------------------------------
+pascal void CFileSelector::navEventProc (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
+{
+ CFileSelector* fs = (CFileSelector*)callBackUD;
+ switch (callBackSelector)
+ {
+ case kNavCBEvent:
+ {
+ #if !PLUGGUI
+ AudioEffectX* effect = (AudioEffectX*)fs->ptr;
+ if (effect && callBackParms->eventData.eventDataParms.event->what == nullEvent)
+ effect->masterIdle ();
+ #endif
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+pascal Boolean CFileSelector::navObjectFilterProc (AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
+{
+ Boolean result = false;
+ CFileSelector* fs = (CFileSelector*)callBackUD;
+ NavFileOrFolderInfo *theInfo = (NavFileOrFolderInfo*)info;
+
+ if (theInfo->isFolder || fs->vstFileSelect->nbFileTypes == 0)
+ result = true;
+ else
+ {
+ FSRef ref;
+ AECoerceDesc (theItem, typeFSRef, theItem);
+ if (AEGetDescData (theItem, &ref, sizeof (FSRef)) == noErr)
+ {
+ LSItemInfoRecord infoRecord;
+ if (LSCopyItemInfoForRef (&ref, kLSRequestExtension | kLSRequestTypeCreator, &infoRecord) == noErr)
+ {
+ char extension [128];
+ extension[0] = 0;
+ if (infoRecord.extension)
+ CFStringGetCString (infoRecord.extension, extension, 128, kCFStringEncodingUTF8);
+ for (long i = 0; i < fs->vstFileSelect->nbFileTypes; i++)
+ {
+ VstFileType* ft = &fs->vstFileSelect->fileTypes[i];
+ if ((OSType)ft->macType == infoRecord.filetype)
+ {
+ result = true;
+ break;
+ }
+ else if (infoRecord.extension)
+ {
+ if (!strcasecmp (extension, ft->unixType) || !strcasecmp (extension, ft->dosType))
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ if (infoRecord.extension)
+ CFRelease (infoRecord.extension);
+ }
+ }
+ }
+ return result;
+}
+#endif
+
+END_NAMESPACE_VSTGUI
+
+#if WINDOWS
+#include <dlgs.h>
+//-----------------------------------------------------------------------------
+UINT_PTR APIENTRY SelectDirectoryHook (HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_NOTIFY:
+ {
+ OFNOTIFY *lpon = (OFNOTIFY *)lParam;
+
+ switch (lpon->hdr.code)
+ {
+ case CDN_FILEOK:
+ CommDlg_OpenSave_GetFolderPath (GetParent (hdlg), selDirPath, kPathMax);
+ bDidCancel = false;
+ break;
+
+ case CDN_INITDONE: {
+ #define HIDE_ITEMS 4
+ int i;
+ UINT hide_items[HIDE_ITEMS] = {edt1, stc3, cmb1, stc2};
+
+ for (i = 0; i < HIDE_ITEMS; i++)
+ CommDlg_OpenSave_HideControl (GetParent (hdlg), hide_items[i]);
+
+ CommDlg_OpenSave_SetControlText (GetParent (hdlg), stc4, (char*)(const char*)stringLookIn);
+ CommDlg_OpenSave_SetControlText (GetParent (hdlg), IDOK, (char*)(const char*)stringSelect);
+ CommDlg_OpenSave_SetControlText (GetParent (hdlg), IDCANCEL, (char*)(const char*)stringCancel);
+ } break;
+ }
+ } break;
+
+ case WM_INITDIALOG:
+ fpOldSelectDirectoryButtonProc = /*(FARPROC)*/(WNDPROC)SetWindowLongPtr (
+ GetDlgItem (GetParent (hdlg), IDOK),
+ GWLP_WNDPROC, (LONG_PTR)SelectDirectoryButtonProc);
+ break;
+
+ case WM_DESTROY:
+ SetWindowLongPtr (GetDlgItem (GetParent (hdlg), IDOK),
+ GWLP_WNDPROC, (LONG_PTR)fpOldSelectDirectoryButtonProc);
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK SelectDirectoryButtonProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_SETTEXT:
+ if (! (strcmp ((char *)lParam, stringSelect) == 0))
+ return false;
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP: {
+ char mode[256];
+ GetWindowText (hwnd, mode, 256);
+ if (!strcmp (mode, stringSelect))
+ {
+ bFolderSelected = true;
+ char oldDirPath[kPathMax];
+ CommDlg_OpenSave_GetFolderPath (GetParent (hwnd), oldDirPath, kPathMax);
+ // you need a lot of tricks to get name of currently selected folder:
+ // the following call of the original windows procedure causes the
+ // selected folder to open and after that you can retrieve its name
+ // by calling ..._GetFolderPath (...)
+ CallWindowProc ((WNDPROC)fpOldSelectDirectoryButtonProc, hwnd, message, wParam, lParam);
+ CommDlg_OpenSave_GetFolderPath (GetParent (hwnd), selDirPath, kPathMax);
+
+ if (1) // consumers like it like this
+ {
+ if (strcmp (oldDirPath, selDirPath) == 0 || selDirPath [0] == 0)
+ {
+ // the same folder as the old one, means nothing selected: close
+ bFolderSelected = true;
+ bDidCancel = false;
+ PostMessage (GetParent (hwnd), WM_CLOSE, 0, 0);
+ return false;
+ }
+ else
+ {
+ // another folder is selected: browse into it
+ bFolderSelected = false;
+ return true;
+ }
+ }
+ else // original code
+ {
+ if (strcmp (oldDirPath, selDirPath) == 0 || selDirPath [0] == 0)
+ {
+ // the same folder as the old one, means nothing selected: stay open
+ bFolderSelected = false;
+ return true;
+ }
+ }
+ }
+
+ bDidCancel = false;
+ PostMessage (GetParent (hwnd), WM_CLOSE, 0, 0);
+ return false;
+ } break;
+ } // end switch
+
+ return CallWindowProc ((WNDPROC)fpOldSelectDirectoryButtonProc, hwnd, message, wParam, lParam);
+}
+
+//-----------------------------------------------------------------------------
+static void showPathInWindowTitle (HWND hParent, LPOFNOTIFY lpon)
+{
+ #define WINDOWTEXTSIZE 260 + 64
+ OPENFILENAME *ofn = lpon->lpOFN;
+ char text[WINDOWTEXTSIZE];
+ char *p;
+ size_t len;
+
+ // Put the path into the Window Title
+ if (lpon->lpOFN->lpstrTitle)
+ strcpy (text, lpon->lpOFN->lpstrTitle);
+ else
+ {
+ char *pp;
+
+ GetWindowText (hParent, text, WINDOWTEXTSIZE);
+ pp = strchr (text, '-');
+ if (pp)
+ *--pp = 0;
+ }
+
+ p = strcat (text, " - [");
+ p = text;
+ len = strlen (text);
+ p += len;
+ len = WINDOWTEXTSIZE - len - 2;
+ CommDlg_OpenSave_GetFolderPath (hParent, p, len);
+ strcat (text, "]");
+ SetWindowText (hParent, text);
+}
+
+//------------------------------------------------------------------------
+UINT_PTR APIENTRY WinSaveHook (HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_NOTIFY: {
+ LPOFNOTIFY lpon = (LPOFNOTIFY)lParam;
+ if (!lpon)
+ break;
+
+ switch (lpon->hdr.code)
+ {
+ case CDN_FOLDERCHANGE:
+ showPathInWindowTitle (GetParent (hdlg), lpon);
+ break;
+ }
+ } break;
+ } // end switch
+
+ return 0;
+}
+#endif
+
+//-----------------------------------------------------------------------------