Fix mantis bug #1619; de-selecting Options->Crossfades->Show now hides all crossfades...
[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/textreceiver.h>
27 #include <pbd/failed_constructor.h>
28 #include <pbd/pthread_utils.h>
29
30 #include <jack/jack.h>
31
32 #include <ardour/version.h>
33 #include <ardour/ardour.h>
34 #include <ardour/audioengine.h>
35
36 #include <gtkmm/main.h>
37 #include <gtkmm2ext/popup.h>
38 #include <gtkmm2ext/utils.h>
39
40 #include "svn_revision.h"
41 #include "version.h"
42 #include "ardour_ui.h"
43 #include "opts.h"
44 #include "enums.h"
45
46 #include "i18n.h"
47
48 using namespace Gtk;
49 using namespace GTK_ARDOUR;
50 using namespace ARDOUR;
51 using namespace PBD;
52 using namespace sigc;
53
54 TextReceiver text_receiver ("ardour");
55
56 extern int curvetest (string);
57
58 static ARDOUR_UI  *ui = 0;
59
60 string
61 which_ui_rcfile ()
62 {
63         string rcfile;
64         char* env;
65
66         if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
67                 rcfile = env;
68         } else {
69                 rcfile = "ardour2_ui.rc";
70         }
71
72         rcfile = find_config_file (rcfile);
73         
74         if (rcfile.empty()) {
75                 warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR2_UI_RC to point to a valid UI style file") << endmsg;
76         } else {
77                 cerr << "Loading ui configuration file " << rcfile << endl;
78         }
79         
80         return rcfile;
81 }
82
83 gint
84 show_ui_callback (void *arg)
85 {
86         ARDOUR_UI * ui = (ARDOUR_UI *) arg;
87
88         ui->hide_splash();
89         
90         return FALSE;
91 }
92
93 void
94 gui_jack_error ()
95 {
96         MessageDialog win (_("Ardour could not connect to JACK."),
97                      false,
98                      Gtk::MESSAGE_INFO,
99                      (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
100 win.set_secondary_text(_("There are several possible reasons:\n\
101 \n\
102 1) JACK is not running.\n\
103 2) JACK is running as another user, perhaps root.\n\
104 3) There is already another client called \"ardour\".\n\
105 \n\
106 Please consider the possibilities, and perhaps (re)start JACK."));
107
108         win.add_button (Stock::QUIT, RESPONSE_CLOSE);
109         win.set_default_response (RESPONSE_CLOSE);
110         
111         win.show_all ();
112         win.set_position (Gtk::WIN_POS_CENTER);
113
114         if (!no_splash) {
115                 ui->hide_splash ();
116         }
117
118         /* we just don't care about the result, but we want to block */
119
120         win.run ();
121 }
122
123 static bool
124 maybe_load_session ()
125 {
126         /* If no session name is given: we're not loading a session yet, nor creating a new one */
127         if (!session_name.length()) {
128                 ui->hide_splash ();
129                 if (!Config->get_no_new_session_dialog()) {
130                         if (!ui->new_session ()) {
131                                 return false;
132                         }
133                 }
134
135                 return true;
136         }
137
138         /* Load session or start the new session dialog */
139         string name, path;
140
141         bool isnew;
142
143         if (Session::find_session (session_name, path, name, isnew)) {
144                 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
145                 return false;
146         }
147
148         if (!new_session) {
149                         
150                 /* Loading a session, but the session doesn't exist */
151                 if (isnew) {
152                         error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
153                                                    "To create it from the command line, start ardour as \"ardour --new %1"), path) 
154                               << endmsg;
155                         return false;
156                 }
157
158                 if (ui->load_session (path, name)) {
159                         /* it failed */
160                         return false;
161                 }
162
163         } else {
164
165                 /*  TODO: This bit of code doesn't work properly yet
166                     Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
167                     ui->set_will_create_new_session_automatically (true); 
168                 */
169                 
170                 /* Show the NSD */
171                 ui->hide_splash ();
172                 if (!Config->get_no_new_session_dialog()) {
173                         if (!ui->new_session ()) {
174                                 return false;
175                         }
176                 }
177         }
178
179         return true;
180 }
181
182 #ifdef VST_SUPPORT
183 /* this is called from the entry point of a wine-compiled
184    executable that is linked against gtk2_ardour built
185    as a shared library.
186 */
187 extern "C" {
188 int ardour_main (int argc, char *argv[])
189 #else
190 int main (int argc, char *argv[])
191 #endif
192
193 {
194         ARDOUR::AudioEngine *engine;
195         vector<Glib::ustring> null_file_list;
196
197         Glib::thread_init();
198         gtk_set_locale ();
199
200         (void) bindtextdomain (PACKAGE, LOCALEDIR);
201         /* our i18n translations are all in UTF-8, so make sure
202            that even if the user locale doesn't specify UTF-8,
203            we use that when handling them.
204         */
205         (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
206         (void) textdomain (PACKAGE);
207
208         pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
209
210         // catch error message system signals ();
211
212         text_receiver.listen_to (error);
213         text_receiver.listen_to (info);
214         text_receiver.listen_to (fatal);
215         text_receiver.listen_to (warning);
216
217         if (parse_opts (argc, argv)) {
218                 exit (1);
219         }
220
221         if (curvetest_file) {
222                 return curvetest (curvetest_file);
223         }
224         
225         cout << _("Ardour/GTK ") 
226              << VERSIONSTRING
227              << _("\n   (built using ")
228              << ardour_svn_revision
229 #ifdef __GNUC__
230              << _(" and GCC version ") << __VERSION__ 
231 #endif
232              << ')'
233              << endl;
234         
235         if (just_version) {
236                 exit (0);
237         }
238
239         if (no_splash) {
240                 cerr << _("Copyright (C) 1999-2007 Paul Davis") << endl
241                      << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
242                      << endl
243                      << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
244                      << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
245                      << _("This is free software, and you are welcome to redistribute it ") << endl
246                      << _("under certain conditions; see the source for copying conditions.")
247                      << endl;
248         }
249
250         /* some GUI objects need this */
251
252         PBD::ID::init ();
253
254         try { 
255                 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
256         } catch (failed_constructor& err) {
257                 error << _("could not create ARDOUR GUI") << endmsg;
258                 exit (1);
259         }
260
261         if (!keybindings_path.empty()) {
262                 ui->set_keybindings_path (keybindings_path);
263         }
264
265         if (!no_splash) {
266                 ui->show_splash ();
267                 if (session_name.length()) {  
268                         g_timeout_add (4000, show_ui_callback, ui);
269                 }
270         }
271
272         try {
273                 ARDOUR::init (use_vst, try_hw_optimization);
274                 setup_gtk_ardour_enums ();
275                 Config->set_current_owner (ConfigVariableBase::Interface);
276                 ui->setup_profile ();
277
278                 try { 
279                         engine = new ARDOUR::AudioEngine (jack_client_name);
280                 } catch (AudioEngine::NoBackendAvailable& err) {
281                         gui_jack_error ();
282                         error << string_compose (_("Could not connect to JACK server as  \"%1\""), jack_client_name) <<  endmsg;
283                         return -1;
284                 }
285                 
286                 ui->set_engine (*engine);
287
288         } catch (failed_constructor& err) {
289                 error << _("could not initialize Ardour.") << endmsg;
290                 return -1;
291         } 
292
293         ui->start_engine ();
294
295         if (maybe_load_session ()) {
296                 ui->run (text_receiver);
297                 ui = 0;
298         }
299
300         delete engine;
301         ARDOUR::cleanup ();
302
303         if (ui) {
304                 ui->kill();
305         }
306                 
307         pthread_cancel_all ();
308
309         exit (0);
310
311         return 0;
312 }
313 #ifdef VST_SUPPORT
314 } // end of extern C block
315 #endif
316