Fix a tiny memory-leak when calling vfork
[ardour.git] / libs / ardour / search_paths.cc
1 /*
2     Copyright (C) 2011 Tim Mayberry
3     Copyright (C) 2013 Paul Davis
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <glib.h>
22 #include <glibmm.h>
23 #include <string.h>
24
25 #include "pbd/pathexpand.h"
26
27 #include "ardour/search_paths.h"
28 #include "ardour/directory_names.h"
29 #include "ardour/filesystem_paths.h"
30
31 #ifdef PLATFORM_WINDOWS
32 #include <windows.h>
33 #include <shlobj.h> // CSIDL_*
34 #include "pbd/windows_special_dirs.h"
35 #endif
36
37 namespace {
38         const char * const backend_env_variable_name = "ARDOUR_BACKEND_PATH";
39         const char * const surfaces_env_variable_name = "ARDOUR_SURFACES_PATH";
40         const char * const export_env_variable_name = "ARDOUR_EXPORT_FORMATS_PATH";
41         const char * const theme_env_variable_name = "ARDOUR_THEMES_PATH";
42         const char * const ladspa_env_variable_name = "LADSPA_PATH";
43         const char * const midi_patch_env_variable_name = "ARDOUR_MIDI_PATCH_PATH";
44         const char * const panner_env_variable_name = "ARDOUR_PANNER_PATH";
45 } // anonymous
46
47 using namespace PBD;
48
49 namespace ARDOUR {
50
51 Searchpath
52 backend_search_path ()
53 {
54         Searchpath spath(user_config_directory ());
55         spath += ardour_dll_directory ();
56         spath.add_subdirectory_to_paths(backend_dir_name);
57
58         spath += Searchpath(Glib::getenv(backend_env_variable_name));
59         return spath;
60 }
61
62 Searchpath
63 control_protocol_search_path ()
64 {
65         Searchpath spath(user_config_directory ());
66         spath += ardour_dll_directory ();
67         spath.add_subdirectory_to_paths (surfaces_dir_name);
68
69         spath += Searchpath(Glib::getenv(surfaces_env_variable_name));
70         return spath;
71 }
72
73 Searchpath
74 theme_search_path ()
75 {
76         Searchpath spath (ardour_data_search_path ());
77         spath.add_subdirectory_to_paths (theme_dir_name);
78
79         spath += Searchpath(Glib::getenv(theme_env_variable_name));
80         return spath;
81 }
82
83 Searchpath
84 export_formats_search_path ()
85 {
86         Searchpath spath (ardour_data_search_path());
87         spath.add_subdirectory_to_paths (export_formats_dir_name);
88
89         bool export_formats_path_defined = false;
90         Searchpath spath_env (Glib::getenv(export_env_variable_name, export_formats_path_defined));
91
92         if (export_formats_path_defined) {
93                 spath += spath_env;
94         }
95
96         return spath;
97 }
98
99 Searchpath
100 ladspa_search_path ()
101 {
102         Searchpath spath_env (Glib::getenv(ladspa_env_variable_name));
103
104         Searchpath spath (user_config_directory ());
105
106         spath += ardour_dll_directory ();
107         spath.add_subdirectory_to_paths (ladspa_dir_name);
108
109 #ifndef PLATFORM_WINDOWS
110         spath.push_back ("/usr/local/lib64/ladspa");
111         spath.push_back ("/usr/local/lib/ladspa");
112         spath.push_back ("/usr/lib64/ladspa");
113         spath.push_back ("/usr/lib/ladspa");
114 #endif
115
116 #ifdef __APPLE__
117         spath.push_back (path_expand ("~/Library/Audio/Plug-Ins/LADSPA"));
118         spath.push_back ("/Library/Audio/Plug-Ins/LADSPA");
119 #endif
120
121         return spath_env + spath;
122 }
123
124 Searchpath
125 lv2_bundled_search_path ()
126 {
127         Searchpath spath( ardour_dll_directory () );
128         spath.add_subdirectory_to_paths ("LV2");
129
130         return spath;
131 }
132
133 Searchpath
134 midi_patch_search_path ()
135 {
136         Searchpath spath (ardour_data_search_path());
137         spath.add_subdirectory_to_paths(midi_patch_dir_name);
138
139         bool midi_patch_path_defined = false;
140         Searchpath spath_env (Glib::getenv(midi_patch_env_variable_name, midi_patch_path_defined));
141
142         if (midi_patch_path_defined) {
143                 spath += spath_env;
144         }
145
146         return spath;
147 }
148
149 Searchpath
150 panner_search_path ()
151 {
152         Searchpath spath(user_config_directory ());
153
154         spath += ardour_dll_directory ();
155         spath.add_subdirectory_to_paths(panner_dir_name);
156         spath += Searchpath(Glib::getenv(panner_env_variable_name));
157
158         return spath;
159 }
160
161 Searchpath
162 template_search_path ()
163 {
164         Searchpath spath (ardour_data_search_path());
165         spath.add_subdirectory_to_paths(templates_dir_name);
166         return spath;
167 }
168
169 Searchpath
170 plugin_metadata_search_path ()
171 {
172         Searchpath spath (ardour_data_search_path());
173         spath.add_subdirectory_to_paths(plugin_metadata_dir_name);
174         return spath;
175 }
176
177 Searchpath
178 route_template_search_path ()
179 {
180         Searchpath spath (ardour_data_search_path());
181         spath.add_subdirectory_to_paths(route_templates_dir_name);
182         return spath;
183 }
184
185 Searchpath
186 lua_search_path ()
187 {
188         Searchpath spath (ardour_data_search_path());
189         spath.add_subdirectory_to_paths(lua_dir_name);
190
191         return spath;
192 }
193
194 #ifdef PLATFORM_WINDOWS
195
196 const char*
197 vst_search_path ()
198 {
199         DWORD dwType = REG_SZ;
200         HKEY hKey;
201         DWORD dwSize = PATH_MAX;
202         char* p = 0;
203         char* user_home = 0;
204         char tmp[PATH_MAX+1];
205
206         if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_CURRENT_USER, "Software\\VST", 0, KEY_READ, &hKey)) {
207                 // Look for the user's VST Registry entry
208                 if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize))
209                         p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), NULL);
210
211                 RegCloseKey (hKey);
212         }
213
214         if (p == 0) {
215                 if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Software\\VST", 0, KEY_READ, &hKey))
216                 {
217                         // Look for a global VST Registry entry
218                         if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize))
219                                 p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), NULL);
220
221                         RegCloseKey (hKey);
222                 }
223         }
224
225         if (p == 0) {
226 #if ( (defined __i386__) || (defined _M_IX86) )
227                 char *pVSTx86 = 0;
228                 std::string pProgFilesX86 = PBD::get_win_special_folder_path (CSIDL_PROGRAM_FILESX86);
229
230                 if (!pProgFilesX86.empty()) {
231                         // Look for a VST folder under C:\Program Files (x86)
232                         if ((pVSTx86 = g_build_filename (pProgFilesX86.c_str(), "Steinberg", "VSTPlugins", NULL)))
233                         {
234                                 if (Glib::file_test (pVSTx86, Glib::FILE_TEST_EXISTS))
235                                         if (Glib::file_test (pVSTx86, Glib::FILE_TEST_IS_DIR))
236                                                 p = g_build_filename (pVSTx86, NULL);
237
238                                 g_free (pVSTx86);
239                         }
240                 }
241 #else
242                 // Look for a VST folder under C:\Program Files
243                 char *pVST = 0;
244                 std::string pProgFiles = PBD::get_win_special_folder_path (CSIDL_PROGRAM_FILES);
245
246                 if (!pProgFiles.empty()) {
247                         if ((pVST = g_build_filename (pProgFiles.c_str(), "Steinberg", "VSTPlugins", NULL))) {
248                                 if (Glib::file_test (pVST, Glib::FILE_TEST_EXISTS))
249                                         if (Glib::file_test (pVST, Glib::FILE_TEST_IS_DIR))
250                                                 p = g_build_filename (pVST, NULL);
251
252                                 g_free (pVST);
253                         }
254                 }
255 #endif
256         }
257
258         if (p == 0) {
259                 // If all else failed, assume the plugins are under "My Documents"
260                 user_home = (char*) g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
261                 if (user_home) {
262                         p = g_build_filename (user_home, "Plugins", "VST", NULL);
263                 } else {
264                         user_home = g_build_filename(g_get_home_dir(), "My Documents", NULL);
265                         if (user_home)
266                                 p = g_build_filename (user_home, "Plugins", "VST", NULL);
267                 }
268         } else {
269                 // Concatenate the registry path with the user's personal path
270                 user_home = (char*) g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
271
272                 if (user_home) {
273                         p = g_build_path (";", p, g_build_filename(user_home, "Plugins", "VST", NULL), NULL);
274                 } else {
275                         user_home = g_build_filename(g_get_home_dir(), "My Documents", NULL);
276
277                         if (user_home) {
278                                 p = g_build_path (";", p, g_build_filename (user_home, "Plugins", "VST", NULL), NULL);
279                         }
280                 }
281         }
282
283         return p;
284 }
285
286 #else
287
288 /* Unix-like. Probably require some OS X specific breakdown if we ever add VST
289  * support on that platform.
290  */
291
292 const char *
293 vst_search_path ()
294 {
295         return "/usr/local/lib/vst:/usr/lib/vst";
296 }
297
298 #endif // PLATFORM_WINDOWS
299
300 } // namespace ARDOUR