merge with master and fix 4 conflicts by hand
[ardour.git] / gtk2_ardour / bundle_env_linux.cc
1 /*
2     Copyright (C) 2001-2012 Paul Davis
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
20 #include <fstream>
21 #include <string>
22 #include <vector>
23 #include <cerrno>
24 #include <cstring>
25
26 #include <glib.h>
27 #include <glibmm/fileutils.h>
28 #include <glibmm/miscutils.h>
29
30 #include <fontconfig/fontconfig.h>
31
32 #include "ardour/ardour.h"
33 #include "ardour/filesystem_paths.h"
34
35 #include "pbd/epa.h"
36 #include "pbd/search_path.h"
37 #include "pbd/pathexpand.h"
38 #include "pbd/file_utils.h"
39
40 #include "bundle_env.h"
41
42 #include "i18n.h"
43
44 using namespace PBD;
45 using namespace ARDOUR;
46 using namespace std;
47
48 void
49 fixup_bundle_environment (int /*argc*/, char* argv[], const char** localedir)
50 {
51         /* THIS IS FOR LINUX - its just about the only place where its
52          * acceptable to build paths directly using '/'.
53          */
54
55         if (!g_getenv ("ARDOUR_BUNDLED")) {
56                 return;
57         }
58
59         EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
60
61         std::string path;
62         std::string dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
63         std::string userconfigdir = user_config_directory();
64
65 #ifdef ENABLE_NLS
66         if (!ARDOUR::translations_are_enabled ()) {
67                 (*localedir) = "/this/cannot/exist";
68         } else {
69                 /* force localedir into the bundle */
70                 vector<string> lpath;
71                 lpath.push_back (dir_path);
72                 lpath.push_back ("share");
73                 lpath.push_back ("locale");
74                 (*localedir) = canonical_path (Glib::build_filename (lpath)).c_str();
75         }
76 #endif
77
78         /* note that this function is POSIX/Linux specific, so using / as
79            a dir separator in this context is just fine.
80         */
81
82         export_search_path (dir_path, "ARDOUR_DLL_PATH", "/lib");
83         export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
84         export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
85         export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
86         export_search_path (dir_path, "LADSPA_PATH", "/plugins");
87         export_search_path (dir_path, "VAMP_PATH", "/lib");
88         export_search_path (dir_path, "GTK_PATH", "/lib/gtkengines");
89
90         g_setenv ("SUIL_MODULE_DIR", (dir_path + "/lib").c_str(), 1);
91         g_setenv ("PATH", (dir_path + "/bin:" + std::string(g_getenv ("PATH"))).c_str(), 1);
92
93         /* unset GTK_RC_FILES so that we only load the RC files that we define
94          */
95
96         g_unsetenv ("GTK_RC_FILES");
97
98         /* Tell fontconfig where to find fonts.conf. Use the system version
99            if it exists, otherwise use the stuff we included in the bundle
100         */
101
102         if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
103                 g_setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
104                 g_setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
105         } else {
106                 error << _("No fontconfig file found on your system. Things may looked very odd or ugly") << endmsg;
107         }
108
109         /* write a pango.rc file and tell pango to use it. we'd love
110            to put this into the Ardour.app bundle and leave it there,
111            but the user may not have write permission. so ...
112
113            we also have to make sure that the user ardour directory
114            actually exists ...
115         */
116
117         if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
118                 error << string_compose (_("cannot create user %3 folder %1 (%2)"), userconfigdir, strerror (errno), PROGRAM_NAME)
119                       << endmsg;
120         } else {
121                 
122                 path = Glib::build_filename (userconfigdir, "pango.rc");
123                 std::ofstream pangorc (path.c_str());
124                 if (!pangorc) {
125                         error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
126                 } else {
127                         pangorc << "[Pango]\nModuleFiles="
128                                 << Glib::build_filename (userconfigdir, "pango.modules")
129                                 << endl;
130                         pangorc.close ();
131                 }
132                 
133                 g_setenv ("PANGO_RC_FILE", path.c_str(), 1);
134                 
135                 /* similar for GDK pixbuf loaders, but there's no RC file required
136                    to specify where it lives.
137                 */
138                 
139                 g_setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders").c_str(), 1);
140         }
141
142         /* this doesn't do much but setting it should prevent various parts of the GTK/GNU stack
143            from looking outside the bundle to find the charset.alias file.
144         */
145         g_setenv ("CHARSETALIASDIR", dir_path.c_str(), 1);
146
147 }
148
149 void 
150 load_custom_fonts() 
151 {
152         std::string ardour_mono_file;
153
154         if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) {
155                 cerr << _("Cannot find ArdourMono TrueType font") << endl;
156         }
157
158         FcConfig *config = FcInitLoadConfigAndFonts();
159         FcBool ret = FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(ardour_mono_file.c_str()));
160
161         if (ret == FcFalse) {
162                 cerr << _("Cannot load ArdourMono TrueType font.") << endl;
163         }
164
165         ret = FcConfigSetCurrent(config);
166
167         if (ret == FcFalse) {
168                 cerr << _("Failed to set fontconfig configuration.") << endl;
169         }
170 }