ardour
filesystem_paths.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 Tim Mayberry
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 #include <cstdlib>
20 #include <iostream>
21 
22 #include "pbd/compose.h"
23 #include "pbd/convert.h"
24 #include "pbd/error.h"
25 
26 #include <glibmm/miscutils.h>
27 #include <glibmm/fileutils.h>
28 
29 #include "ardour/directory_names.h"
31 
32 #include "i18n.h"
33 
34 #ifdef PLATFORM_WINDOWS
35 #include "shlobj.h"
37 #endif
38 
39 using namespace PBD;
40 
41 namespace ARDOUR {
42 
43 using std::string;
44 
45 static std::string
46 user_config_directory_name (int version = -1)
47 {
48  if (version < 0) {
49  version = atoi (X_(PROGRAM_VERSION));
50  }
51 
52  const string config_dir_name = string_compose ("%1%2", X_(PROGRAM_NAME), version);
53 
54 #if defined (__APPLE__) || defined (PLATFORM_WINDOWS)
55  return config_dir_name;
56 #else
57  return downcase (config_dir_name);
58 #endif
59 }
60 
61 std::string
62 user_config_directory (int version)
63 {
64  std::string p;
65 
66 #ifdef __APPLE__
67 
68  p = Glib::build_filename (Glib::get_home_dir(), "Library/Preferences");
69 
70 #else
71 
72  const char* c = 0;
73  /* adopt freedesktop standards, and put .ardour3 into $XDG_CONFIG_HOME or ~/.config */
74  if ((c = getenv ("XDG_CONFIG_HOME")) != 0) {
75  p = c;
76  } else {
77 
78 #ifdef PLATFORM_WINDOWS
79  // Not technically the home dir (since it needs to be a writable folder)
80  const string home_dir = Glib::get_user_config_dir();
81 #else
82  const string home_dir = Glib::get_home_dir();
83 #endif
84  if (home_dir.empty ()) {
85  error << "Unable to determine home directory" << endmsg;
86  exit (1);
87  }
88  p = home_dir;
89 
90 #ifndef PLATFORM_WINDOWS
91  p = Glib::build_filename (p, ".config");
92 #endif
93 
94  }
95 #endif // end not __APPLE__
96 
97  p = Glib::build_filename (p, user_config_directory_name (version));
98 
99  if (version < 0) {
100  /* Only create the user config dir if the version was negative,
101  meaning "for the current version.
102  */
103  if (!Glib::file_test (p, Glib::FILE_TEST_EXISTS)) {
104  if (g_mkdir_with_parents (p.c_str(), 0755)) {
105  error << string_compose (_("Cannot create Configuration directory %1 - cannot run"),
106  p) << endmsg;
107  exit (1);
108  }
109  } else if (!Glib::file_test (p, Glib::FILE_TEST_IS_DIR)) {
110  error << string_compose (_("Configuration directory %1 already exists and is not a directory/folder - cannot run"),
111  p) << endmsg;
112  exit (1);
113  }
114  }
115 
116  return p;
117 }
118 
119 std::string
121 {
122  static std::string p;
123 
124  if (!p.empty()) return p;
125 
126 #ifdef __APPLE__
127  p = Glib::build_filename (Glib::get_home_dir(), "Library/Caches");
128 #else
129  const char* c = 0;
130 
131  /* adopt freedesktop standards, and put .ardour3 into $XDG_CACHE_HOME
132  * defaulting to or ~/.config
133  */
134  if ((c = getenv ("XDG_CACHE_HOME")) != 0) {
135  p = c;
136  } else {
137 
138 #ifdef PLATFORM_WINDOWS
139  // Not technically the home dir (since it needs to be a writable folder)
140  const string home_dir = Glib::get_user_data_dir();
141 #else
142  const string home_dir = Glib::get_home_dir();
143 #endif
144  if (home_dir.empty ()) {
145  error << "Unable to determine home directory" << endmsg;
146  exit (1);
147  }
148  p = home_dir;
149 
150 #ifndef PLATFORM_WINDOWS
151  p = Glib::build_filename (p, ".cache");
152 #endif
153 
154  }
155 #endif // end not __APPLE__
156 
157  p = Glib::build_filename (p, user_config_directory_name ());
158 
159 #ifdef PLATFORM_WINDOWS
160  /* On Windows Glib::get_user_data_dir is the folder to use for local
161  * (as opposed to roaming) application data.
162  * See documentation for CSIDL_LOCAL_APPDATA.
163  * Glib::get_user_data_dir() == GLib::get_user_config_dir()
164  * so we add an extra subdir *below* the config dir.
165  */
166  p = Glib::build_filename (p, "cache");
167 #endif
168 
169  if (!Glib::file_test (p, Glib::FILE_TEST_EXISTS)) {
170  if (g_mkdir_with_parents (p.c_str(), 0755)) {
171  error << string_compose (_("Cannot create cache directory %1 - cannot run"),
172  p) << endmsg;
173  exit (1);
174  }
175  } else if (!Glib::file_test (p, Glib::FILE_TEST_IS_DIR)) {
176  error << string_compose (_("Cache directory %1 already exists and is not a directory/folder - cannot run"),
177  p) << endmsg;
178  exit (1);
179  }
180 
181  return p;
182 }
183 
184 std::string
186 {
187 #ifdef PLATFORM_WINDOWS
188  std::string dll_dir_path(g_win32_get_package_installation_directory_of_module(NULL));
189  dll_dir_path = Glib::build_filename (dll_dir_path, "lib");
190  return Glib::build_filename (dll_dir_path, LIBARDOUR);
191 #else
192  std::string s = Glib::getenv("ARDOUR_DLL_PATH");
193  if (s.empty()) {
194  std::cerr << _("ARDOUR_DLL_PATH not set in environment - exiting\n");
195  ::exit (1);
196  }
197  return s;
198 #endif
199 }
200 
201 #ifdef PLATFORM_WINDOWS
203 windows_search_path ()
204 {
205  std::string dll_dir_path(g_win32_get_package_installation_directory_of_module(NULL));
206  dll_dir_path = Glib::build_filename (dll_dir_path, "share");
207  return Glib::build_filename (dll_dir_path, LIBARDOUR);
208 }
209 #endif
210 
213 {
214  static Searchpath search_path;
215 
216  if (search_path.empty()) {
217  // Start by adding the user's personal config folder
218  search_path += user_config_directory();
219 #ifdef PLATFORM_WINDOWS
220  // On Windows, add am intermediate configuration folder
221  // (one that's guaranteed to be writable by all users).
222  const gchar* const *all_users_folder = g_get_system_config_dirs();
223  // Despite its slightly odd name, the above returns a single entry which
224  // corresponds to 'All Users' on Windows (according to the documentation)
225 
226  if (all_users_folder) {
227  std::string writable_all_users_path = all_users_folder[0];
228  writable_all_users_path += "\\";
229  writable_all_users_path += PROGRAM_NAME;
230  writable_all_users_path += "\\.config";
231 #ifdef _WIN64
232  writable_all_users_path += "\\win64";
233 #else
234  writable_all_users_path += "\\win32";
235 #endif
236  search_path += writable_all_users_path;
237  }
238 
239  // now add a suitable config path from the bundle
240  search_path += windows_search_path ();
241 #endif
242  // finally, add any paths from ARDOUR_CONFIG_PATH if it exists
243  std::string s = Glib::getenv("ARDOUR_CONFIG_PATH");
244  if (s.empty()) {
245  std::cerr << _("ARDOUR_CONFIG_PATH not set in environment\n");
246  } else {
247  search_path += Searchpath (s);
248  }
249  }
250 
251  return search_path;
252 }
253 
256 {
257  static Searchpath search_path;
258 
259  if (search_path.empty()) {
260  search_path += user_config_directory();
261 #ifdef PLATFORM_WINDOWS
262  search_path += windows_search_path ();
263 #endif
264  std::string s = Glib::getenv("ARDOUR_DATA_PATH");
265  if (s.empty()) {
266  std::cerr << _("ARDOUR_DATA_PATH not set in environment\n");
267  } else {
268  search_path += Searchpath (s);
269  }
270  }
271 
272  return search_path;
273 }
274 
275 string
277 {
278  if (version < 0) {
279  version = atoi (PROGRAM_VERSION);
280  }
281 
282  return Glib::build_filename (user_config_directory (version), string (".a") + to_string (version, std::dec));
283 }
284 
285 
286 } // namespace ARDOUR
std::string to_string(T t, std::ios_base &(*f)(std::ios_base &))
Definition: convert.h:53
int atoi(const string &s)
Definition: convert.cc:140
static std::string user_config_directory_name(int version=-1)
LIBPBD_API Transmitter error
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
string downcase(const string &str)
Definition: convert.cc:58
#define _(Text)
Definition: i18n.h:11
LIBARDOUR_API std::string user_config_directory(int version=-1)
#define X_(Text)
Definition: i18n.h:13
Definition: amp.h:29
LIBARDOUR_API std::string ardour_dll_directory()
LIBARDOUR_API std::string been_here_before_path(int version=-1)
LIBARDOUR_API PBD::Searchpath ardour_config_search_path()
LIBARDOUR_API std::string user_cache_directory()
Definition: debug.h:30
LIBARDOUR_API PBD::Searchpath ardour_data_search_path()
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208