move fixup_bundle_environment() code into per-platform files
[ardour.git] / gtk2_ardour / bundle_env_cocoa.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 #include <Carbon/Carbon.h>
45 #include <mach-o/dyld.h>
46 #include <sys/param.h>
47
48 using namespace PBD;
49 using namespace ARDOUR;
50 using namespace std;
51
52 extern void set_language_preference (); // cocoacarbon.mm
53
54 void
55 fixup_bundle_environment (int, char* [], const char** localedir)
56 {
57         if (!g_getenv ("ARDOUR_BUNDLED")) {
58                 return;
59         }
60
61         EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
62
63         set_language_preference ();
64
65         char execpath[MAXPATHLEN+1];
66         uint32_t pathsz = sizeof (execpath);
67
68         _NSGetExecutablePath (execpath, &pathsz);
69
70         std::string path;
71         std::string exec_dir = Glib::path_get_dirname (execpath);
72         std::string bundle_dir;
73         std::string userconfigdir = user_config_directory();
74
75         bundle_dir = Glib::path_get_dirname (exec_dir);
76
77 #ifdef ENABLE_NLS
78         if (!ARDOUR::translations_are_enabled ()) {
79                 (*localedir) = "/this/cannot/exist";
80         } else {
81                 /* force localedir into the bundle */
82                 
83                 vector<string> lpath;
84                 lpath.push_back (bundle_dir);
85                 lpath.push_back ("Resources");
86                 lpath.push_back ("locale");
87                 (*localedir) = strdup (Glib::build_filename (lpath).c_str());
88         }
89 #endif
90                 
91         export_search_path (bundle_dir, "ARDOUR_DLL_PATH", "/lib");
92
93         /* inside an OS X .app bundle, there is no difference
94            between DATA and CONFIG locations, since OS X doesn't
95            attempt to do anything to expose the notion of
96            machine-independent shared data.
97         */
98
99         export_search_path (bundle_dir, "ARDOUR_DATA_PATH", "/Resources");
100         export_search_path (bundle_dir, "ARDOUR_CONFIG_PATH", "/Resources");
101         export_search_path (bundle_dir, "ARDOUR_INSTANT_XML_PATH", "/Resources");
102         export_search_path (bundle_dir, "LADSPA_PATH", "/Plugins");
103         export_search_path (bundle_dir, "VAMP_PATH", "/lib");
104         export_search_path (bundle_dir, "GTK_PATH", "/lib/gtkengines");
105
106         g_setenv ("SUIL_MODULE_DIR", (bundle_dir + "/lib").c_str(), 1);
107         g_setenv ("PATH", (bundle_dir + "/MacOS:" + std::string(g_getenv ("PATH"))).c_str(), 1);
108
109         /* unset GTK_RC_FILES so that we only load the RC files that we define
110          */
111
112         g_unsetenv ("GTK_RC_FILES");
113
114         /* write a pango.rc file and tell pango to use it. we'd love
115            to put this into the PROGRAM_NAME.app bundle and leave it there,
116            but the user may not have write permission. so ...
117
118            we also have to make sure that the user ardour directory
119            actually exists ...
120         */
121
122         if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
123                 error << string_compose (_("cannot create user %3 folder %1 (%2)"), userconfigdir, strerror (errno), PROGRAM_NAME)
124                       << endmsg;
125         } else {
126                 
127                 path = Glib::build_filename (userconfigdir, "pango.rc");
128                 std::ofstream pangorc (path.c_str());
129                 if (!pangorc) {
130                         error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
131                 } else {
132                         pangorc << "[Pango]\nModuleFiles="
133                                 << Glib::build_filename (bundle_dir, "Resources/pango.modules") 
134                                 << endl;
135                         pangorc.close ();
136                         
137                         g_setenv ("PANGO_RC_FILE", path.c_str(), 1);
138                 }
139         }
140         
141         g_setenv ("CHARSETALIASDIR", bundle_dir.c_str(), 1);
142         g_setenv ("FONTCONFIG_FILE", Glib::build_filename (bundle_dir, "Resources/fonts.conf").c_str(), 1);
143         g_setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (bundle_dir, "Resources/gdk-pixbuf.loaders").c_str(), 1);
144 }
145
146 void load_custom_fonts() 
147 {
148         /* this code will only compile on OS X 10.6 and above, and we currently do not
149          * need it for earlier versions since we fall back on a non-monospace,
150          * non-custom font.
151          */
152
153 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
154         std::string ardour_mono_file;
155
156         if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) {
157                 cerr << _("Cannot find ArdourMono TrueType font") << endl;
158         }
159
160         CFStringRef ttf;
161         CFURLRef fontURL;
162         CFErrorRef error;
163         ttf = CFStringCreateWithBytes(
164                         kCFAllocatorDefault, (UInt8*) ardour_mono_file.c_str(),
165                         ardour_mono_file.length(),
166                         kCFStringEncodingUTF8, FALSE);
167         fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, ttf, kCFURLPOSIXPathStyle, TRUE);
168         if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error) != true) {
169                 cerr << _("Cannot load ArdourMono TrueType font.") << endl;
170         }
171 #endif
172 }