2 Copyright (C) 2014 Waves Audio Ltd.
\r
4 This program is free software; you can redistribute it and/or modify
\r
5 it under the terms of the GNU General Public License as published by
\r
6 the Free Software Foundation; either version 2 of the License, or
\r
7 (at your option) any later version.
\r
9 This program is distributed in the hope that it will be useful,
\r
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 GNU General Public License for more details.
\r
14 You should have received a copy of the GNU General Public License
\r
15 along with this program; if not, write to the Free Software
\r
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
\r
20 #include <boost/assign/list_of.hpp>
\r
22 #include "waves_audiobackend.h"
\r
23 #include "waves_midiport.h"
\r
24 #include "waves_midi_event.h"
\r
25 #include "waves_midi_buffer.h"
\r
27 using namespace ARDOUR;
\r
31 const std::vector<std::string> WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("CoreMIDI");
\r
35 const std::vector<std::string> WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("Multimedia Extensions");
\r
40 std::vector<std::string>
\r
41 WavesAudioBackend::enumerate_midi_options () const
\r
43 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_midi_options ()" << std::endl;
\r
44 return __available_midi_options;
\r
49 WavesAudioBackend::set_midi_option (const std::string& option)
\r
51 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_midi_option ( " << option << " )" << std::endl;
\r
52 if (option == __available_midi_options[0]) {
\r
54 // COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl;
\r
56 else if (option == __available_midi_options[1]) {
\r
58 // COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl;
\r
61 std::cerr << "WavesAudioBackend::set_midi_option (): Invalid MIDI option!" << std::endl;
\r
70 WavesAudioBackend::midi_option () const
\r
72 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::midi_option ():" << std::endl;
\r
73 return * (__available_midi_options.begin () + (_use_midi?1:0));
\r
78 WavesAudioBackend::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buffer, void* port_buffer, uint32_t event_index)
\r
80 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_get ():" << std::endl;
\r
82 if (buffer == NULL) {
\r
83 std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'buffer' argument!\n";
\r
87 if (port_buffer == NULL) {
\r
88 std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'port_buffer' argument!\n";
\r
92 WavesMidiBuffer& source = * (WavesMidiBuffer*)port_buffer;
\r
94 if (event_index >= source.size ()) {
\r
95 std::cerr << "WavesAudioBackend::midi_event_get () : 'event_index' is out of the number of events stored in 'port_buffer'!\n";
\r
99 WavesMidiEvent* waves_midi_event = source[event_index];
\r
101 timestamp = waves_midi_event->timestamp ();
\r
102 size = waves_midi_event->size ();
\r
103 *buffer = waves_midi_event->data ();
\r
110 WavesAudioBackend::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
\r
112 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_put ():" << std::endl;
\r
113 if (buffer == NULL) {
\r
114 std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'buffer' argument!\n";
\r
118 if (port_buffer == NULL) {
\r
119 std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'port_buffer' argument!\n";
\r
123 WavesMidiBuffer& target = * (WavesMidiBuffer*)port_buffer;
\r
124 // COMMENTED FREQUENT DBG LOGS */ std::cout << "\t [" << target.name () << "]"<< std::endl;
\r
126 if (target.size () && (pframes_t)target.back ()->timestamp () > timestamp) {
\r
127 std::cerr << "WavesAudioBackend::midi_event_put (): The MIDI Event to put is a bit late!" << std::endl;
\r
128 std::cerr << "\tprev timestamp is " << (pframes_t)target.back ()->timestamp () << " as the current one is " << timestamp << std::endl;
\r
132 target.push_back (new WavesMidiEvent (timestamp, buffer, size));
\r
138 WavesAudioBackend::get_midi_event_count (void* port_buffer)
\r
140 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::get_midi_event_count (): " << std::endl;
\r
142 if (port_buffer == NULL) {
\r
143 std::cerr << "WavesAudioBackend::get_midi_event_count () : NULL in the 'port_buffer' argument!\n";
\r
147 // COMMENTED FREQUENT DBG LOGS */ std::cout << "\tcount = " << (* (WavesMidiBuffer*)port_buffer).size () << std::endl;
\r
149 return (* (WavesMidiBuffer*)port_buffer).size ();
\r
154 WavesAudioBackend::midi_clear (void* port_buffer)
\r
156 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_clear (): " << std::endl;
\r
157 if (port_buffer == NULL) {
\r
158 std::cerr << "WavesAudioBackend::midi_clear () : NULL in the 'port_buffer' argument!\n";
\r
162 (* (WavesMidiBuffer*)port_buffer).clear ();
\r
167 WavesAudioBackend::_changed_midi_devices ()
\r
169 if (_midi_device_manager.stream (false)) {
\r
170 std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (false) failed!" << std::endl;
\r
174 _midi_device_manager.stop ();
\r
176 if (_midi_device_manager.start () != 0) {
\r
177 std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.start () failed!" << std::endl;
\r
181 if (_register_system_midi_ports () != 0) {
\r
182 std::cerr << "WavesAudioBackend::_changed_midi_devices (): _register_system_midi_ports () failed!" << std::endl;
\r
186 manager.registration_callback ();
\r
188 if (_midi_device_manager.stream (true)) {
\r
189 std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (true) failed!" << std::endl;
\r
196 WavesAudioBackend::_unregister_system_midi_ports ()
\r
198 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_unregister_system_midi_ports ()" << std::endl;
\r
199 std::vector<WavesMidiPort*> physical_midi_ports = _physical_midi_inputs;
\r
200 physical_midi_ports.insert (physical_midi_ports.begin (), _physical_midi_outputs.begin (), _physical_midi_outputs.end ());
\r
202 for (std::vector<WavesMidiPort*>::const_iterator it = physical_midi_ports.begin (); it != physical_midi_ports.end (); ++it) {
\r
203 std::vector<WavesDataPort*>::iterator port_iterator = std::find (_ports.begin (), _ports.end (), *it);
\r
204 if (port_iterator == _ports.end ()) {
\r
205 std::cerr << "WavesAudioBackend::_unregister_system_midi_ports (): Failed to find port [" << (*it)->name () << "]!" << std::endl;
\r
208 _ports.erase (port_iterator);
\r
211 _physical_midi_inputs.clear ();
\r
212 _physical_midi_outputs.clear ();
\r
217 WavesAudioBackend::_register_system_midi_ports ()
\r
219 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_register_system_midi_ports ()" << std::endl;
\r
221 LatencyRange lr = {0,0};
\r
222 lr.min = lr.max = _buffer_size;
\r
224 for (size_t i = 0; i<_ports.size ();) {
\r
225 WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (_ports[i]);
\r
226 if (!midi_port || !midi_port->is_physical () || !midi_port->is_terminal ()) {
\r
231 if ((midi_port->is_input () && !midi_port->midi_device ()->is_output ()) ||
\r
232 (midi_port->is_output () && !midi_port->midi_device ()->is_input ())) {
\r
233 disconnect_all (midi_port);
\r
234 unregister_port (midi_port);
\r
235 continue; // to be here for further additions in the end of this loop
\r
241 const std::vector<WavesMidiDevice *>& devices = _midi_device_manager.devices ();
\r
243 for (std::vector<WavesMidiDevice*>::const_iterator it = devices.begin (); it != devices.end (); ++it) {
\r
244 if ((*it)->is_input ()) {
\r
245 std::string port_name = "system_midi:" + (*it)->name () + " capture";
\r
246 WavesDataPort* port = _find_port (port_name);
\r
247 WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (port);
\r
248 if (midi_port && (midi_port->type () != DataType::MIDI ||
\r
249 midi_port->midi_device () != *it ||
\r
250 !midi_port->is_output () ||
\r
251 !midi_port->is_physical () ||
\r
252 !midi_port->is_terminal ())) {
\r
253 std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl;
\r
254 disconnect_all (midi_port);
\r
255 unregister_port (midi_port);
\r
259 if (port == NULL) {
\r
260 port = _register_port ( port_name, DataType::MIDI , static_cast<ARDOUR::PortFlags> (IsOutput | IsPhysical | IsTerminal));
\r
261 if (port == NULL) {
\r
264 ((WavesMidiPort*)port)->set_midi_device (*it);
\r
266 port->set_latency_range (lr, false);
\r
269 if ((*it)->is_output ()) {
\r
270 std::string port_name = "system_midi:" + (*it)->name () + " playback";
\r
271 WavesDataPort* port = _find_port (port_name);
\r
272 WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (port);
\r
273 if (midi_port && (midi_port->type () != DataType::MIDI ||
\r
274 midi_port->midi_device () != *it ||
\r
275 !midi_port->is_input () ||
\r
276 !midi_port->is_physical () ||
\r
277 !midi_port->is_terminal ())) {
\r
278 std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl;
\r
279 disconnect_all (midi_port);
\r
280 unregister_port (midi_port);
\r
283 if (port == NULL) {
\r
284 port = _register_port (port_name,
\r
286 static_cast<ARDOUR::PortFlags> (IsInput | IsPhysical | IsTerminal));
\r
287 if (port == NULL) {
\r
292 ((WavesMidiPort*)port)->set_midi_device ((*it));
\r
293 port->set_latency_range (lr, true);
\r
302 WavesAudioBackend::_read_midi_data_from_devices ()
\r
304 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_read_midi_data_from_devices ():" << std::endl;
\r
305 if (!_midi_device_manager.is_streaming ())
\r
308 _midi_device_manager.do_read ();
\r
310 for (std::vector<WavesMidiPort*>::iterator it = _physical_midi_inputs.begin (); it != _physical_midi_inputs.end (); ++it) {
\r
311 WavesMidiDevice* midi_device = (*it)->midi_device ();
\r
313 WavesMidiBuffer& waves_midi_buffer = (*it)->buffer ();
\r
314 waves_midi_buffer.clear ();
\r
316 while (WavesMidiEvent *waves_midi_event = midi_device->dequeue_input_waves_midi_event ()) {
\r
317 int32_t timestamp_st = _buffer_size - (_sample_time_at_cycle_start - waves_midi_event->timestamp ());
\r
319 if (timestamp_st < 0) {
\r
322 else if (timestamp_st >= (int32_t)_buffer_size) {
\r
323 timestamp_st = _buffer_size - 1;
\r
325 waves_midi_event->set_timestamp (timestamp_st);
\r
326 waves_midi_buffer.push_back (waves_midi_event);
\r
334 WavesAudioBackend::_write_midi_data_to_devices (pframes_t nframes)
\r
336 if (!_midi_device_manager.is_streaming ())
\r
339 for (std::vector<WavesMidiPort*>::iterator it = _physical_midi_outputs.begin (); it != _physical_midi_outputs.end (); ++it) {
\r
340 WavesMidiDevice* midi_device = (*it)->midi_device ();
\r
341 WavesMidiBuffer &waves_midi_buffer = * (WavesMidiBuffer*) (*it)->get_buffer (nframes);
\r
343 for (WavesMidiBufferIterator it = waves_midi_buffer.begin (); it != waves_midi_buffer.end ();) {
\r
344 WavesMidiEvent* waves_midi_event = *it;
\r
346 waves_midi_buffer.erase (it);
\r
348 waves_midi_event->set_timestamp (_sample_time_at_cycle_start + waves_midi_event->timestamp () + nframes);
\r
349 midi_device->enqueue_output_waves_midi_event (waves_midi_event);
\r
352 _midi_device_manager.do_write ();
\r