1 module derelict.portmidi.portmidi; 2 3 private { 4 import derelict.util.loader; 5 import derelict.util.system; 6 7 static if(Derelict_OS_Windows) 8 enum libNames = "libPortMidi.dll"; 9 10 else static if(Derelict_OS_Mac) 11 enum libNames = "libportmidi.dylib, /usr/local/lib/libportmidi.dylib"; 12 13 else static if(Derelict_OS_Posix) 14 enum libNames = "libportmidi.so, /usr/local/lib/libportmidi.so"; 15 16 else 17 static assert(0, "Need to implement libportmidi libNames for this operating system."); 18 } 19 20 enum int PM_DEFAULT_SYSEX_BUFFER_SIZE = 1024; 21 22 enum int HDRLENGTH = 50; 23 enum uint PM_HOST_ERROR_MSG_LEN = 256; 24 enum int pmNoDevice = -1; 25 26 enum { 27 PM_FILT_ACTIVE = (1 << 0x0E), 28 PM_FILT_SYSEX = (1 << 0x00), 29 PM_FILT_CLOCK = (1 << 0x08), 30 PM_FILT_PLAY = ((1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B)), 31 PM_FILT_TICK = (1 << 0x09), 32 PM_FILT_FD = (1 << 0x0D), 33 PM_FILT_UNDEFINED = PM_FILT_FD, 34 PM_FILT_RESET = (1 << 0X0F), 35 PM_FILT_REALTIME = PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK | 36 PM_FILT_PLAY | PM_FILT_UNDEFINED | PM_FILT_RESET | PM_FILT_TICK, 37 38 PM_FILT_NOTE = ((1 << 0x19) | (1 << 0x18)), 39 PM_FILT_CHANNEL_AFTERTOUCH = (1 << 0x1D), 40 PM_FILT_POLY_AFTERTOUCH = (1 << 0x1A), 41 PM_FILT_AFTERTOUCH = PM_FILT_CHANNEL_AFTERTOUCH | PM_FILT_POLY_AFTERTOUCH, 42 PM_FILT_PROGRAM = (1 << 0x1C), 43 PM_FILT_CONTROL = (1 << 0x1B), 44 PM_FILT_PITCHBEND = (1 << 0x1E), 45 PM_FILT_MTC = (1 << 0x01), 46 PM_FILT_SONG_POSITION = (1 << 0x02), 47 PM_FILT_SONG_SELECT = (1 << 0x03), 48 PM_FILT_TUNE = (1 << 0x06), 49 PM_FILT_SYSTEMCOMMON = (PM_FILT_MTC | PM_FILT_SONG_POSITION | PM_FILT_SONG_SELECT | PM_FILT_TUNE) 50 } 51 52 alias PmError = int; 53 54 enum : PmError { 55 pmNoError = 0, 56 pmHostError = -10000, 57 pmInvalidDeviceId, 58 pmInsufficientMemory, 59 pmBufferTooSmall, 60 pmBufferOverflow, 61 pmBadPtr, 62 pmBadData, 63 pmInternalError, 64 pmBufferMaxSize 65 } 66 67 alias PortMidiStream = void; 68 alias PmStream = PortMidiStream; 69 alias PmDeviceID = int; 70 alias PmTimestamp = long; 71 alias PmMessage = long; 72 73 //From pmutil.h 74 alias PmQueue = void; 75 76 extern(C) nothrow alias PmTimeProcPtr = PmTimestamp* function(void* time_info); 77 78 struct PmDeviceInfo { 79 int structVersion; 80 const char* interf; 81 const char* name; 82 int input; 83 int output; 84 int opened; 85 } 86 87 struct PmEvent 88 { 89 PmMessage message; 90 PmTimestamp timestamp; 91 } 92 93 //Replicates behavior of the following line in portmidi.h: 94 //#define PmBefore(t1,t2) ((t1-t2) < 0) 95 bool PmBefore(T)(T t1, T t2) { 96 return t1 - t2 < 0; 97 } 98 99 //Replicates the behavior of the following line in portmidi.h: 100 //#define Pm_Channel(channel) (1<<(channel)) 101 int Pm_Channel(int channel) { 102 return 1 << channel; 103 } 104 105 //Replicates the Pm_Message* macros in portmidi.h 106 PmMessage Pm_Message(long status, long data1, long data2) { 107 return ((data2 << 16) & 0xff0000) | ((data1 << 8) & 0xff00) | (status & 0xff); 108 } 109 110 long Pm_MessageStatus(PmMessage msg) { 111 return msg & 0xff; 112 } 113 114 long Pm_MessageData1(PmMessage msg) { 115 return (msg >> 8) & 0xff; 116 } 117 118 long Pm_MessageData2(PmMessage msg) { 119 return (msg >> 16) & 0xff; 120 } 121 122 extern(C) @nogc nothrow { 123 alias da_Pm_Initialize = PmError function(); 124 alias da_Pm_Terminate = PmError function(); 125 alias da_Pm_HasHostError = int function(PortMidiStream* stream); 126 alias da_Pm_GetErrorText = const(char)* function(PmError errnum); 127 alias da_Pm_GetHostErrorText = const(char)* function(char* msg, uint len); 128 alias da_Pm_CountDevices = int function(); 129 alias da_Pm_GetDefaultInputDeviceID = PmDeviceID function(); 130 alias da_Pm_GetDefaultOutputDeviceID = PmDeviceID function(); 131 alias da_Pm_GetDeviceInfo = const(PmDeviceInfo)* function(PmDeviceID id); 132 133 alias da_Pm_OpenInput = PmError function( PortMidiStream** stream, 134 PmDeviceID inputDevice, 135 void* inputDriverInfo, 136 long bufferSize, 137 PmTimeProcPtr time_proc, 138 void* time_info); 139 140 alias da_Pm_OpenOutput = PmError function( PortMidiStream** stream, 141 PmDeviceID outputDevice, 142 void* outputDriverInfo, 143 long bufferSize, 144 PmTimeProcPtr time_proc, 145 void* time_info, 146 long latency); 147 148 alias da_Pm_SetFilter = PmError function(PortMidiStream* stream, long filters); 149 alias da_Pm_SetChannelMask = PmError function(PortMidiStream* stream, int mask); 150 alias da_Pm_Abort = PmError function(PortMidiStream* stream); 151 alias da_Pm_Close = PmError function(PortMidiStream* stream); 152 alias da_Pm_Read = int function(PortMidiStream* stream, PmEvent* buffer, long length); 153 alias da_Pm_Poll = PmError function(PortMidiStream* stream); 154 alias da_Pm_Write = PmError function(PortMidiStream* stream, PmEvent* buffer, long length); 155 alias da_Pm_WriteShort = PmError function(PortMidiStream* stream, PmTimestamp when, long msg); 156 alias da_Pm_WriteSysEx = PmError function(PortMidiStream* stream, PmTimestamp when, ubyte* msg); 157 158 //From pmutil.h 159 alias da_Pm_QueueCreate = PmQueue* function(long num_msgs, int bytes_per_msg); 160 alias da_Pm_QueueDestroy = PmError function(PmQueue* queue); 161 alias da_Pm_Dequeue = PmError function(PmQueue* queue, void* msg); 162 alias da_Pm_Enqueue = PmError function(PmQueue* queue, void* msg); 163 alias da_Pm_QueueFull = int function(PmQueue* queue); 164 alias da_Pm_QueueEmpty = int function(PmQueue* queue); 165 alias da_Pm_QueuePeek = void* function(PmQueue* queue); 166 alias da_Pm_SetOverflow = PmError function(PmQueue* queue); 167 } 168 169 __gshared { 170 da_Pm_Initialize Pm_Initialize; 171 da_Pm_Terminate Pm_Terminate; 172 da_Pm_HasHostError Pm_HasHostError; 173 da_Pm_GetErrorText Pm_GetErrorText; 174 da_Pm_GetHostErrorText Pm_GetHostErrorText; 175 da_Pm_CountDevices Pm_CountDevices; 176 da_Pm_GetDefaultInputDeviceID Pm_GetDefaultInputDeviceID; 177 da_Pm_GetDefaultOutputDeviceID Pm_GetDefaultOutputDeviceID; 178 da_Pm_GetDeviceInfo Pm_GetDeviceInfo; 179 da_Pm_OpenInput Pm_OpenInput; 180 da_Pm_OpenOutput Pm_OpenOutput; 181 da_Pm_SetFilter Pm_SetFilter; 182 da_Pm_SetChannelMask Pm_SetChannelMask; 183 da_Pm_Abort Pm_Abort; 184 da_Pm_Close Pm_Close; 185 da_Pm_Read Pm_Read; 186 da_Pm_Poll Pm_Poll; 187 da_Pm_Write Pm_Write; 188 da_Pm_WriteShort Pm_WriteShort; 189 da_Pm_WriteSysEx Pm_WriteSysEx; 190 191 //From pmutil.h 192 da_Pm_QueueCreate Pm_QueueCreate; 193 da_Pm_QueueDestroy Pm_QueueDestroy; 194 da_Pm_Dequeue Pm_Dequeue; 195 da_Pm_Enqueue Pm_Enqueue; 196 da_Pm_QueueFull Pm_QueueFull; 197 da_Pm_QueueEmpty Pm_QueueEmpty; 198 da_Pm_QueuePeek Pm_QueuePeek; 199 da_Pm_SetOverflow Pm_SetOverflow; 200 201 } 202 203 class DerelictPortMidiLoader : SharedLibLoader { 204 public this() { 205 super(libNames); 206 } 207 208 protected override void loadSymbols() { 209 bindFunc(cast(void**)&Pm_Initialize, "Pm_Initialize"); 210 bindFunc(cast(void**)&Pm_Terminate, "Pm_Terminate"); 211 bindFunc(cast(void**)&Pm_HasHostError, "Pm_HasHostError"); 212 bindFunc(cast(void**)&Pm_GetErrorText, "Pm_GetErrorText"); 213 bindFunc(cast(void**)&Pm_GetHostErrorText, "Pm_GetHostErrorText"); 214 bindFunc(cast(void**)&Pm_CountDevices, "Pm_CountDevices"); 215 bindFunc(cast(void**)&Pm_GetDefaultInputDeviceID, "Pm_GetDefaultInputDeviceID"); 216 bindFunc(cast(void**)&Pm_GetDefaultOutputDeviceID, "Pm_GetDefaultOutputDeviceID"); 217 bindFunc(cast(void**)&Pm_GetDeviceInfo, "Pm_GetDeviceInfo"); 218 bindFunc(cast(void**)&Pm_OpenInput, "Pm_OpenInput"); 219 bindFunc(cast(void**)&Pm_OpenOutput, "Pm_OpenOutput"); 220 bindFunc(cast(void**)&Pm_SetFilter, "Pm_SetFilter"); 221 bindFunc(cast(void**)&Pm_SetChannelMask, "Pm_SetChannelMask"); 222 bindFunc(cast(void**)&Pm_Abort, "Pm_Abort"); 223 bindFunc(cast(void**)&Pm_Close, "Pm_Close"); 224 bindFunc(cast(void**)&Pm_Read, "Pm_Read"); 225 bindFunc(cast(void**)&Pm_Poll, "Pm_Poll"); 226 bindFunc(cast(void**)&Pm_Write, "Pm_Write"); 227 bindFunc(cast(void**)&Pm_WriteShort, "Pm_WriteShort"); 228 bindFunc(cast(void**)&Pm_WriteSysEx, "Pm_WriteSysEx"); 229 230 //From pmutil.h 231 bindFunc(cast(void**)&Pm_QueueCreate, "Pm_QueueCreate"); 232 bindFunc(cast(void**)&Pm_QueueDestroy, "Pm_QueueDestroy"); 233 bindFunc(cast(void**)&Pm_Dequeue, "Pm_Dequeue"); 234 bindFunc(cast(void**)&Pm_Enqueue, "Pm_Enqueue"); 235 bindFunc(cast(void**)&Pm_QueueFull, "Pm_QueueFull"); 236 bindFunc(cast(void**)&Pm_QueueEmpty, "Pm_QueueEmpty"); 237 bindFunc(cast(void**)&Pm_QueuePeek, "Pm_QueuePeek"); 238 bindFunc(cast(void**)&Pm_SetOverflow, "Pm_SetOverflow"); 239 } 240 } 241 242 __gshared DerelictPortMidiLoader DerelictPortMidi; 243 244 shared static this() { 245 DerelictPortMidi = new DerelictPortMidiLoader; 246 } 247