2014-02-24 14:39:10 -05:00
|
|
|
/*
|
2014-04-29 16:30:56 -04:00
|
|
|
Copyright (C) 2014 Waves Audio Ltd.
|
2014-02-24 14:39:10 -05:00
|
|
|
|
|
|
|
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 "waves_midi_device_manager.h"
|
|
|
|
#include "waves_audiobackend.h"
|
|
|
|
|
|
|
|
#ifdef __WINDOWS__
|
|
|
|
|
|
|
|
#include "windows.h"
|
|
|
|
#include "mmsystem.h"
|
|
|
|
|
|
|
|
#elif __MACOS__
|
|
|
|
|
|
|
|
#include <CoreMIDI/MIDIServices.h>
|
|
|
|
|
|
|
|
#define midiInGetNumDevs MIDIGetNumberOfSources
|
|
|
|
#define midiOutGetNumDevs MIDIGetNumberOfDestinations
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
using namespace ARDOUR;
|
|
|
|
|
|
|
|
WavesMidiDeviceManager::WavesMidiDeviceManager (WavesAudioBackend& audiobackend)
|
|
|
|
: _active (false)
|
|
|
|
, _streaming (false)
|
|
|
|
, _input_device_count (0)
|
|
|
|
, _output_device_count (0)
|
|
|
|
, _audiobackend (audiobackend)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WavesMidiDeviceManager::~WavesMidiDeviceManager ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
WavesMidiDeviceManager::start ()
|
|
|
|
{
|
|
|
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::stream ():" << std::endl;
|
|
|
|
if ( _active == true ) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Pm_Initialize () != pmNoError) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_create_devices ();
|
|
|
|
|
|
|
|
_input_device_count = midiInGetNumDevs ();
|
|
|
|
_output_device_count = midiOutGetNumDevs ();
|
|
|
|
|
|
|
|
_active = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
WavesMidiDeviceManager::stream (bool yn)
|
|
|
|
{
|
|
|
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::stream ():" << std::endl;
|
|
|
|
if (!_active) {
|
|
|
|
std::cerr << "WavesMidiDeviceManager::stream (): the midi device manager is not started up !" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_streaming == yn) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (yn) {
|
|
|
|
if ( Pt_Start (1, __portmidi_callback, this) != ptNoError) {
|
|
|
|
std::cerr << "WavesMidiDeviceManager::stream (): Pt_Start () failed!" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (Pt_Stop () != ptNoError) {
|
|
|
|
std::cerr << "WavesMidiDeviceManager::stream (): Pt_Stop () failed!" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_streaming = yn;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
WavesMidiDeviceManager::stop ()
|
|
|
|
{
|
|
|
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::stop ():" << std::endl;
|
|
|
|
|
|
|
|
if ( _active == false )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
stream (false);
|
|
|
|
|
|
|
|
_close_devices ();
|
|
|
|
_active = false;
|
|
|
|
|
|
|
|
if (Pm_Terminate () != pmNoError) {
|
|
|
|
std::cerr << "WavesMidiDeviceManager::stop (): Pt_Terminate () failed!" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
WavesMidiDeviceManager::__portmidi_callback (PtTimestamp timestamp, void * userData)
|
|
|
|
{
|
|
|
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::__portmidi_callback ():" << std::endl;
|
|
|
|
WavesMidiDeviceManager *dm = (WavesMidiDeviceManager *)userData;
|
|
|
|
|
|
|
|
if (dm == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dm->_portmidi_callback (timestamp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
WavesMidiDeviceManager::_portmidi_callback (PtTimestamp timestamp)
|
|
|
|
{
|
|
|
|
if ((!_active) || (!_streaming)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((_input_device_count != midiInGetNumDevs ()) || (_output_device_count != midiOutGetNumDevs ())) {
|
|
|
|
_audiobackend._changed_midi_devices ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WavesMidiDeviceManager::do_read ()
|
|
|
|
{
|
|
|
|
for (std::vector<WavesMidiDevice *>::const_iterator it = _devices.begin (); it != _devices.end (); ++it) {
|
|
|
|
(*it)->read_midi ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void WavesMidiDeviceManager::do_write ()
|
|
|
|
{
|
|
|
|
for (std::vector<WavesMidiDevice *>::const_iterator it = _devices.begin (); it != _devices.end (); ++it) {
|
|
|
|
(*it)->write_midi ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PmTimestamp
|
|
|
|
WavesMidiDeviceManager::__get_time_ms (void *time_info)
|
|
|
|
{
|
|
|
|
return ((WavesAudioBackend*)time_info)->sample_time ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WavesMidiDevice* WavesMidiDeviceManager::_get_device (const std::string& name)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < _devices.size (); i++) {
|
|
|
|
if (name == _devices[i]->name ()) {
|
|
|
|
return _devices[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
WavesMidiDeviceManager::_create_devices ()
|
|
|
|
{
|
|
|
|
int count = Pm_CountDevices ();
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
|
|
|
const PmDeviceInfo* pm_device_info = Pm_GetDeviceInfo (i);
|
|
|
|
|
|
|
|
if (pm_device_info == NULL) {
|
|
|
|
std::cerr << "WavesMidiDeviceManager::_create_devices (): Pm_GetDeviceInfo (" << i << ") failed!" << std::endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
WavesMidiDevice *device = _get_device (pm_device_info->name);
|
|
|
|
if (device) {
|
|
|
|
device->validate ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
device = new WavesMidiDevice (pm_device_info->name);
|
|
|
|
_devices.push_back (device);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (device->open (__get_time_ms, (void*)&_audiobackend)) {
|
|
|
|
std::cerr << "WavesMidiDeviceManager::_create_devices (): [" << device->name () << "]->open () failed!" << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
WavesMidiDeviceManager::_delete_devices ()
|
|
|
|
{
|
|
|
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::_delete_devices ():" << std::endl;
|
|
|
|
while (!_devices.empty ()) {
|
|
|
|
WavesMidiDevice * device = _devices.back ();
|
|
|
|
_devices.pop_back ();
|
|
|
|
delete device;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
WavesMidiDeviceManager::_close_devices ()
|
|
|
|
{
|
|
|
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::_delete_devices ():" << std::endl;
|
|
|
|
for (size_t i = 0; i < _devices.size (); i++) {
|
|
|
|
_devices[i]->close ();
|
|
|
|
}
|
|
|
|
}
|