view core/Midi.cpp @ 191:b3a306da03e0

Implemented Midi output
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 03 Feb 2016 01:18:30 +0000
parents 9108a0a34cb8
children 265a527f8be8
line wrap: on
line source
/*
 * Midi.cpp
 *
 *  Created on: 15 Jan 2016
 *      Author: giulio
 */

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

#define kMidiInput 0
#define kMidiOutput 1

bool Midi::staticConstructed;
AuxiliaryTask Midi::midiInputTask;
AuxiliaryTask Midi::midiOutputTask;
std::vector<Midi *> Midi::objAddrs[2];

Midi::Midi(){
	outputPort = -1;
	inputPort = -1;
	size_t inputBytesInitialSize = 1000;
	inputBytes.resize(inputBytesInitialSize);
	outputBytes.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::midiOutputLoop, 50, "MidiOutupt");
}

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

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

void Midi::readInputLoop(){
	while(!gShouldStop){
		int maxBytesToRead = inputBytes.size() - inputBytesWritePointer;
		int ret = read(inputPort, &inputBytes[inputBytesWritePointer], sizeof(midi_byte_t)*maxBytesToRead);
		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
	}
}

void Midi::writeOutputLoop(){
	while(!gShouldStop){
		usleep(1000);
		int length = outputBytesWritePointer - outputBytesReadPointer;
		if(length < 0){
			length = outputBytes.size() - outputBytesReadPointer;
		}
		if(length == 0){ //nothing to be written
			continue;
		}
		int ret;
		ret = write(outputPort, &outputBytes[outputBytesReadPointer], sizeof(midi_byte_t)*length);
		if(ret < 0){ //error occurred
//			if(errno != EAGAIN){ // () would return EAGAIN when no data are available to read just now
//				rt_printf("Error while writing midi %d\n", errno);
//			}
			rt_printf("error occurred while writing: %d\n", errno);
			usleep(10000); //wait before retrying
			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[kMidiInput].push_back(this);
	inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY);
	if(inputPort < 0){
		printf("Error occurred while opening midi input port %d: %d", port, inputPort);
		return -1;
	} else {
		printf("Reading from port %d\n", port);
		BeagleRT_scheduleAuxiliaryTask(midiInputTask);
		return 1;
	}
}

int Midi::writeTo(int port){
	objAddrs[kMidiOutput].push_back(this);
	outputPort = open("/dev/midi1", O_WRONLY, 0);
	if(outputPort < 0){
		printf("Error occurred while opening midi output port %d: %d", port, outputPort);
		return -1;
	} else {
		printf("Writing to Midi port %d\n", port);
		BeagleRT_scheduleAuxiliaryTask(midiOutputTask);
		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;
}

int Midi::writeOutput(midi_byte_t byte){
	return writeOutput(&byte, 1);
}

int Midi::writeOutput(midi_byte_t* bytes, unsigned int length){
	int ret = write(outputPort, bytes, length);
	if(ret < 0)
		return -1;
	else
		return 1;
}