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