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