annotate core/Midi.cpp @ 269:ac8eb07afcf5

Oxygen text added to each render.cpp file for the default projects. Text includes project explanation from Wiki, edited in places. Empty project added as a default project. Doxyfile updated. Each of the project locations added to INPUT configuration option. Consider just watching the whole project file so all new projects are automatically pulled through.
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:40:16 +0100
parents a0a7f00cf98d
children e4392164b458
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@181 95 midiInputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiInput");
giuliomoro@191 96 midiOutputTask = BeagleRT_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@181 179 BeagleRT_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@191 191 BeagleRT_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();