/* Copyright (C) 2013 Valeriy Kamyshniy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "waves_audiobackend.h" #include "waves_midiport.h" #include "waves_midi_event.h" #include "waves_midi_buffer.h" using namespace ARDOUR; #ifdef __MACOS__ const std::vector WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("CoreMIDI"); #elif _WINDOWS const std::vector WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("Multimedia Extensions"); #endif std::vector WavesAudioBackend::enumerate_midi_options () const { // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_midi_options ()" << std::endl; return __available_midi_options; } int WavesAudioBackend::set_midi_option (const std::string& option) { // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_midi_option ( " << option << " )" << std::endl; if (option == __available_midi_options[0]) { _use_midi = false; // COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl; } else if (option == __available_midi_options[1]) { _use_midi = true; // COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl; } else { std::cerr << "WavesAudioBackend::set_midi_option (): Invalid MIDI option!" << std::endl; return -1; } return 0; } std::string WavesAudioBackend::midi_option () const { // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::midi_option ():" << std::endl; return * (__available_midi_options.begin () + (_use_midi?1:0)); } int WavesAudioBackend::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buffer, void* port_buffer, uint32_t event_index) { // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_get ():" << std::endl; if (buffer == NULL) { std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'buffer' argument!\n"; return -1; } if (port_buffer == NULL) { std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'port_buffer' argument!\n"; return -1; } WavesMidiBuffer& source = * (WavesMidiBuffer*)port_buffer; if (event_index >= source.size ()) { std::cerr << "WavesAudioBackend::midi_event_get () : 'event_index' is out of the number of events stored in 'port_buffer'!\n"; return -1; } WavesMidiEvent* waves_midi_event = source[event_index]; timestamp = waves_midi_event->timestamp (); size = waves_midi_event->size (); *buffer = waves_midi_event->data (); return 0; } int WavesAudioBackend::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size) { // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_put ():" << std::endl; if (buffer == NULL) { std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'buffer' argument!\n"; return -1; } if (port_buffer == NULL) { std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'port_buffer' argument!\n"; return -1; } WavesMidiBuffer& target = * (WavesMidiBuffer*)port_buffer; // COMMENTED FREQUENT DBG LOGS */ std::cout << "\t [" << target.name () << "]"<< std::endl; if (target.size () && (pframes_t)target.back ()->timestamp () > timestamp) { std::cerr << "WavesAudioBackend::midi_event_put (): The MIDI Event to put is a bit late!" << std::endl; std::cerr << "\tprev timestamp is " << (pframes_t)target.back ()->timestamp () << " as the current one is " << timestamp << std::endl; return -1; } target.push_back (new WavesMidiEvent (timestamp, buffer, size)); return 0; } uint32_t WavesAudioBackend::get_midi_event_count (void* port_buffer) { // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::get_midi_event_count (): " << std::endl; if (port_buffer == NULL) { std::cerr << "WavesAudioBackend::get_midi_event_count () : NULL in the 'port_buffer' argument!\n"; return -1; } // COMMENTED FREQUENT DBG LOGS */ std::cout << "\tcount = " << (* (WavesMidiBuffer*)port_buffer).size () << std::endl; return (* (WavesMidiBuffer*)port_buffer).size (); } void WavesAudioBackend::midi_clear (void* port_buffer) { // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_clear (): " << std::endl; if (port_buffer == NULL) { std::cerr << "WavesAudioBackend::midi_clear () : NULL in the 'port_buffer' argument!\n"; return; } (* (WavesMidiBuffer*)port_buffer).clear (); } void WavesAudioBackend::_changed_midi_devices () { if (_midi_device_manager.stream (false)) { std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (false) failed!" << std::endl; return; } _midi_device_manager.stop (); if (_midi_device_manager.start () != 0) { std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.start () failed!" << std::endl; return; } if (_register_system_midi_ports () != 0) { std::cerr << "WavesAudioBackend::_changed_midi_devices (): _register_system_midi_ports () failed!" << std::endl; return; } manager.registration_callback (); if (_midi_device_manager.stream (true)) { std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (true) failed!" << std::endl; return; } } void WavesAudioBackend::_unregister_system_midi_ports () { // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_unregister_system_midi_ports ()" << std::endl; std::vector physical_midi_ports = _physical_midi_inputs; physical_midi_ports.insert (physical_midi_ports.begin (), _physical_midi_outputs.begin (), _physical_midi_outputs.end ()); for (std::vector::const_iterator it = physical_midi_ports.begin (); it != physical_midi_ports.end (); ++it) { std::vector::iterator port_iterator = std::find (_ports.begin (), _ports.end (), *it); if (port_iterator == _ports.end ()) { std::cerr << "WavesAudioBackend::_unregister_system_midi_ports (): Failed to find port [" << (*it)->name () << "]!" << std::endl; } else _ports.erase (port_iterator); delete *it; } _physical_midi_inputs.clear (); _physical_midi_outputs.clear (); } int WavesAudioBackend::_register_system_midi_ports () { // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_register_system_midi_ports ()" << std::endl; LatencyRange lr = {0,0}; lr.min = lr.max = _buffer_size; for (size_t i = 0; i<_ports.size ();) { WavesMidiPort* midi_port = dynamic_cast (_ports[i]); if (!midi_port || !midi_port->is_physical () || !midi_port->is_terminal ()) { ++i; continue; } if ((midi_port->is_input () && !midi_port->midi_device ()->is_output ()) || (midi_port->is_output () && !midi_port->midi_device ()->is_input ())) { disconnect_all (midi_port); unregister_port (midi_port); continue; // to be here for further additions in the end of this loop } ++i; } const std::vector& devices = _midi_device_manager.devices (); for (std::vector::const_iterator it = devices.begin (); it != devices.end (); ++it) { if ((*it)->is_input ()) { std::string port_name = "system_midi:" + (*it)->name () + " capture"; WavesDataPort* port = _find_port (port_name); WavesMidiPort* midi_port = dynamic_cast (port); if (midi_port && (midi_port->type () != DataType::MIDI || midi_port->midi_device () != *it || !midi_port->is_output () || !midi_port->is_physical () || !midi_port->is_terminal ())) { std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl; disconnect_all (midi_port); unregister_port (midi_port); port = NULL; } if (port == NULL) { port = _register_port ( port_name, DataType::MIDI , static_cast (IsOutput | IsPhysical | IsTerminal)); if (port == NULL) { return -1; } ((WavesMidiPort*)port)->set_midi_device (*it); } port->set_latency_range (lr, false); } if ((*it)->is_output ()) { std::string port_name = "system_midi:" + (*it)->name () + " playback"; WavesDataPort* port = _find_port (port_name); WavesMidiPort* midi_port = dynamic_cast (port); if (midi_port && (midi_port->type () != DataType::MIDI || midi_port->midi_device () != *it || !midi_port->is_input () || !midi_port->is_physical () || !midi_port->is_terminal ())) { std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl; disconnect_all (midi_port); unregister_port (midi_port); } if (port == NULL) { port = _register_port (port_name, DataType::MIDI, static_cast (IsInput | IsPhysical | IsTerminal)); if (port == NULL) { return -1; } } ((WavesMidiPort*)port)->set_midi_device ((*it)); port->set_latency_range (lr, true); } } return 0; } int WavesAudioBackend::_read_midi_data_from_devices () { // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_read_midi_data_from_devices ():" << std::endl; if (!_midi_device_manager.is_streaming ()) return 0; _midi_device_manager.do_read (); for (std::vector::iterator it = _physical_midi_inputs.begin (); it != _physical_midi_inputs.end (); ++it) { WavesMidiDevice* midi_device = (*it)->midi_device (); WavesMidiBuffer& waves_midi_buffer = (*it)->buffer (); waves_midi_buffer.clear (); while (WavesMidiEvent *waves_midi_event = midi_device->dequeue_input_waves_midi_event ()) { int32_t timestamp_st = _buffer_size - (_sample_time_at_cycle_start - waves_midi_event->timestamp ()); if (timestamp_st < 0) { timestamp_st = 0; } else if (timestamp_st >= (int32_t)_buffer_size) { timestamp_st = _buffer_size - 1; } waves_midi_event->set_timestamp (timestamp_st); waves_midi_buffer.push_back (waves_midi_event); } } return 0; } int WavesAudioBackend::_write_midi_data_to_devices (pframes_t nframes) { if (!_midi_device_manager.is_streaming ()) return 0; for (std::vector::iterator it = _physical_midi_outputs.begin (); it != _physical_midi_outputs.end (); ++it) { WavesMidiDevice* midi_device = (*it)->midi_device (); WavesMidiBuffer &waves_midi_buffer = * (WavesMidiBuffer*) (*it)->get_buffer (nframes); for (WavesMidiBufferIterator it = waves_midi_buffer.begin (); it != waves_midi_buffer.end ();) { WavesMidiEvent* waves_midi_event = *it; waves_midi_buffer.erase (it); waves_midi_event->set_timestamp (_sample_time_at_cycle_start + waves_midi_event->timestamp () + nframes); midi_device->enqueue_output_waves_midi_event (waves_midi_event); } } _midi_device_manager.do_write (); return 0; }