annotate core/Midi.cpp @ 553:e545ce04cf2c prerelease

Updated Makefile to take LDFLAGS=, LDLIBS=, CFLAGS=, CPPFLAGS=
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 24 Jun 2016 17:13:45 +0100
parents e4392164b458
children
rev   line source
giuliomoro@181 1 /*
giuliomoro@181 2 * Midi.cpp
giuliomoro@181 3 *
giuliomoro@181 4 * Created on: 15 Jan 2016
giuliomoro@181 5 * Author: giulio
giuliomoro@181 6 */
giuliomoro@181 7
giuliomoro@181 8 #include "Midi.h"
giuliomoro@181 9 #include <fcntl.h>
giuliomoro@181 10 #include <errno.h>
giuliomoro@181 11
giuliomoro@191 12 #define kMidiInput 0
giuliomoro@191 13 #define kMidiOutput 1
giuliomoro@191 14
giuliomoro@197 15
giuliomoro@197 16 midi_byte_t midiMessageStatusBytes[midiMessageStatusBytesLength]=
giuliomoro@197 17 {
giuliomoro@197 18 0x80,
giuliomoro@197 19 0x90,
giuliomoro@197 20 0xA0,
giuliomoro@197 21 0xB0,
giuliomoro@197 22 0xC0,
giuliomoro@197 23 0xD0,
giuliomoro@197 24 0xE0,
giuliomoro@197 25 0
giuliomoro@197 26 };
giuliomoro@197 27
giuliomoro@197 28 unsigned int midiMessageNumDataBytes[midiMessageStatusBytesLength]={2, 2, 2, 2, 1, 1, 2, 0};
giuliomoro@197 29
giuliomoro@181 30 bool Midi::staticConstructed;
giuliomoro@181 31 AuxiliaryTask Midi::midiInputTask;
giuliomoro@181 32 AuxiliaryTask Midi::midiOutputTask;
giuliomoro@191 33 std::vector<Midi *> Midi::objAddrs[2];
giuliomoro@181 34
giuliomoro@197 35 int MidiParser::parse(midi_byte_t* input, unsigned int length){
giuliomoro@197 36 unsigned int consumedBytes = 0;
giuliomoro@197 37 for(unsigned int n = 0; n < length; n++){
giuliomoro@197 38 consumedBytes++;
giuliomoro@197 39 if(waitingForStatus == true){
giuliomoro@197 40 int statusByte = input[n];
giuliomoro@197 41 MidiMessageType newType = kmmNone;
giuliomoro@197 42 if (statusByte >= 0x80){//it actually is a status byte
giuliomoro@197 43 for(int n = 0; n < midiMessageStatusBytesLength; n++){ //find the statusByte in the array
giuliomoro@197 44 if(midiMessageStatusBytes[n] == (statusByte&0xf0)){
giuliomoro@197 45 newType = (MidiMessageType)n;
giuliomoro@197 46 break;
giuliomoro@197 47 }
giuliomoro@197 48 }
giuliomoro@197 49 elapsedDataBytes = 0;
giuliomoro@197 50 waitingForStatus = false;
giuliomoro@197 51 messages[writePointer].setType(newType);
giuliomoro@197 52 messages[writePointer].setChannel((midi_byte_t)(statusByte&0xf));
giuliomoro@197 53 consumedBytes++;
giuliomoro@197 54 } else { // either something went wrong or it's a system message
giuliomoro@197 55 continue;
giuliomoro@197 56 }
giuliomoro@197 57 } else {
giuliomoro@197 58 messages[writePointer].setDataByte(elapsedDataBytes, input[n]);
giuliomoro@197 59 elapsedDataBytes++;
giuliomoro@197 60 if(elapsedDataBytes == messages[writePointer].getNumDataBytes()){
giuliomoro@224 61 // done with the current message
giuliomoro@224 62 // call the callback if available
giuliomoro@224 63 if(isCallbackEnabled() == true){
giuliomoro@226 64 messageReadyCallback(getNextChannelMessage(), callbackArg);
giuliomoro@224 65 }
giuliomoro@197 66 waitingForStatus = true;
giuliomoro@197 67 writePointer++;
giuliomoro@197 68 if(writePointer == messages.size()){
giuliomoro@197 69 writePointer = 0;
giuliomoro@197 70 }
giuliomoro@197 71 }
giuliomoro@197 72 }
giuliomoro@197 73 }
giuliomoro@224 74
giuliomoro@197 75 return consumedBytes;
giuliomoro@197 76 };
giuliomoro@197 77
giuliomoro@197 78
giuliomoro@181 79 Midi::Midi(){
giuliomoro@181 80 outputPort = -1;
giuliomoro@181 81 inputPort = -1;
giuliomoro@197 82 inputParser = 0;
giuliomoro@181 83 size_t inputBytesInitialSize = 1000;
giuliomoro@181 84 inputBytes.resize(inputBytesInitialSize);
giuliomoro@191 85 outputBytes.resize(inputBytesInitialSize);
giuliomoro@181 86 inputBytesWritePointer = 0;
giuliomoro@181 87 inputBytesReadPointer = inputBytes.size() - 1;
giuliomoro@181 88 if(!staticConstructed){
giuliomoro@181 89 staticConstructor();
giuliomoro@181 90 }
giuliomoro@181 91 }
giuliomoro@181 92
giuliomoro@181 93 void Midi::staticConstructor(){
giuliomoro@181 94 staticConstructed = true;
giuliomoro@301 95 midiInputTask = Bela_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiInput");
giuliomoro@301 96 midiOutputTask = Bela_createAuxiliaryTask(Midi::midiOutputLoop, 50, "MidiOutupt");
giuliomoro@181 97 }
giuliomoro@181 98
giuliomoro@181 99 Midi::~Midi(){}
giuliomoro@197 100
giuliomoro@197 101 void Midi::enableParser(bool enable){
giuliomoro@197 102 if(enable == true){
giuliomoro@197 103 delete inputParser;
giuliomoro@197 104 inputParser = new MidiParser();
giuliomoro@197 105 parserEnabled = true;
giuliomoro@197 106 } else {
giuliomoro@197 107 delete inputParser;
giuliomoro@197 108 parserEnabled = false;
giuliomoro@197 109 }
giuliomoro@197 110 }
giuliomoro@197 111
giuliomoro@191 112 void Midi::midiInputLoop(){
giuliomoro@191 113 for(unsigned int n = 0; n < objAddrs[kMidiInput].size(); n++){
giuliomoro@191 114 objAddrs[kMidiInput][n] -> readInputLoop();
giuliomoro@191 115 }
giuliomoro@191 116 }
giuliomoro@181 117
giuliomoro@191 118 void Midi::midiOutputLoop(){
giuliomoro@191 119 for(unsigned int n = 0; n < objAddrs[kMidiOutput].size(); n++){
giuliomoro@191 120 objAddrs[kMidiOutput][n] -> writeOutputLoop();
giuliomoro@181 121 }
giuliomoro@181 122 }
giuliomoro@181 123
giuliomoro@181 124 void Midi::readInputLoop(){
giuliomoro@181 125 while(!gShouldStop){
giuliomoro@181 126 int maxBytesToRead = inputBytes.size() - inputBytesWritePointer;
giuliomoro@181 127 int ret = read(inputPort, &inputBytes[inputBytesWritePointer], sizeof(midi_byte_t)*maxBytesToRead);
giuliomoro@181 128 if(ret < 0){
giuliomoro@181 129 if(errno != EAGAIN){ // read() would return EAGAIN when no data are available to read just now
giuliomoro@181 130 rt_printf("Error while reading midi %d\n", errno);
giuliomoro@181 131 }
giuliomoro@181 132 usleep(1000);
giuliomoro@181 133 continue;
giuliomoro@181 134 }
giuliomoro@181 135 inputBytesWritePointer += ret;
giuliomoro@181 136 if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around
giuliomoro@181 137 inputBytesWritePointer = 0;
giuliomoro@181 138 }
giuliomoro@224 139
giuliomoro@197 140 if(parserEnabled == true && ret > 0){ // if the parser is enabled and there is new data, send the data to it
giuliomoro@197 141 int input;
giuliomoro@199 142 while((input=_getInput()) >= 0){
giuliomoro@197 143 midi_byte_t inputByte = (midi_byte_t)(input);
giuliomoro@197 144 inputParser->parse(&inputByte, 1);
giuliomoro@197 145 }
giuliomoro@197 146 }
giuliomoro@181 147 if(ret < maxBytesToRead){ //no more data to retrieve at the moment
giuliomoro@181 148 usleep(1000);
giuliomoro@197 149 } // otherwise there might be more data ready to be read (we were at the end of the buffer), so don't sleep
giuliomoro@181 150 }
giuliomoro@181 151 }
giuliomoro@181 152
giuliomoro@191 153 void Midi::writeOutputLoop(){
giuliomoro@191 154 while(!gShouldStop){
giuliomoro@191 155 usleep(1000);
giuliomoro@191 156 int length = outputBytesWritePointer - outputBytesReadPointer;
giuliomoro@191 157 if(length < 0){
giuliomoro@191 158 length = outputBytes.size() - outputBytesReadPointer;
giuliomoro@191 159 }
giuliomoro@191 160 if(length == 0){ //nothing to be written
giuliomoro@191 161 continue;
giuliomoro@191 162 }
giuliomoro@191 163 int ret;
giuliomoro@191 164 ret = write(outputPort, &outputBytes[outputBytesReadPointer], sizeof(midi_byte_t)*length);
giuliomoro@191 165 if(ret < 0){ //error occurred
giuliomoro@191 166 rt_printf("error occurred while writing: %d\n", errno);
giuliomoro@191 167 usleep(10000); //wait before retrying
giuliomoro@191 168 continue;
giuliomoro@191 169 }
giuliomoro@191 170 }
giuliomoro@191 171 }
giuliomoro@181 172 int Midi::readFrom(int port){
giuliomoro@191 173 objAddrs[kMidiInput].push_back(this);
giuliomoro@181 174 inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY);
giuliomoro@181 175 if(inputPort < 0){
giuliomoro@181 176 return -1;
giuliomoro@181 177 } else {
giuliomoro@228 178 printf("Reading from Midi port %d\n", port);
giuliomoro@301 179 Bela_scheduleAuxiliaryTask(midiInputTask);
giuliomoro@181 180 return 1;
giuliomoro@181 181 }
giuliomoro@181 182 }
giuliomoro@181 183
giuliomoro@191 184 int Midi::writeTo(int port){
giuliomoro@191 185 objAddrs[kMidiOutput].push_back(this);
giuliomoro@191 186 outputPort = open("/dev/midi1", O_WRONLY, 0);
giuliomoro@191 187 if(outputPort < 0){
giuliomoro@191 188 return -1;
giuliomoro@191 189 } else {
giuliomoro@191 190 printf("Writing to Midi port %d\n", port);
giuliomoro@301 191 Bela_scheduleAuxiliaryTask(midiOutputTask);
giuliomoro@191 192 return 1;
giuliomoro@191 193 }
giuliomoro@191 194 }
giuliomoro@191 195
giuliomoro@199 196 int Midi::_getInput(){
giuliomoro@181 197 if(inputPort < 0)
giuliomoro@181 198 return -2;
giuliomoro@181 199 if(inputBytesReadPointer == inputBytesWritePointer){
giuliomoro@181 200 return -1; // no bytes to read
giuliomoro@181 201 }
giuliomoro@181 202 midi_byte_t inputMessage = inputBytes[inputBytesReadPointer++];
giuliomoro@181 203 if(inputBytesReadPointer == inputBytes.size()){ // wrap pointer
giuliomoro@181 204 inputBytesReadPointer = 0;
giuliomoro@181 205 }
giuliomoro@181 206 return inputMessage;
giuliomoro@181 207 }
giuliomoro@191 208
giuliomoro@199 209 int Midi::getInput(){
giuliomoro@199 210 if(parserEnabled == true) {
giuliomoro@199 211 return -3;
giuliomoro@199 212 }
giuliomoro@199 213 return _getInput();
giuliomoro@199 214 }
giuliomoro@199 215
giuliomoro@197 216 MidiParser* Midi::getParser(){
giuliomoro@197 217 if(parserEnabled == false){
giuliomoro@197 218 return 0;
giuliomoro@197 219 }
giuliomoro@197 220 return inputParser;
giuliomoro@197 221 };
giuliomoro@197 222
giuliomoro@191 223 int Midi::writeOutput(midi_byte_t byte){
giuliomoro@191 224 return writeOutput(&byte, 1);
giuliomoro@191 225 }
giuliomoro@191 226
giuliomoro@191 227 int Midi::writeOutput(midi_byte_t* bytes, unsigned int length){
giuliomoro@191 228 int ret = write(outputPort, bytes, length);
giuliomoro@191 229 if(ret < 0)
giuliomoro@191 230 return -1;
giuliomoro@191 231 else
giuliomoro@191 232 return 1;
giuliomoro@191 233 }
giuliomoro@197 234
giuliomoro@197 235 MidiChannelMessage::MidiChannelMessage(){};
giuliomoro@197 236 MidiChannelMessage::MidiChannelMessage(MidiMessageType type){
giuliomoro@197 237 setType(type);
giuliomoro@197 238 };
giuliomoro@197 239 MidiChannelMessage::~MidiChannelMessage(){};
giuliomoro@197 240 MidiMessageType MidiChannelMessage::getType(){
giuliomoro@197 241 return _type;
giuliomoro@197 242 };
giuliomoro@197 243 int MidiChannelMessage::getChannel(){
giuliomoro@197 244 return _channel;
giuliomoro@197 245 };
giuliomoro@197 246 //int MidiChannelMessage::set(midi_byte_t* input);
giuliomoro@197 247 //
giuliomoro@197 248 //int MidiControlChangeMessage ::getValue();
giuliomoro@197 249 //int MidiControlChangeMessage::set(midi_byte_t* input){
giuliomoro@197 250 // channel = input[0];
giuliomoro@197 251 // number = input[1];
giuliomoro@197 252 // value = input[2];
giuliomoro@197 253 // return 3;
giuliomoro@197 254 //}
giuliomoro@197 255
giuliomoro@197 256 //int MidiNoteMessage::getNote();
giuliomoro@197 257 //int MidiNoteMessage::getVelocity();
giuliomoro@197 258
giuliomoro@197 259 //midi_byte_t MidiProgramChangeMessage::getProgram();