/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: src/drivers/wintel32/audio/wintel32midisystem.cpp

*/

#include "drivers/wintel32/core/core.hpp"

#include <mmsystem.h>

#include "sgx/core/core.hpp"
#include "sgx/audio/midi.hpp"

#include "drivers/wintel32/audio/wintel32midiindevice.hpp"

static void CALLBACK MidiInCallback(HMIDIIN hMidiIn,  UINT wMsg,  tINT32 dwInstance, tINT32 dwParam1,   tINT32 dwParam2);

sgxMidiInDevice *
sgxMidiSystem::openMidiIn(sgxMidiIn *pClassHandler, void *pSystem)
{
	HMIDIIN deviceHandle;

	if (0 != midiInOpen(&deviceHandle, 0, (DWORD)MidiInCallback, (DWORD)pClassHandler, CALLBACK_FUNCTION)) {
		return NULL;
	}
	return (sgxMidiInDevice *)new CDeviceWintel32MidiInDevice(deviceHandle);
}

sgxMidiOutDevice *
sgxMidiSystem::openMidiOut(sgxMidiOut *pClassHandler, void *pSystem)
{
	return NULL;
}

static void CALLBACK 
MidiInCallback(HMIDIIN hMidiIn,  UINT wMsg,  tINT32 dwInstance, tINT32 param1,   tINT32 param2) {
	sgxMidiIn *ptr = (sgxMidiIn *)dwInstance;

	if(wMsg == MIM_DATA) {
		int loByte = param1 & 255;
		int chanmsg = loByte & 0xf0;
		int channel = loByte & 0x0f;

		switch(loByte) {
			case srtTimingClock:
				ptr->midiClockprocess();
				break;

			case srtStart:
			case srtContinue:
				ptr->start();
				break;
			
			case srtStop:
				ptr->stop();
				break;
			case srtActiveSensing:
				break;
			case srtSystemReset:
				break;
			default:
				if (chanmsg == msgNoteOn && (param1&0xff0000) == 0) {
					chanmsg = msgNoteOff;
				}
				ptr->midiEventprocess(chanmsg, channel, (param1&0xff00)>>8, (param1&0xff0000)>>16);
				break;
		}
	}
}

