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