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