317f1ec257fe9af54ba6d6a1420c86d3540ad7ee
[ardour.git] / libs / backends / wavesaudio / waves_midi_device_manager.cc
1 /*
2     Copyright (C) 2013 Waves Audio Ltd.
3
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.
8
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.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "waves_midi_device_manager.h"
21 #include "waves_audiobackend.h"
22
23 #ifdef PLATFORM_WINDOWS
24
25 #include "windows.h"
26 #include "mmsystem.h"
27
28 #elif defined(__APPLE__)
29
30 #include <CoreMIDI/MIDIServices.h>
31
32 #define midiInGetNumDevs MIDIGetNumberOfSources
33 #define midiOutGetNumDevs MIDIGetNumberOfDestinations
34
35 #endif
36
37 using namespace ARDOUR;
38
39 WavesMidiDeviceManager::WavesMidiDeviceManager (WavesAudioBackend& audiobackend)
40     : _active (false)
41     , _streaming (false)
42     , _input_device_count (0)
43     , _output_device_count (0)
44     , _audiobackend (audiobackend)
45 {
46 }
47
48
49 WavesMidiDeviceManager::~WavesMidiDeviceManager ()
50 {
51 }
52
53
54 int
55 WavesMidiDeviceManager::start ()
56 {
57     // COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::stream ():" << std::endl;
58     if ( _active == true ) {
59         return -1;
60     }
61
62     if (Pm_Initialize () != pmNoError) {
63         return -1;
64     }
65
66     _create_devices ();
67
68     _input_device_count = midiInGetNumDevs ();
69     _output_device_count = midiOutGetNumDevs ();
70
71     _active = true;
72
73     return 0;
74 }
75
76
77 int
78 WavesMidiDeviceManager::stream (bool yn)
79 {
80     // COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::stream ():" << std::endl;
81     if (!_active) {
82         std::cerr << "WavesMidiDeviceManager::stream (): the midi device manager is not started up !" << std::endl;
83         return -1;
84     }
85
86     if (_streaming == yn) {
87         return 0;
88     }
89
90     if (yn)    {
91         if ( Pt_Start (1, __portmidi_callback, this) != ptNoError) {
92             std::cerr << "WavesMidiDeviceManager::stream (): Pt_Start () failed!" << std::endl;
93             return -1;
94         }
95     }
96     else {
97         if (Pt_Stop () != ptNoError) {
98             std::cerr << "WavesMidiDeviceManager::stream (): Pt_Stop () failed!" << std::endl;
99             return -1;
100         }
101     }
102
103     _streaming = yn;
104     return 0;
105 }
106
107
108 int
109 WavesMidiDeviceManager::stop ()
110 {
111     // COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::stop ():" << std::endl;
112
113     if ( _active == false ) {
114         return 0;
115         }
116     
117     stream (false);
118
119     _delete_devices ();
120     _active = false;
121
122     if (Pm_Terminate () != pmNoError) {
123         std::cerr << "WavesMidiDeviceManager::stop (): Pt_Terminate () failed!" << std::endl;
124         return -1;
125     }
126
127     return 0;
128 }
129
130 void 
131 WavesMidiDeviceManager::__portmidi_callback (PtTimestamp timestamp, void * userData)
132 {
133     // COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::__portmidi_callback ():" << std::endl;
134     WavesMidiDeviceManager *dm = (WavesMidiDeviceManager *)userData;
135     
136     if (dm == NULL) {
137         return;
138     }
139     
140     dm->_portmidi_callback (timestamp);
141 }
142
143 void
144 WavesMidiDeviceManager::_portmidi_callback (PtTimestamp timestamp)
145 {
146     if ((!_active) || (!_streaming)) {
147         return;
148     }
149
150     if ((_input_device_count != midiInGetNumDevs ()) || (_output_device_count != midiOutGetNumDevs ())) {
151         _audiobackend._changed_midi_devices ();
152         return;
153     }
154 }
155
156 void WavesMidiDeviceManager::do_read ()
157 {
158     for (std::vector<WavesMidiDevice *>::const_iterator it = _devices.begin ();  it != _devices.end (); ++it) {
159         (*it)->read_midi ();
160     }
161 }
162
163
164 void WavesMidiDeviceManager::do_write ()
165 {
166     for (std::vector<WavesMidiDevice *>::const_iterator it = _devices.begin ();  it != _devices.end (); ++it) {
167         (*it)->write_midi ();
168     }
169 }
170
171
172 PmTimestamp
173 WavesMidiDeviceManager::__get_time_ms (void *time_info)
174
175     return ((WavesAudioBackend*)time_info)->sample_time ();
176 }
177
178
179 WavesMidiDevice* WavesMidiDeviceManager::_get_device (const std::string& name)
180 {
181     for (size_t i = 0; i < _devices.size (); i++) {
182         if (name == _devices[i]->name ()) {
183             return _devices[i];
184         }
185     }
186     return NULL;
187 }
188
189
190 int
191 WavesMidiDeviceManager::_create_devices ()
192 {
193     int count = Pm_CountDevices ();
194
195     for (int i = 0; i < count; i++) {
196
197         const PmDeviceInfo* pm_device_info = Pm_GetDeviceInfo (i);
198             // COMMENTED DBG LOGS */ std::cout << "                                    interf : " << pm_device_info->interf << std::endl;
199             // COMMENTED DBG LOGS */ std::cout << "                                      name : " << pm_device_info->name << std::endl;
200             // COMMENTED DBG LOGS */ std::cout << "                                     input : " << pm_device_info->input << std::endl;
201             // COMMENTED DBG LOGS */ std::cout << "                                    output : " << pm_device_info->output << std::endl;
202             // COMMENTED DBG LOGS */ std::cout << "                                    opened : " << pm_device_info->opened << std::endl;
203 #if defined (PLATFORM_WINDOWS)
204                 if (strncmp (pm_device_info->name, "Microsoft", strlen ("Microsoft")) == 0) {
205                         // COMMENTED DBG LOGS */ std::cout << "      skipping anything from Microsoft :" << pm_device_info->name << std::endl;
206                         continue;
207                 }
208 #endif
209         if (pm_device_info == NULL) {
210             std::cerr << "WavesMidiDeviceManager::_create_devices (): Pm_GetDeviceInfo (" << i << ") failed!" << std::endl;
211             continue;
212         }
213
214         WavesMidiDevice *device = _get_device (pm_device_info->name);
215         if (!device) {
216             device = new WavesMidiDevice (pm_device_info->name);
217             _devices.push_back (device);
218                         if (device->open (__get_time_ms, (void*)&_audiobackend)) {
219                                 std::cerr << "WavesMidiDeviceManager::_create_devices (): [" << device->name () << "]->open () failed!" << std::endl;
220                         }
221                 }
222     }
223
224     return 0;
225 }
226
227
228 int
229 WavesMidiDeviceManager::_delete_devices ()
230 {
231     // COMMENTED DBG LOGS */ std::cout << "WavesMidiDeviceManager::_delete_devices ():" << std::endl;
232     while (!_devices.empty ()) {
233         WavesMidiDevice * device = _devices.back ();
234         _devices.pop_back ();
235                 device->close ();
236         delete device;
237     }
238     return 0;
239 }
240