aboutsummaryrefslogtreecommitdiff
path: root/backends/midi/ypa1.cpp
blob: 6766af341f60883bc2caf20831a7b43c7babf913 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "stdafx.h"
#include "sound/mpu401.h"
#include "common/engine.h"	// for warning/error/debug

#include "Pa1Lib.h"

class MidiDriver_YamahaPa1:public MidiDriver_MPU401 {
public:
	MidiDriver_YamahaPa1();
	int open();
	void close();
	void send(uint32 b);

private:
	UInt8 _midiHandle;
	Boolean _isOpen;
 };

MidiDriver_YamahaPa1::MidiDriver_YamahaPa1() {
	_isOpen = false;
	_midiHandle = 0;
}

int MidiDriver_YamahaPa1::open()
{
	if (!(_isOpen = Pa1Lib_midiOpen(NULL, &_midiHandle)))
		return MERR_DEVICE_NOT_AVAILABLE;

	Pa1Lib_midiControlChange(_midiHandle,0,120,0); // all sound off
	Pa1Lib_midiControlChange(_midiHandle,0,121,0); // reset all controller
	Pa1Lib_midiControlChange(_midiHandle,0,123,0); // all not off

	return 0;
}

void MidiDriver_YamahaPa1::close()
{
	if (_isOpen) {
		Pa1Lib_midiControlChange(_midiHandle,0,120,0); // all sound off
		Pa1Lib_midiControlChange(_midiHandle,0,121,0); // reset all controller
		Pa1Lib_midiControlChange(_midiHandle,0,123,0); // all not off
		Pa1Lib_midiClose(_midiHandle);
	}
}

void MidiDriver_YamahaPa1::send(uint32 b)
{
	if (!_isOpen)
		return;

	UInt8 midiCmd[4];
	UInt8 chanID,mdCmd;

	midiCmd[3] = (b & 0xFF000000) >> 24;
	midiCmd[2] = (b & 0x00FF0000) >> 16;
	midiCmd[1] = (b & 0x0000FF00) >> 8;
	midiCmd[0] = (b & 0x000000FF);
	
	chanID = (midiCmd[0] & 0x0F) ;
	mdCmd = midiCmd[0] & 0xF0;
	
	switch (mdCmd) {
		case 0x80:	// note off
			Pa1Lib_midiNoteOff(_midiHandle, chanID, midiCmd[1], 0);
			break;
	
		case 0x90:	// note on
			Pa1Lib_midiNoteOn(_midiHandle, chanID, midiCmd[1], midiCmd[2]);
			break;
		
		case 0xB0:	// control change
			Pa1Lib_midiControlChange(_midiHandle, chanID, midiCmd[1], midiCmd[2]);
			break;
		
		case 0xC0:	// progam change
			Pa1Lib_midiProgramChange(_midiHandle, chanID, midiCmd[1]);
			break;
		
		case 0xE0:	// pitchBend
			Pa1Lib_midiPitchBend(_midiHandle, chanID, (short)(midiCmd[1] | (midiCmd[2] << 8)));
			break;
	}
}

MidiDriver *MidiDriver_YamahaPa1_create()
{
	return new MidiDriver_YamahaPa1();
}

//////////////////////////////////////////
// thread emu
static struct {
	bool active;
	int old_time;
	int sleep;

} g_thread;

static bool t_first_call = false;

int MidiDriver_MPU401::midi_driver_thread(void *param) {
	MidiDriver_MPU401 *mid = (MidiDriver_MPU401 *)param;
	int cur_time;

	if (!t_first_call)	
	{
		g_thread.active = false;
		g_thread.old_time = g_system->get_msecs();
		g_thread.sleep = 10;
		t_first_call = true;
	}

	cur_time = g_system->get_msecs();
	if (cur_time - g_thread.old_time >= g_thread.sleep)
		g_thread.active = true;

	if (g_thread.active)
	{
		cur_time = g_system->get_msecs();
		while (g_thread.old_time < cur_time) {
			g_thread.old_time += 10;
			// Don't use mid->_se_on_timer()
			// We must come in through IMuseMonitor to protect
			// against conflicts with script access to IMuse.
			if (mid->_timer_proc)
				(*(mid->_timer_proc)) (mid->_timer_param);
		}
		g_thread.active = false;
	}

	return 0;
}