1 module armos.communication.midi;
2 
3 import derelict.portmidi.portmidi;
4 import derelict.portmidi.porttime;
5 
6 struct MidiMessage{
7     long timestamp;
8     long status;
9     long data1;
10     long data2;
11 }
12 
13 /++
14 +/
15 class MidiStream {
16     public{
17         this(int id = -1, in size_t bufferSize = 1024){
18             DerelictPortMidi.load();
19             DerelictPortTime.load();
20             if(id == -1) id = defaultInputDeviceId();
21             auto e = Pm_OpenInput(&_stream,
22                                   id,
23                                   null,
24                                   bufferSize,
25                                   null,
26                                   null);
27         }
28 
29         static int defaultInputDeviceId(){
30             return Pm_GetDefaultInputDeviceID();
31         }
32 
33         MidiStream close(){
34             Pm_Close(this._stream);
35             _hasClosed = true;
36             return this;
37         }
38 
39         MidiMessage[] popMessages(){
40             immutable size_t max = 1024;
41             auto buffer = new PmEvent[](max);
42             auto numEvents = Pm_Read(_stream, buffer.ptr, max);
43             auto events = new MidiMessage[](numEvents);
44             foreach (size_t i, ref event; events) {
45                 import std.conv:to;
46                 event.timestamp = buffer[i].timestamp.to!long;
47                 event.status    = buffer[i].message.to!long & 0xFF;
48                 event.data1     = (buffer[i].message.to!long>>8) & 0xFF;
49                 event.data2     = (buffer[i].message.to!long>>16) & 0xFF;
50             }
51             return events;
52         }
53     }//public
54 
55     private{
56         ~this(){
57             if(!_hasClosed){
58                 close;
59             }
60         }
61 
62         PmStream*  _stream;
63         PmDeviceID _deviceId;
64         bool _hasClosed = false;
65     }//private
66 }//class Stream
67 
68