Add missing i18n include (after 7f3f2018334)
[ardour.git] / session_utils / common.cc
1 /*
2  * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
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 along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include <iostream>
20 #include <cstdlib>
21 #include <glibmm.h>
22
23 #include "pbd/debug.h"
24 #include "pbd/event_loop.h"
25 #include "pbd/error.h"
26 #include "pbd/failed_constructor.h"
27 #include "pbd/pthread_utils.h"
28
29 #include "ardour/audioengine.h"
30 #include "ardour/filename_extensions.h"
31 #include "ardour/types.h"
32
33 #include "common.h"
34
35 using namespace std;
36 using namespace ARDOUR;
37 using namespace PBD;
38
39 static const char* localedir = LOCALEDIR;
40 TestReceiver test_receiver;
41
42 void
43 TestReceiver::receive (Transmitter::Channel chn, const char * str)
44 {
45         const char *prefix = "";
46
47         switch (chn) {
48         case Transmitter::Error:
49                 prefix = ": [ERROR]: ";
50                 break;
51         case Transmitter::Info:
52                 /* ignore */
53                 return;
54         case Transmitter::Warning:
55                 prefix = ": [WARNING]: ";
56                 break;
57         case Transmitter::Fatal:
58                 prefix = ": [FATAL]: ";
59                 break;
60         case Transmitter::Throw:
61                 /* this isn't supposed to happen */
62                 abort ();
63         }
64
65         /* note: iostreams are already thread-safe: no external
66            lock required.
67         */
68
69         std::cout << prefix << str << std::endl;
70
71         if (chn == Transmitter::Fatal) {
72                 ::exit (9);
73         }
74 }
75
76 /* temporarily required due to some code design confusion (Feb 2014) */
77
78 #include "ardour/vst_types.h"
79
80 int vstfx_init (void*) { return 0; }
81 void vstfx_exit () {}
82 void vstfx_destroy_editor (VSTState*) {}
83
84 class MyEventLoop : public sigc::trackable, public EventLoop
85 {
86         public:
87                 MyEventLoop (std::string const& name) : EventLoop (name) {
88                         run_loop_thread = Glib::Threads::Thread::self();
89                 }
90
91                 void call_slot (InvalidationRecord*, const boost::function<void()>& f) {
92                         if (Glib::Threads::Thread::self() == run_loop_thread) {
93                                 f ();
94                         }
95                 }
96
97                 Glib::Threads::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
98
99         private:
100                 Glib::Threads::Thread* run_loop_thread;
101                 Glib::Threads::Mutex   request_buffer_map_lock;
102 };
103
104 static MyEventLoop *event_loop;
105
106 void
107 SessionUtils::init (bool print_log)
108 {
109         if (!ARDOUR::init (false, true, localedir)) {
110                 cerr << "Ardour failed to initialize\n" << endl;
111                 ::exit (EXIT_FAILURE);
112         }
113
114         event_loop = new MyEventLoop ("util");
115         EventLoop::set_event_loop_for_thread (event_loop);
116         SessionEvent::create_per_thread_pool ("util", 512);
117
118         if (print_log) {
119                 test_receiver.listen_to (error);
120                 test_receiver.listen_to (info);
121                 test_receiver.listen_to (fatal);
122                 test_receiver.listen_to (warning);
123         }
124 }
125
126 // TODO return NULL, rather than exit() ?!
127 static Session * _load_session (string dir, string state)
128 {
129         AudioEngine* engine = AudioEngine::create ();
130
131         if (!engine->set_backend ("None (Dummy)", "Unit-Test", "")) {
132                 std::cerr << "Cannot create Audio/MIDI engine\n";
133                 ::exit (EXIT_FAILURE);
134         }
135
136         engine->set_input_channels (256);
137         engine->set_output_channels (256);
138
139         float sr;
140         SampleFormat sf;
141         std::string v;
142
143         std::string s = Glib::build_filename (dir, state + statefile_suffix);
144
145         if (!Glib::file_test (s, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
146                 std::cerr << "Cannot read session '"<< s << "'\n";
147                 return 0;
148         }
149
150         if (Session::get_info_from_path (s, sr, sf, v) == 0) {
151                 if (engine->set_sample_rate (sr)) {
152                         std::cerr << "Cannot set session's samplerate.\n";
153                         return 0;
154                 }
155         } else {
156                 std::cerr << "Cannot get samplerate from session.\n";
157                 return 0;
158         }
159
160         if (engine->start () != 0) {
161                 std::cerr << "Cannot start Audio/MIDI engine\n";
162                 return 0;
163         }
164
165         Session* session = new Session (*engine, dir, state);
166         engine->set_session (session);
167         return session;
168 }
169
170 Session *
171 SessionUtils::load_session (string dir, string state, bool exit_at_failure)
172 {
173         Session* s = 0;
174         try {
175                 s = _load_session (dir, state);
176         } catch (failed_constructor& e) {
177                 cerr << "failed_constructor: " << e.what() << "\n";
178                 ::exit (EXIT_FAILURE);
179         } catch (AudioEngine::PortRegistrationFailure& e) {
180                 cerr << "PortRegistrationFailure: " << e.what() << "\n";
181                 ::exit (EXIT_FAILURE);
182         } catch (exception& e) {
183                 cerr << "exception: " << e.what() << "\n";
184                 ::exit (EXIT_FAILURE);
185         } catch (...) {
186                 cerr << "unknown exception.\n";
187                 ::exit (EXIT_FAILURE);
188         }
189         if (!s && exit_at_failure) {
190                 ::exit (EXIT_FAILURE);
191         }
192         return s;
193 }
194
195 Session *
196 SessionUtils::create_session (string dir, string state, float sample_rate)
197 {
198         AudioEngine* engine = AudioEngine::create ();
199
200         if (!engine->set_backend ("None (Dummy)", "Unit-Test", "")) {
201                 std::cerr << "Cannot create Audio/MIDI engine\n";
202                 ::exit (EXIT_FAILURE);
203         }
204
205         engine->set_input_channels (256);
206         engine->set_output_channels (256);
207
208         if (engine->set_sample_rate (sample_rate)) {
209                 std::cerr << "Cannot set session's samplerate.\n";
210                 return 0;
211         }
212
213         if (engine->start () != 0) {
214                 std::cerr << "Cannot start Audio/MIDI engine\n";
215                 return 0;
216         }
217
218         std::string s = Glib::build_filename (dir, state + statefile_suffix);
219
220         if (Glib::file_test (dir, Glib::FILE_TEST_EXISTS)) {
221                 std::cerr << "Session folder already exists '"<< dir << "'\n";
222         }
223         if (Glib::file_test (s, Glib::FILE_TEST_EXISTS)) {
224                 std::cerr << "Session file exists '"<< s << "'\n";
225                 return 0;
226         }
227
228         Session* session = new Session (*engine, dir, state);
229         engine->set_session (session);
230         return session;
231 }
232
233 void
234 SessionUtils::unload_session (Session *s)
235 {
236         delete s;
237         AudioEngine::instance()->stop ();
238         AudioEngine::destroy ();
239 }
240
241 void
242 SessionUtils::cleanup ()
243 {
244         ARDOUR::cleanup ();
245         delete event_loop;
246         pthread_cancel_all ();
247 }