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