view core/Midi.cpp @ 184:9108a0a34cb8

Better(non ideal) monophonic behaviour of the basic midi implementation. Would require to remember what notes are being held down and release either the most recent or low/high priority.
author Giulio Moro <giuliomoro@yahoo.it>
date Sun, 17 Jan 2016 21:56:13 +0000
parents 391ad036557d
children b3a306da03e0
line wrap: on
line source
/*
 * Midi.cpp
 *
 *  Created on: 15 Jan 2016
 *      Author: giulio
 */

#include "Midi.h"
#include <fcntl.h>
#include <errno.h>

bool Midi::staticConstructed;
AuxiliaryTask Midi::midiInputTask;
AuxiliaryTask Midi::midiOutputTask;
std::vector<Midi *> Midi::objAddrs(0);

Midi::Midi(){
	outputPort = -1;
	inputPort = -1;
	size_t inputBytesInitialSize = 1000;
	inputBytes.resize(inputBytesInitialSize);
	inputBytesWritePointer = 0;
	inputBytesReadPointer = inputBytes.size() - 1;
	if(!staticConstructed){
		staticConstructor();
	}
}

void Midi::staticConstructor(){
	staticConstructed = true;
	midiInputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiInput");
	midiOutputTask = BeagleRT_createAuxiliaryTask(Midi::midiInputLoop, 50, "MidiOutupt");
}

Midi::~Midi(){}

void Midi::midiInputLoop(){
	printf("Midi input loop %d\n", objAddrs.size());
	for(unsigned int n = 0; n < objAddrs.size(); n++){
		objAddrs[n] -> readInputLoop();
	}
}

void Midi::readInputLoop(){
	while(!gShouldStop){
		int maxBytesToRead = inputBytes.size() - inputBytesWritePointer;
		int ret = read(inputPort, &inputBytes[inputBytesWritePointer], sizeof(midi_byte_t)*maxBytesToRead);
		static int count = 0;
		count++;
		if(ret < 0){
			if(errno != EAGAIN){ // read() would return EAGAIN when no data are available to read just now
				rt_printf("Error while reading midi %d\n", errno);
			}
			usleep(1000);
			continue;
		}
		inputBytesWritePointer += ret;
		if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around
			inputBytesWritePointer = 0;
		}
		if(ret < maxBytesToRead){ //no more data to retrieve at the moment
			usleep(1000);
		} // otherwise there might be more data ready to be read, so don't sleep
	}
}

int Midi::readFrom(int port){
	objAddrs.push_back(this);
	inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY);
	if(inputPort < 0){
		printf("Error occurred while opening midi port %d: %d", port, inputPort);
		return -1;
	} else {
		printf("Reading from port %d\n", inputPort);
		BeagleRT_scheduleAuxiliaryTask(midiInputTask);
		return 1;
	}
}

int  Midi::getInput(){
	if(inputPort < 0)
		return -2;
	if(inputBytesReadPointer == inputBytesWritePointer){
		return -1; // no bytes to read
	}
	midi_byte_t inputMessage = inputBytes[inputBytesReadPointer++];
	if(inputBytesReadPointer == inputBytes.size()){ // wrap pointer
		inputBytesReadPointer = 0;
	}
	return inputMessage;
}