iPlug2 - C++ Audio Plug-in Framework
IPlugPaths.cpp
Go to the documentation of this file.
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 
16 #include "IPlugPlatform.h"
17 #include "IPlugConstants.h"
18 #include "IPlugPaths.h"
19 
20 #if defined OS_WEB
21 #include <emscripten/val.h>
22 #elif defined OS_WIN
23 #include <windows.h>
24 #include <Shlobj.h>
25 #include <Shlwapi.h>
26 #endif
27 
28 BEGIN_IPLUG_NAMESPACE
29 
30 #if defined OS_WIN
31 #pragma mark - OS_WIN
32 
33 // Unicode helpers
34 void UTF8ToUTF16(wchar_t* utf16Str, const char* utf8Str, int maxLen)
35 {
36  int requiredSize = MultiByteToWideChar(CP_UTF8, 0, utf8Str, -1, NULL, 0);
37 
38  if (requiredSize > 0 && requiredSize <= maxLen)
39  {
40  MultiByteToWideChar(CP_UTF8, 0, utf8Str, -1, utf16Str, requiredSize);
41  return;
42  }
43 
44  utf16Str[0] = 0;
45 }
46 
47 void UTF16ToUTF8(WDL_String& utf8Str, const wchar_t* utf16Str)
48 {
49  int requiredSize = WideCharToMultiByte(CP_UTF8, 0, utf16Str, -1, NULL, 0, NULL, NULL);
50 
51  if (requiredSize > 0 && utf8Str.SetLen(requiredSize))
52  {
53  WideCharToMultiByte(CP_UTF8, 0, utf16Str, -1, utf8Str.Get(), requiredSize, NULL, NULL);
54  return;
55  }
56 
57  utf8Str.Set("");
58 }
59 
60  // Helper for getting a known folder in UTF8
61 void GetKnownFolder(WDL_String &path, int identifier, int flags = 0)
62 {
63  wchar_t wideBuffer[1024];
64 
65  SHGetFolderPathW(NULL, identifier, NULL, flags, wideBuffer);
66  UTF16ToUTF8(path, wideBuffer);
67 }
68 
69 static void GetModulePath(HMODULE hModule, WDL_String& path)
70 {
71  path.Set("");
72  char pathCStr[MAX_WIN32_PATH_LEN];
73  pathCStr[0] = '\0';
74  if (GetModuleFileName(hModule, pathCStr, MAX_WIN32_PATH_LEN))
75  {
76  int s = -1;
77  for (int i = 0; i < strlen(pathCStr); ++i)
78  {
79  if (pathCStr[i] == '\\')
80  {
81  s = i;
82  }
83  }
84  if (s >= 0 && s + 1 < strlen(pathCStr))
85  {
86  path.Set(pathCStr, s + 1);
87  }
88  }
89 }
90 
91 void HostPath(WDL_String& path, const char* bundleID)
92 {
93  GetModulePath(0, path);
94 }
95 
96 void PluginPath(WDL_String& path, HMODULE pExtra)
97 {
98  GetModulePath(pExtra, path);
99 }
100 
101 void BundleResourcePath(WDL_String& path, HMODULE pExtra)
102 {
103 #ifdef VST3_API
104  GetModulePath(pExtra, path);
105 #ifdef ARCH_64BIT
106  path.SetLen(path.GetLength() - strlen("x86_64-win/"));
107 #else
108  path.SetLen(path.GetLength() - strlen("x86-win/"));
109 #endif
110  path.Append("Resources\\");
111 #endif
112 }
113 
114 void DesktopPath(WDL_String& path)
115 {
116  GetKnownFolder(path, CSIDL_DESKTOP);
117 }
118 
119 void UserHomePath(WDL_String & path)
120 {
121  GetKnownFolder(path, CSIDL_PROFILE);
122 }
123 
124 void AppSupportPath(WDL_String& path, bool isSystem)
125 {
126  GetKnownFolder(path, isSystem ? CSIDL_COMMON_APPDATA : CSIDL_LOCAL_APPDATA);
127 }
128 
129 void VST3PresetsPath(WDL_String& path, const char* mfrName, const char* pluginName, bool isSystem)
130 {
131  if (!isSystem)
132  GetKnownFolder(path, CSIDL_PERSONAL, SHGFP_TYPE_CURRENT);
133  else
134  AppSupportPath(path, true);
135 
136  path.AppendFormatted(MAX_WIN32_PATH_LEN, "\\VST3 Presets\\%s\\%s", mfrName, pluginName);
137 }
138 
139 void SandboxSafeAppSupportPath(WDL_String& path, const char* appGroupID)
140 {
141  AppSupportPath(path);
142 }
143 
144 void INIPath(WDL_String& path, const char * pluginName)
145 {
146  GetKnownFolder(path, CSIDL_LOCAL_APPDATA);
147 
148  path.AppendFormatted(MAX_WIN32_PATH_LEN, "\\%s", pluginName);
149 }
150 
151 static BOOL EnumResNameProc(HANDLE module, LPCTSTR type, LPTSTR name, LONG_PTR param)
152 {
153  if (IS_INTRESOURCE(name)) return true; // integer resources not wanted
154  else {
155  WDL_String* search = (WDL_String*)param;
156  if (search != 0 && name != 0)
157  {
158  //strip off extra quotes
159  WDL_String strippedName(strlwr(name + 1));
160  strippedName.SetLen(strippedName.GetLength() - 1);
161 
162  if (strcmp(strlwr(search->Get()), strippedName.Get()) == 0) // if we are looking for a resource with this name
163  {
164  search->SetFormatted(strippedName.GetLength() + 7, "found: %s", strippedName.Get());
165  return false;
166  }
167  }
168  }
169 
170  return true; // keep enumerating
171 }
172 
173 EResourceLocation LocateResource(const char* name, const char* type, WDL_String& result, const char*, void* pHInstance, const char*)
174 {
175  if (CStringHasContents(name))
176  {
177  WDL_String search(name);
178  WDL_String typeUpper(type);
179 
180  HMODULE hInstance = static_cast<HMODULE>(pHInstance);
181 
182  EnumResourceNames(hInstance, _strupr(typeUpper.Get()), (ENUMRESNAMEPROC)EnumResNameProc, (LONG_PTR)&search);
183 
184  if (strstr(search.Get(), "found: ") != 0)
185  {
186  result.SetFormatted(MAX_PATH, "\"%s\"", search.Get() + 7, search.GetLength() - 7); // 7 = strlen("found: ")
187  return EResourceLocation::kWinBinary;
188  }
189  else
190  {
191  if (PathFileExists(name))
192  {
193  result.Set(name);
194  return EResourceLocation::kAbsolutePath;
195  }
196  }
197  }
198  return EResourceLocation::kNotFound;
199 }
200 
201 const void* LoadWinResource(const char* resid, const char* type, int& sizeInBytes, void* pHInstance)
202 {
203  WDL_String typeUpper(type);
204 
205  HMODULE hInstance = static_cast<HMODULE>(pHInstance);
206 
207  HRSRC hResource = FindResource(hInstance, resid, _strupr(typeUpper.Get()));
208 
209  if (!hResource)
210  return NULL;
211 
212  DWORD size = SizeofResource(hInstance, hResource);
213 
214  if (size < 8)
215  return NULL;
216 
217  HGLOBAL res = LoadResource(hInstance, hResource);
218 
219  const void* pResourceData = LockResource(res);
220 
221  if (!pResourceData)
222  {
223  sizeInBytes = 0;
224  return NULL;
225  }
226  else
227  {
228  sizeInBytes = size;
229  return pResourceData;
230  }
231 }
232 
233 bool AppIsSandboxed()
234 {
235  return false;
236 }
237 
238 #elif defined OS_WEB
239 #pragma mark - OS_WEB
240 
241 void AppSupportPath(WDL_String& path, bool isSystem)
242 {
243  path.Set("Settings");
244 }
245 
246 void SandboxSafeAppSupportPath(WDL_String& path, const char* appGroupID)
247 {
248  path.Set("Settings");
249 }
250 
251 void DesktopPath(WDL_String& path)
252 {
253  path.Set("");
254 }
255 
256 void VST3PresetsPath(WDL_String& path, const char* mfrName, const char* pluginName, bool isSystem)
257 {
258  path.Set("Presets");
259 }
260 
261 EResourceLocation LocateResource(const char* name, const char* type, WDL_String& result, const char*, void*, const char*)
262 {
263  if (CStringHasContents(name))
264  {
265  WDL_String plusSlash;
266  WDL_String path(name);
267  const char* file = path.get_filepart();
268 
269  bool foundResource = false;
270 
271  //TODO: FindResource is not sufficient here
272 
273  if(strcmp(type, "png") == 0) { //TODO: lowercase/uppercase png
274  plusSlash.SetFormatted(strlen("/resources/img/") + strlen(file) + 1, "/resources/img/%s", file);
275  foundResource = emscripten::val::global("Module")["preloadedImages"].call<bool>("hasOwnProperty", std::string(plusSlash.Get()));
276  }
277  else if(strcmp(type, "ttf") == 0) { //TODO: lowercase/uppercase ttf
278  plusSlash.SetFormatted(strlen("/resources/fonts/") + strlen(file) + 1, "/resources/fonts/%s", file);
279  foundResource = true; // TODO: check ttf
280  }
281  else if(strcmp(type, "svg") == 0) { //TODO: lowercase/uppercase svg
282  plusSlash.SetFormatted(strlen("/resources/img/") + strlen(file) + 1, "/resources/img/%s", file);
283  foundResource = true; // TODO: check svg
284  }
285 
286  if(foundResource)
287  {
288  result.Set(plusSlash.Get());
289  return EResourceLocation::kAbsolutePath;
290  }
291  }
292  return EResourceLocation::kNotFound;
293 }
294 
295 bool AppIsSandboxed()
296 {
297  return true;
298 }
299 
300 #endif
301 
302 END_IPLUG_NAMESPACE
bool AppIsSandboxed()
const void * LoadWinResource(const char *resID, const char *type, int &sizeInBytes, void *pHInstance)
Load a resource from the binary (windows only).
Include to get consistently named preprocessor macros for different platforms and logging functionali...
Common paths useful for plug-ins.
void BundleResourcePath(WDL_String &path, PluginIDType pExtra=0)
Get the path to the plug-in bundle resource path.
void SandboxSafeAppSupportPath(WDL_String &path, const char *appGroupID="")
void AppSupportPath(WDL_String &path, bool isSystem=false)
IPlug Constant definitions, Types, magic numbers.
void UserHomePath(WDL_String &path)
EResourceLocation LocateResource(const char *fileNameOrResID, const char *type, WDL_String &result, const char *bundleID, void *pHInstance, const char *sharedResourcesSubPath)
Find the absolute path of a resource based on it&#39;s file name (e.g.
void INIPath(WDL_String &path, const char *pluginName)
Get the path to the folder where the App&#39;s settings.ini file is stored.
void VST3PresetsPath(WDL_String &path, const char *mfrName, const char *pluginName, bool isSystem=true)
void HostPath(WDL_String &path, const char *bundleID=0)
Get the path to the host binary.
void PluginPath(WDL_String &path, PluginIDType pExtra)
Get the path to the plug-in binary.
void DesktopPath(WDL_String &path)