⛏️ index : haiku.git

/*
 * Copyright 2006, Haiku.
 * 
 * Copyright (c) 2002-2003 Matthijs Hollemans
 * Copyright (c) 2002 Michael Pfeiffer
 * Copyright (c) 2002 Jerome Leveque
 * Copyright (c) 2002 Paul Stadler
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Matthijs Hollemans
 *		Michael Pfeiffer
 *		JΓ©rΓ΄me Leveque
 *		Paul Stadler
 */

#include <List.h>
#include <Midi.h>
#include <MidiProducer.h>

#include "MidiGlue.h"
#include "debug.h"

using namespace BPrivate;


status_t 
_run_thread(void* data)
{
	BMidi* midi = (BMidi*)data;
	midi->Run();
	midi->fIsRunning = false;
	return 0;
}


BMidi::BMidi()
{
	fConnections = new BList;
	fThreadId    = -1;
	fIsRunning   = false;

	fProducer = new BMidiLocalProducer("MidiGlue(out)");
	fConsumer = new BMidiGlue(this, "MidiGlue(in)");
}


BMidi::~BMidi()
{
	Stop();

	status_t result;
	wait_for_thread(fThreadId, &result);

	fProducer->Release();
	fConsumer->Release();

	delete fConnections;
}


void 
BMidi::NoteOff(uchar channel, uchar note, uchar velocity, uint32 time)
{
	// do nothing
}


void 
BMidi::NoteOn(uchar channel, uchar note, uchar velocity, uint32 time)
{
	// do nothing
}


void 
BMidi::KeyPressure(
	uchar channel, uchar note, uchar pressure, uint32 time)
{
	// do nothing
}


void 
BMidi::ControlChange(
	uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
{
	// do nothing
}


void 
BMidi::ProgramChange(uchar channel, uchar programNumber, uint32 time)
{
	// do nothing
}


void 
BMidi::ChannelPressure(uchar channel, uchar pressure, uint32 time)
{
	// do nothing
}


void 
BMidi::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
{
	// do nothing
}


void 
BMidi::SystemExclusive(void* data, size_t length, uint32 time)
{
	// do nothing
}


void 
BMidi::SystemCommon(uchar status, uchar data1, uchar data2, uint32 time)
{
	// do nothing
}


void 
BMidi::SystemRealTime(uchar status, uint32 time)
{
	// do nothing
}


void 
BMidi::TempoChange(int32 beatsPerMinute, uint32 time)
{
	// do nothing
}


void 
BMidi::AllNotesOff(bool justChannel, uint32 time)
{
	for (uchar channel = 1; channel <= 16; ++channel) {
		SprayControlChange(channel, B_ALL_NOTES_OFF, 0, time);

		if (!justChannel) {
			for (uchar note = 0; note <= 0x7F; ++note) {
				SprayNoteOff(channel, note, 0, time);
			}
		}
	}
}


status_t 
BMidi::Start()
{
	if (fIsRunning) 
		return B_OK;

	status_t err = spawn_thread(
		_run_thread, "MidiRunThread", B_URGENT_PRIORITY, this);

	if (err < B_OK) 
		return err;

	fThreadId  = err;
	fIsRunning = true;

	err = resume_thread(fThreadId);
	if (err != B_OK) {
		fThreadId  = -1;
		fIsRunning = false;
	}

	return err;
}


void 
BMidi::Stop()
{
	AllNotesOff();
	fThreadId = -1;
}
    

bool 
BMidi::IsRunning() const
{
	return fIsRunning;
}


void 
BMidi::Connect(BMidi* toObject)
{
	if (toObject != NULL) {
		if (fProducer->Connect(toObject->fConsumer) == B_OK) {
			fConnections->AddItem(toObject);
		}
	}
}


void 
BMidi::Disconnect(BMidi* fromObject)
{
	if (fromObject == NULL)
		return;

	if (fProducer->Disconnect(fromObject->fConsumer) == B_OK) {
		fConnections->RemoveItem(fromObject);
	}
}


bool 
BMidi::IsConnected(BMidi* toObject) const
{
	if (toObject != NULL)
		return fProducer->IsConnected(toObject->fConsumer);

	return false;
}


BList* 
BMidi::Connections() const
{
	return fConnections;
}


void 
BMidi::SnoozeUntil(uint32 time) const
{
	snooze_until(MAKE_BIGTIME(time), B_SYSTEM_TIMEBASE);
}


bool 
BMidi::KeepRunning()
{
	return (fThreadId != -1);
}


void BMidi::_ReservedMidi1() {}
void BMidi::_ReservedMidi2() {}
void BMidi::_ReservedMidi3() {}


void 
BMidi::Run()
{
	// do nothing
}


void 
BMidi::SprayNoteOff(
	uchar channel, uchar note, uchar velocity, uint32 time) const
{
	fProducer->SprayNoteOff(
		channel - 1, note, velocity, MAKE_BIGTIME(time));
}


void 
BMidi::SprayNoteOn(
	uchar channel, uchar note, uchar velocity, uint32 time) const
{
	fProducer->SprayNoteOn(
		channel - 1, note, velocity, MAKE_BIGTIME(time));
}


void 
BMidi::SprayKeyPressure(
	uchar channel, uchar note, uchar pressure, uint32 time) const
{
	fProducer->SprayKeyPressure(
		channel - 1, note, pressure, MAKE_BIGTIME(time));
}


void 
BMidi::SprayControlChange(
	uchar channel, uchar controlNumber, uchar controlValue, 
	uint32 time) const
{
	fProducer->SprayControlChange(
		channel - 1, controlNumber, controlValue, MAKE_BIGTIME(time));
}


void 
BMidi::SprayProgramChange(
	uchar channel, uchar programNumber, uint32 time) const
{
	fProducer->SprayProgramChange(
		channel - 1, programNumber, MAKE_BIGTIME(time));
}


void 
BMidi::SprayChannelPressure(
	uchar channel, uchar pressure, uint32 time) const
{
	fProducer->SprayChannelPressure(
		channel - 1, pressure, MAKE_BIGTIME(time));
}


void 
BMidi::SprayPitchBend(
	uchar channel, uchar lsb, uchar msb, uint32 time) const
{
	fProducer->SprayPitchBend(channel - 1, lsb, msb, MAKE_BIGTIME(time));
}


void 
BMidi::SpraySystemExclusive(
	void* data, size_t length, uint32 time) const
{
	fProducer->SpraySystemExclusive(data, length, MAKE_BIGTIME(time));
}


void 
BMidi::SpraySystemCommon(
	uchar status, uchar data1, uchar data2, uint32 time) const
{
	fProducer->SpraySystemCommon(status, data1, data2, MAKE_BIGTIME(time));
}


void 
BMidi::SpraySystemRealTime(uchar status, uint32 time) const
{
	fProducer->SpraySystemRealTime(status, MAKE_BIGTIME(time));
}


void 
BMidi::SprayTempoChange(int32 beatsPerMinute, uint32 time) const
{
	fProducer->SprayTempoChange(beatsPerMinute, MAKE_BIGTIME(time));
}