Update ghost note presence when mouse mode is changed. Fixes #3559.
[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 #include <cerrno>
23 #include <fstream>
24
25 #include <sigc++/bind.h>
26 #include <gtkmm/settings.h>
27
28 #include "pbd/error.h"
29 #include "pbd/file_utils.h"
30 #include "pbd/textreceiver.h"
31 #include "pbd/failed_constructor.h"
32 #include "pbd/pthread_utils.h"
33
34 #include <jack/jack.h>
35
36 #include "ardour/svn_revision.h"
37 #include "ardour/version.h"
38 #include "ardour/ardour.h"
39 #include "ardour/audioengine.h"
40 #include "ardour/session_utils.h"
41 #include "ardour/filesystem_paths.h"
42
43 #include <gtkmm/main.h>
44 #include <gtkmm2ext/application.h>
45 #include <gtkmm2ext/popup.h>
46 #include <gtkmm2ext/utils.h>
47
48 #include "version.h"
49 #include "utils.h"
50 #include "ardour_ui.h"
51 #include "opts.h"
52 #include "enums.h"
53
54 #include "i18n.h"
55
56 using namespace std;
57 using namespace Gtk;
58 using namespace ARDOUR_COMMAND_LINE;
59 using namespace ARDOUR;
60 using namespace PBD;
61
62 TextReceiver text_receiver ("ardour");
63
64 extern int curvetest (string);
65
66 static ARDOUR_UI  *ui = 0;
67 static const char* localedir = LOCALEDIR;
68
69 void
70 gui_jack_error ()
71 {
72         MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
73                      false,
74                      Gtk::MESSAGE_INFO,
75                      (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
76 win.set_secondary_text(_("There are several possible reasons:\n\
77 \n\
78 1) JACK is not running.\n\
79 2) JACK is running as another user, perhaps root.\n\
80 3) There is already another client called \"ardour\".\n\
81 \n\
82 Please consider the possibilities, and perhaps (re)start JACK."));
83
84         win.add_button (Stock::QUIT, RESPONSE_CLOSE);
85         win.set_default_response (RESPONSE_CLOSE);
86
87         win.show_all ();
88         win.set_position (Gtk::WIN_POS_CENTER);
89
90         if (!no_splash) {
91                 ui->hide_splash ();
92         }
93
94         /* we just don't care about the result, but we want to block */
95
96         win.run ();
97 }
98
99
100 #ifdef __APPLE__
101
102 #include <mach-o/dyld.h>
103 #include <sys/param.h>
104
105 extern void set_language_preference (); // cocoacarbon.mm
106
107 void
108 fixup_bundle_environment ()
109 {
110         if (!getenv ("ARDOUR_BUNDLED")) {
111                 return;
112         }
113
114         set_language_preference ();
115
116         char execpath[MAXPATHLEN+1];
117         uint32_t pathsz = sizeof (execpath);
118
119         _NSGetExecutablePath (execpath, &pathsz);
120
121         std::string exec_path (execpath);
122         std::string dir_path = Glib::path_get_dirname (exec_path);
123         std::string path;
124         const char *cstr = getenv ("PATH");
125
126         /* ensure that we find any bundled executables (e.g. JACK),
127            and find them before any instances of the same name
128            elsewhere in PATH
129         */
130
131         path = dir_path;
132
133         /* JACK is often in /usr/local/bin and since Info.plist refuses to 
134            set PATH, we have to force this in order to discover a running
135            instance of JACK ...
136         */
137         
138         path += ':';
139         path += "/usr/local/bin";
140
141         if (cstr) {
142                 path += ':';
143                 path += cstr;
144         }
145         setenv ("PATH", path.c_str(), 1);
146
147         path = dir_path;
148         path += "/../Resources";
149         path += dir_path;
150         path += "/../Resources/Surfaces";
151         path += dir_path;
152         path += "/../Resources/Panners";
153
154         setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
155
156         path = user_config_directory().to_string();
157         path += ':';
158         path += dir_path;
159         path += "/../Resources/icons:";
160         path += dir_path;
161         path += "/../Resources/pixmaps:";
162         path += dir_path;
163         path += "/../Resources/share:";
164         path += dir_path;
165         path += "/../Resources";
166
167         setenv ("ARDOUR_PATH", path.c_str(), 1);
168         setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
169         setenv ("ARDOUR_DATA_PATH", path.c_str(), 1);
170
171         path = dir_path;
172         path += "/../Resources";
173         setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
174
175         cstr = getenv ("LADSPA_PATH");
176         if (cstr) {
177                 path = cstr;
178                 path += ':';
179         } else {
180                 path = "";
181         }
182         path += dir_path;
183         path += "/../Plugins";
184
185         setenv ("LADSPA_PATH", path.c_str(), 1);
186
187         cstr = getenv ("VAMP_PATH");
188         if (cstr) {
189                 path = cstr;
190                 path += ':';
191         } else {
192                 path = "";
193         }
194         path += dir_path;
195         path += "/../Frameworks";
196
197         setenv ("VAMP_PATH", path.c_str(), 1);
198
199         cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
200         if (cstr) {
201                 path = cstr;
202                 path += ':';
203         } else {
204                 path = "";
205         }
206         path += dir_path;
207         path += "/../Surfaces";
208
209         setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
210
211         cstr = getenv ("LV2_PATH");
212         if (cstr) {
213                 path = cstr;
214                 path += ':';
215         } else {
216                 path = "";
217         }
218         path += dir_path;
219         path += "/../Plugins";
220
221         setenv ("LV2_PATH", path.c_str(), 1);
222
223         path = dir_path;
224         path += "/../Frameworks/clearlooks";
225
226         setenv ("GTK_PATH", path.c_str(), 1);
227
228         if (!ARDOUR::translations_are_disabled ()) {
229
230                 path = dir_path;
231                 path += "/../Resources/locale";
232                 
233                 localedir = strdup (path.c_str());
234                 setenv ("GTK_LOCALEDIR", localedir, 1);
235         }
236
237         /* write a pango.rc file and tell pango to use it. we'd love
238            to put this into the PROGRAM_NAME.app bundle and leave it there,
239            but the user may not have write permission. so ...
240
241            we also have to make sure that the user ardour directory
242            actually exists ...
243         */
244
245         try {
246                 sys::create_directories (user_config_directory ());
247         }
248         catch (const sys::filesystem_error& ex) {
249                 error << _("Could not create user configuration directory") << endmsg;
250         }
251
252         sys::path pangopath = user_config_directory();
253         pangopath /= "pango.rc";
254         path = pangopath.to_string();
255
256         std::ofstream pangorc (path.c_str());
257         if (!pangorc) {
258                 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
259                 return;
260         } else {
261                 pangorc << "[Pango]\nModuleFiles=";
262
263                 pangopath = dir_path;
264                 pangopath /= "..";
265                 pangopath /= "Resources";
266                 pangopath /= "pango.modules";
267
268                 pangorc << pangopath.to_string() << endl;
269
270                 pangorc.close ();
271
272                 setenv ("PANGO_RC_FILE", path.c_str(), 1);
273         }
274
275         // gettext charset aliases
276
277         setenv ("CHARSETALIASDIR", path.c_str(), 1);
278
279         // font config
280
281         path = dir_path;
282         path += "/../Resources/fonts.conf";
283
284         setenv ("FONTCONFIG_FILE", path.c_str(), 1);
285
286         // GDK Pixbuf loader module file
287
288         path = dir_path;
289         path += "/../Resources/gdk-pixbuf.loaders";
290
291         setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
292
293         if (getenv ("ARDOUR_WITH_JACK")) {
294                 // JACK driver dir
295
296                 path = dir_path;
297                 path += "/../Frameworks";
298
299                 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
300         }
301 }
302
303 #else
304
305 void
306 fixup_bundle_environment (int argc, char* argv[])
307 {
308         if (!getenv ("ARDOUR_BUNDLED")) {
309                 return;
310         }
311         
312         Glib::ustring exec_path = argv[0];
313         Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
314         Glib::ustring path;
315         const char *cstr = getenv ("PATH");
316         Glib::ustring userconfigdir = user_config_directory().to_string();
317
318         /* ensure that we find any bundled executables (e.g. JACK),
319            and find them before any instances of the same name
320            elsewhere in PATH
321         */
322
323         /* note that this function is POSIX/Linux specific, so using / as 
324            a dir separator in this context is just fine.
325         */
326
327         path = dir_path;
328         path += "/etc:";
329         path += dir_path;
330         path += "/lib/surfaces:";
331         path += dir_path;
332         path += "/lib/panners:";
333
334         setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
335
336         path = userconfigdir;
337         path += ':';
338         path += dir_path;
339         path += "/etc/icons:";
340         path += dir_path;
341         path += "/etc/pixmaps:";
342         path += dir_path;
343         path += "/share:";
344         path += dir_path;
345         path += "/etc";
346
347         setenv ("ARDOUR_PATH", path.c_str(), 1);
348         setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
349         setenv ("ARDOUR_DATA_PATH", path.c_str(), 1);
350
351         path = dir_path;
352         path += "/etc";
353         setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
354
355         cstr = getenv ("LADSPA_PATH");
356         if (cstr) {
357                 path = cstr;
358                 path += ':';
359         } else {
360                 path = "";
361         }
362         path += dir_path;
363         path += "/lib/plugins";
364         
365         setenv ("LADSPA_PATH", path.c_str(), 1);
366
367         cstr = getenv ("VAMP_PATH");
368         if (cstr) {
369                 path = cstr;
370                 path += ':';
371         } else {
372                 path = "";
373         }
374         path += dir_path;
375         path += "/lib";
376         
377         setenv ("VAMP_PATH", path.c_str(), 1);
378
379         cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
380         if (cstr) {
381                 path = cstr;
382                 path += ':';
383         } else {
384                 path = "";
385         }
386         path += dir_path;
387         path += "/lib/surfaces";
388         
389         setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
390
391         cstr = getenv ("LV2_PATH");
392         if (cstr) {
393                 path = cstr;
394                 path += ':';
395         } else {
396                 path = "";
397         }
398         path += dir_path;
399         path += "/lib/plugins";
400         
401         setenv ("LV2_PATH", path.c_str(), 1);
402
403         path = dir_path;
404         path += "/lib/clearlooks";
405
406         setenv ("GTK_PATH", path.c_str(), 1);
407
408         if (!ARDOUR::translations_are_disabled ()) {
409                 path = dir_path;
410                 path += "/share/locale";
411                 
412                 localedir = strdup (path.c_str());
413                 setenv ("GTK_LOCALEDIR", localedir, 1);
414         }
415
416         /* write a pango.rc file and tell pango to use it. we'd love
417            to put this into the Ardour.app bundle and leave it there,
418            but the user may not have write permission. so ... 
419
420            we also have to make sure that the user ardour directory
421            actually exists ...
422         */
423
424         if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
425                 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
426                       << endmsg;
427         } else {
428
429                 Glib::ustring mpath;
430
431                 path = Glib::build_filename (userconfigdir, "pango.rc");
432
433                 std::ofstream pangorc (path.c_str());
434                 if (!pangorc) {
435                         error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
436                 } else {
437                         mpath = Glib::build_filename (userconfigdir, "pango.modules");
438                         
439                         pangorc << "[Pango]\nModuleFiles=";
440                         pangorc << mpath << endl;
441                         pangorc.close ();
442                 }
443
444                 setenv ("PANGO_RC_FILE", path.c_str(), 1);
445
446                 /* similar for GDK pixbuf loaders, but there's no RC file required
447                    to specify where it lives.
448                 */
449
450                 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
451                 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
452         }
453 }
454
455 #endif
456
457 static gboolean
458 tell_about_jack_death (void* /* ignored */)
459 {
460         if (AudioEngine::instance()->processed_frames() == 0) {
461                 /* died during startup */
462                 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
463                 msg.set_position (Gtk::WIN_POS_CENTER);
464                 msg.set_secondary_text (string_compose (_(
465 "JACK exited unexpectedly, and without notifying %1.\n\
466 \n\
467 This could be due to misconfiguration or to an error inside JACK.\n\
468 \n\
469 Click OK to exit %1."), PROGRAM_NAME));
470     
471                 msg.run ();
472                 _exit (0);
473                 
474         } else {
475
476                 /* engine has already run, so this is a mid-session JACK death */
477                 
478                 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
479                 msg->set_secondary_text (string_compose (_(
480 "JACK exited unexpectedly, and without notifying %1.\n\
481 \n\
482 This is probably due to an error inside JACK. You should restart JACK\n\
483 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
484 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
485                 msg->present ();
486         }
487         return false; /* do not call again */
488 }
489
490 static void
491 sigpipe_handler (int /*signal*/)
492 {
493         /* XXX fix this so that we do this again after a reconnect to JACK
494          */
495
496         static bool done_the_jack_thing = false;
497         
498         if (!done_the_jack_thing) {
499                 AudioEngine::instance()->died ();
500                 g_idle_add (tell_about_jack_death, 0);
501                 done_the_jack_thing =  true;
502         }
503 }
504
505 #ifdef HAVE_LV2
506 void close_external_ui_windows();
507 #endif
508
509 #ifdef VST_SUPPORT
510
511 extern int gui_init (int* argc, char** argv[]);
512
513 /* this is called from the entry point of a wine-compiled
514    executable that is linked against gtk2_ardour built
515    as a shared library.
516 */
517 extern "C" {
518 int ardour_main (int argc, char *argv[])
519 #else
520 int main (int argc, char *argv[])
521 #endif
522 {
523 #ifdef __APPLE__
524         fixup_bundle_environment ();
525 #endif
526
527         if (!Glib::thread_supported())
528                 Glib::thread_init();
529
530         gtk_set_locale ();
531
532 #ifdef VST_SUPPORT
533         /* this does some magic that is needed to make GTK and Wine's own
534            X11 client interact properly.
535         */
536         gui_init (&argc, &argv);
537 #endif
538
539         (void) bindtextdomain (PACKAGE, localedir);
540         /* our i18n translations are all in UTF-8, so make sure
541            that even if the user locale doesn't specify UTF-8,
542            we use that when handling them.
543         */
544         (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
545         (void) textdomain (PACKAGE);
546
547         pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
548
549         // catch error message system signals ();
550
551         text_receiver.listen_to (error);
552         text_receiver.listen_to (info);
553         text_receiver.listen_to (fatal);
554         text_receiver.listen_to (warning);
555
556         if (parse_opts (argc, argv)) {
557                 exit (1);
558         }
559
560         if (curvetest_file) {
561                 return curvetest (curvetest_file);
562         }
563
564         cout << PROGRAM_NAME
565              << VERSIONSTRING
566              << _(" (built using ")
567              << svn_revision
568 #ifdef __GNUC__
569              << _(" and GCC version ") << __VERSION__
570 #endif
571              << ')'
572              << endl;
573
574         if (just_version) {
575                 exit (0);
576         }
577
578         if (no_splash) {
579                 cerr << _("Copyright (C) 1999-2010 Paul Davis") << endl
580                      << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
581                      << endl
582                      << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
583                      << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
584                      << _("This is free software, and you are welcome to redistribute it ") << endl
585                      << _("under certain conditions; see the source for copying conditions.")
586                      << endl;
587         }
588
589         /* some GUI objects need this */
590
591         PBD::ID::init ();
592
593         if (::signal (SIGPIPE, sigpipe_handler)) {
594                 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
595         }
596
597         try {
598                 ui = new ARDOUR_UI (&argc, &argv);
599         } catch (failed_constructor& err) {
600                 error << _("could not create ARDOUR GUI") << endmsg;
601                 exit (1);
602         }
603
604         ui->run (text_receiver);
605         Gtkmm2ext::Application::instance()->cleanup();
606         ui = 0;
607
608         ARDOUR::cleanup ();
609         pthread_cancel_all ();
610
611 #ifdef HAVE_LV2
612         close_external_ui_windows();
613 #endif
614         return 0;
615 }
616 #ifdef VST_SUPPORT
617 } // end of extern C block
618 #endif
619