2 * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
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.
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.
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.
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"
29 #include "ardour/audioengine.h"
30 #include "ardour/filename_extensions.h"
31 #include "ardour/types.h"
36 using namespace ARDOUR;
39 static const char* localedir = LOCALEDIR;
40 TestReceiver test_receiver;
43 TestReceiver::receive (Transmitter::Channel chn, const char * str)
45 const char *prefix = "";
48 case Transmitter::Error:
49 prefix = ": [ERROR]: ";
51 case Transmitter::Info:
54 case Transmitter::Warning:
55 prefix = ": [WARNING]: ";
57 case Transmitter::Fatal:
58 prefix = ": [FATAL]: ";
60 case Transmitter::Throw:
61 /* this isn't supposed to happen */
65 /* note: iostreams are already thread-safe: no external
69 std::cout << prefix << str << std::endl;
71 if (chn == Transmitter::Fatal) {
76 /* temporarily required due to some code design confusion (Feb 2014) */
78 #include "ardour/vst_types.h"
80 int vstfx_init (void*) { return 0; }
82 void vstfx_destroy_editor (VSTState*) {}
84 class MyEventLoop : public sigc::trackable, public EventLoop
87 MyEventLoop (std::string const& name) : EventLoop (name) {
88 run_loop_thread = Glib::Threads::Thread::self();
91 void call_slot (InvalidationRecord*, const boost::function<void()>& f) {
92 if (Glib::Threads::Thread::self() == run_loop_thread) {
97 Glib::Threads::Mutex& slot_invalidation_mutex() { return request_buffer_map_lock; }
100 Glib::Threads::Thread* run_loop_thread;
101 Glib::Threads::Mutex request_buffer_map_lock;
104 static MyEventLoop *event_loop;
107 SessionUtils::init (bool print_log)
109 if (!ARDOUR::init (false, true, localedir)) {
110 cerr << "Ardour failed to initialize\n" << endl;
111 ::exit (EXIT_FAILURE);
114 event_loop = new MyEventLoop ("util");
115 EventLoop::set_event_loop_for_thread (event_loop);
116 SessionEvent::create_per_thread_pool ("util", 512);
119 test_receiver.listen_to (error);
120 test_receiver.listen_to (info);
121 test_receiver.listen_to (fatal);
122 test_receiver.listen_to (warning);
126 // TODO return NULL, rather than exit() ?!
127 static Session * _load_session (string dir, string state)
129 AudioEngine* engine = AudioEngine::create ();
131 if (!engine->set_backend ("None (Dummy)", "Unit-Test", "")) {
132 std::cerr << "Cannot create Audio/MIDI engine\n";
133 ::exit (EXIT_FAILURE);
136 engine->set_input_channels (256);
137 engine->set_output_channels (256);
143 std::string s = Glib::build_filename (dir, state + statefile_suffix);
145 if (!Glib::file_test (s, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
146 std::cerr << "Cannot read session '"<< s << "'\n";
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";
156 std::cerr << "Cannot get samplerate from session.\n";
160 if (engine->start () != 0) {
161 std::cerr << "Cannot start Audio/MIDI engine\n";
165 Session* session = new Session (*engine, dir, state);
166 engine->set_session (session);
171 SessionUtils::load_session (string dir, string state, bool exit_at_failure)
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);
186 cerr << "unknown exception.\n";
187 ::exit (EXIT_FAILURE);
189 if (!s && exit_at_failure) {
190 ::exit (EXIT_FAILURE);
196 SessionUtils::create_session (string dir, string state, float sample_rate)
198 AudioEngine* engine = AudioEngine::create ();
200 if (!engine->set_backend ("None (Dummy)", "Unit-Test", "")) {
201 std::cerr << "Cannot create Audio/MIDI engine\n";
202 ::exit (EXIT_FAILURE);
205 engine->set_input_channels (256);
206 engine->set_output_channels (256);
208 if (engine->set_sample_rate (sample_rate)) {
209 std::cerr << "Cannot set session's samplerate.\n";
213 if (engine->start () != 0) {
214 std::cerr << "Cannot start Audio/MIDI engine\n";
218 std::string s = Glib::build_filename (dir, state + statefile_suffix);
220 if (Glib::file_test (dir, Glib::FILE_TEST_EXISTS)) {
221 std::cerr << "Session folder already exists '"<< dir << "'\n";
223 if (Glib::file_test (s, Glib::FILE_TEST_EXISTS)) {
224 std::cerr << "Session file exists '"<< s << "'\n";
228 Session* session = new Session (*engine, dir, state);
229 engine->set_session (session);
234 SessionUtils::unload_session (Session *s)
237 AudioEngine::instance()->stop ();
238 AudioEngine::destroy ();
242 SessionUtils::cleanup ()
246 pthread_cancel_all ();