c4b9b9a8976fa0e15103ee8545e28c126bf5aa4a
[ardour.git] / gtk2_ardour / main.cc
1 /*
2     Copyright (C) 2001-2007 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 <cstdlib>
21 #include <signal.h>
22
23 #include <sigc++/bind.h>
24 #include <gtkmm/settings.h>
25 #include <glibmm/ustring.h>
26
27 #include <pbd/error.h>
28 #include <pbd/textreceiver.h>
29 #include <pbd/failed_constructor.h>
30 #include <pbd/pthread_utils.h>
31
32 #include <jack/jack.h>
33
34 #include <ardour/version.h>
35 #include <ardour/ardour.h>
36 #include <ardour/audioengine.h>
37
38 #include <gtkmm/main.h>
39 #include <gtkmm2ext/popup.h>
40 #include <gtkmm2ext/utils.h>
41
42 #include "svn_revision.h"
43 #include "version.h"
44 #include "ardour_ui.h"
45 #include "opts.h"
46 #include "enums.h"
47
48 #include "i18n.h"
49
50 using namespace Gtk;
51 using namespace ARDOUR_COMMAND_LINE;
52 using namespace ARDOUR;
53 using namespace PBD;
54 using namespace sigc;
55
56 TextReceiver text_receiver ("ardour");
57
58 extern int curvetest (string);
59
60 static ARDOUR_UI  *ui = 0;
61 static const char* localedir = LOCALEDIR;
62
63 #ifdef __APPLE__
64
65 #include <mach-o/dyld.h>
66 #include <sys/param.h>
67 #include <fstream>
68
69 void
70 fixup_bundle_environment ()
71 {
72         if (!getenv ("ARDOUR_BUNDLED")) {
73                 return;
74         }
75
76         char execpath[MAXPATHLEN+1];
77         uint32_t pathsz = sizeof (execpath);
78
79         _NSGetExecutablePath (execpath, &pathsz);
80
81         Glib::ustring exec_path (execpath);
82         Glib::ustring dir_path = Glib::path_get_dirname (exec_path);
83         Glib::ustring path;
84         const char *cstr = getenv ("PATH");
85
86         /* ensure that we find any bundled executables (e.g. JACK),
87            and find them before any instances of the same name
88            elsewhere in PATH
89         */
90
91         path = dir_path;
92         if (cstr) {
93                 path += ':';
94                 path += cstr;
95         }
96         setenv ("PATH", path.c_str(), 1);
97
98         path = dir_path;
99         path += "/../Resources";
100         path += dir_path;
101         path += "/../Resources/Surfaces";
102         path += dir_path;
103         path += "/../Resources/Panners";
104
105         setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
106
107         path = dir_path;
108         path += "/../Resources/icons:";
109         path += dir_path;
110         path += "/../Resources/pixmaps:";
111         path += dir_path;
112         path += "/../Resources/share:";
113         path += dir_path;
114         path += "/../Resources";
115
116         setenv ("ARDOUR_PATH", path.c_str(), 1);
117         setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
118         setenv ("ARDOUR_DATA_PATH", path.c_str(), 1);
119
120         cstr = getenv ("LADSPA_PATH");
121         if (cstr) {
122                 path = cstr;
123                 path += ':';
124         } else {
125                 path = "";
126         }
127         path += dir_path;
128         path += "/../Plugins";
129         
130         setenv ("LADSPA_PATH", path.c_str(), 1);
131
132         cstr = getenv ("VAMP_PATH");
133         if (cstr) {
134                 path = cstr;
135                 path += ':';
136         } else {
137                 path = "";
138         }
139         path += dir_path;
140         path += "/../Frameworks";
141         
142         setenv ("VAMP_PATH", path.c_str(), 1);
143
144         cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
145         if (cstr) {
146                 path = cstr;
147                 path += ':';
148         } else {
149                 path = "";
150         }
151         path += dir_path;
152         path += "/../Surfaces";
153         
154         setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
155
156         cstr = getenv ("LV2_PATH");
157         if (cstr) {
158                 path = cstr;
159                 path += ':';
160         } else {
161                 path = "";
162         }
163         path += dir_path;
164         path += "/../Plugins";
165         
166         setenv ("LV2_PATH", path.c_str(), 1);
167
168         path = dir_path;
169         path += "/../Frameworks/clearlooks";
170
171         setenv ("GTK_PATH", path.c_str(), 1);
172
173         path = dir_path;
174         path += "/../Resources/locale";
175         
176         localedir = strdup (path.c_str());
177
178         /* write a pango.rc file and tell pango to use it. we'd love
179            to put this into the Ardour.app bundle and leave it there,
180            but the user may not have write permission. so ... 
181
182            we also have to make sure that the user ardour directory
183            actually exists ...
184         */
185
186         if (g_mkdir_with_parents (ARDOUR::get_user_ardour_path().c_str(), 0755) < 0) {
187                 error << string_compose (_("cannot create user ardour folder %1 (%2)"), ARDOUR::get_user_ardour_path(), strerror (errno))
188                       << endmsg;
189         } else {
190
191                 path = Glib::build_filename (ARDOUR::get_user_ardour_path(), "pango.rc");
192                 
193                 std::ofstream pangorc (path.c_str());
194                 if (!pangorc) {
195                         error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
196                 } else {
197                         pangorc << "[Pango]\nModuleFiles=";
198                         Glib::ustring mpath;
199
200                         mpath = dir_path;
201                         mpath += "/../Resources/pango.modules";
202
203                         pangorc << mpath << endl;
204                         
205                         pangorc.close ();
206                         setenv ("PANGO_RC_FILE", path.c_str(), 1);
207                 }
208         }
209
210         // gettext charset aliases
211
212         setenv ("CHARSETALIASDIR", path.c_str(), 1);
213
214         // font config
215         
216         path = dir_path;
217         path += "/../Resources/fonts.conf";
218
219         setenv ("FONTCONFIG_FILE", path.c_str(), 1);
220
221         // GDK Pixbuf loader module file
222
223         path = dir_path;
224         path += "/../Resources/gdk-pixbuf.loaders";
225
226         setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
227         cerr << "Set GDK_PIXBUF_MODULE_FILE to " << path << endl;
228
229         if (getenv ("ARDOUR_WITH_JACK")) {
230                 // JACK driver dir
231                 
232                 path = dir_path;
233                 path += "/../Frameworks";
234                 
235                 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
236         }
237 }
238
239 #endif
240
241 static void
242 sigpipe_handler (int sig)
243 {
244         cerr << _("SIGPIPE received - JACK has probably died") << endl;
245 }
246
247 #ifdef VST_SUPPORT
248 /* this is called from the entry point of a wine-compiled
249    executable that is linked against gtk2_ardour built
250    as a shared library.
251 */
252 extern "C" {
253 int ardour_main (int argc, char *argv[])
254 #else
255 int main (int argc, char* argv[])
256 #endif
257 {
258         vector<Glib::ustring> null_file_list;
259         
260 #ifdef __APPLE__
261         fixup_bundle_environment ();
262 #endif
263
264         Glib::thread_init();
265         gtk_set_locale ();
266
267         (void) bindtextdomain (PACKAGE, localedir);
268         /* our i18n translations are all in UTF-8, so make sure
269            that even if the user locale doesn't specify UTF-8,
270            we use that when handling them.
271         */
272         (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
273         (void) textdomain (PACKAGE);
274
275         pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
276
277         // catch error message system signals ();
278
279         text_receiver.listen_to (error);
280         text_receiver.listen_to (info);
281         text_receiver.listen_to (fatal);
282         text_receiver.listen_to (warning);
283
284         if (parse_opts (argc, argv)) {
285                 exit (1);
286         }
287
288         if (curvetest_file) {
289                 return curvetest (curvetest_file);
290         }
291         
292         cout << _("Ardour/GTK ") 
293              << VERSIONSTRING
294              << _("\n   (built using ")
295              << ardour_svn_revision
296 #ifdef __GNUC__
297              << _(" and GCC version ") << __VERSION__ 
298 #endif
299              << ')'
300              << endl;
301         
302         if (just_version) {
303                 exit (0);
304         }
305
306         if (no_splash) {
307                 cerr << _("Copyright (C) 1999-2008 Paul Davis") << endl
308                      << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
309                      << endl
310                      << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
311                      << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
312                      << _("This is free software, and you are welcome to redistribute it ") << endl
313                      << _("under certain conditions; see the source for copying conditions.")
314                      << endl;
315         }
316
317         /* some GUI objects need this */
318
319         PBD::ID::init ();
320
321         if (::signal (SIGPIPE, sigpipe_handler)) {
322                 cerr << _("Cannot install SIGPIPE error handler") << endl;
323         }
324
325         try { 
326                 ui = new ARDOUR_UI (&argc, &argv);
327         } catch (failed_constructor& err) {
328                 error << _("could not create ARDOUR GUI") << endmsg;
329                 exit (1);
330         }
331
332         ui->run (text_receiver);
333         ui = 0;
334
335         ARDOUR::cleanup ();
336         pthread_cancel_all ();
337         return 0;
338 }
339 #ifdef VST_SUPPORT
340 } // end of extern C block
341 #endif
342