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