Skip to content

Latest commit

 

History

History
312 lines (277 loc) · 7.53 KB

native_midi_win32.c

File metadata and controls

312 lines (277 loc) · 7.53 KB
 
Dec 31, 2011
Dec 31, 2011
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
native_midi: Hardware Midi support for the SDL_mixer library
Copyright (C) 2000,2001 Florian 'Proff' Schulze <florian.proff.schulze@gmx.net>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Apr 30, 2006
Apr 30, 2006
21
#include "SDL_config.h"
22
23
24
/* everything below is currently one very big bad hack ;) Proff */
Apr 30, 2006
Apr 30, 2006
25
#if __WIN32__
Aug 19, 2001
Aug 19, 2001
26
27
28
29
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
30
31
32
33
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "native_midi.h"
Sep 6, 2001
Sep 6, 2001
34
#include "native_midi_common.h"
Aug 19, 2001
Aug 19, 2001
35
36
37
38
struct _NativeMidiSong {
int MusicLoaded;
int MusicPlaying;
Jan 1, 2012
Jan 1, 2012
39
40
41
int Loops;
int CurrentHdr;
MIDIHDR MidiStreamHdr[2];
Aug 19, 2001
Aug 19, 2001
42
MIDIEVENT *NewEvents;
Jan 1, 2012
Jan 1, 2012
43
Uint16 ppqn;
Sep 6, 2001
Sep 6, 2001
44
int Size;
Aug 19, 2001
Aug 19, 2001
45
46
47
int NewPos;
};
48
49
50
51
52
53
54
55
static UINT MidiDevice=MIDI_MAPPER;
static HMIDISTRM hMidiStream;
static NativeMidiSong *currentsong;
static int BlockOut(NativeMidiSong *song)
{
MMRESULT err;
int BlockSize;
Jan 1, 2012
Jan 1, 2012
56
MIDIHDR *hdr;
57
58
59
if ((song->MusicLoaded) && (song->NewEvents))
{
Jan 1, 2012
Jan 1, 2012
60
61
62
63
// proff 12/8/98: Added for safety
song->CurrentHdr = !song->CurrentHdr;
hdr = &song->MidiStreamHdr[song->CurrentHdr];
midiOutUnprepareHeader((HMIDIOUT)hMidiStream,hdr,sizeof(MIDIHDR));
Sep 6, 2001
Sep 6, 2001
64
if (song->NewPos>=song->Size)
65
return 0;
Sep 6, 2001
Sep 6, 2001
66
BlockSize=(song->Size-song->NewPos);
67
68
69
70
if (BlockSize<=0)
return 0;
if (BlockSize>36000)
BlockSize=36000;
Jan 1, 2012
Jan 1, 2012
71
hdr->lpData=(void *)((unsigned char *)song->NewEvents+song->NewPos);
72
song->NewPos+=BlockSize;
Jan 1, 2012
Jan 1, 2012
73
74
75
76
77
hdr->dwBufferLength=BlockSize;
hdr->dwBytesRecorded=BlockSize;
hdr->dwFlags=0;
hdr->dwOffset=0;
err=midiOutPrepareHeader((HMIDIOUT)hMidiStream,hdr,sizeof(MIDIHDR));
78
79
if (err!=MMSYSERR_NOERROR)
return 0;
Jan 1, 2012
Jan 1, 2012
80
err=midiStreamOut(hMidiStream,hdr,sizeof(MIDIHDR));
81
82
83
84
85
return 0;
}
return 1;
}
Sep 6, 2001
Sep 6, 2001
86
static void MIDItoStream(NativeMidiSong *song, MIDIEvent *evntlist)
Sep 6, 2001
Sep 6, 2001
88
89
90
91
92
93
94
int eventcount;
MIDIEvent *event;
MIDIEVENT *newevent;
eventcount=0;
event=evntlist;
while (event)
Sep 6, 2001
Sep 6, 2001
96
97
eventcount++;
event=event->next;
Sep 6, 2001
Sep 6, 2001
99
100
101
102
103
104
105
106
107
song->NewEvents=malloc(eventcount*3*sizeof(DWORD));
if (!song->NewEvents)
return;
memset(song->NewEvents,0,(eventcount*3*sizeof(DWORD)));
eventcount=0;
event=evntlist;
newevent=song->NewEvents;
while (event)
Sep 6, 2001
Sep 6, 2001
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
int status = (event->status&0xF0)>>4;
switch (status)
{
case MIDI_STATUS_NOTE_OFF:
case MIDI_STATUS_NOTE_ON:
case MIDI_STATUS_AFTERTOUCH:
case MIDI_STATUS_CONTROLLER:
case MIDI_STATUS_PROG_CHANGE:
case MIDI_STATUS_PRESSURE:
case MIDI_STATUS_PITCH_WHEEL:
newevent->dwDeltaTime=event->time;
newevent->dwEvent=(event->status|0x80)|(event->data[0]<<8)|(event->data[1]<<16)|(MEVT_SHORTMSG<<24);
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
eventcount++;
break;
case MIDI_STATUS_SYSEX:
if (event->status == 0xFF && event->data[0] == 0x51) /* Tempo change */
{
int tempo = (event->extraData[0] << 16) |
(event->extraData[1] << 8) |
event->extraData[2];
newevent->dwDeltaTime=event->time;
newevent->dwEvent=(MEVT_TEMPO<<24) | tempo;
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
eventcount++;
}
break;
Sep 6, 2001
Sep 6, 2001
138
139
140
141
142
143
144
145
146
147
event=event->next;
}
song->Size=eventcount*3*sizeof(DWORD);
{
int time;
int temptime;
148
song->NewPos=0;
Sep 6, 2001
Sep 6, 2001
149
150
151
time=0;
newevent=song->NewEvents;
while (song->NewPos<song->Size)
Sep 6, 2001
Sep 6, 2001
153
154
155
156
157
158
temptime=newevent->dwDeltaTime;
newevent->dwDeltaTime-=time;
time=temptime;
if ((song->NewPos+12)>=song->Size)
newevent->dwEvent |= MEVT_F_CALLBACK;
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
159
160
161
song->NewPos+=12;
}
}
Sep 6, 2001
Sep 6, 2001
162
163
song->NewPos=0;
song->MusicLoaded=1;
164
165
}
Sep 26, 2009
Sep 26, 2009
166
167
void CALLBACK MidiProc( HMIDIIN hMidi, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2 )
168
169
170
171
{
switch( uMsg )
{
case MOM_DONE:
Jan 1, 2012
Jan 1, 2012
172
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)&currentsong->MidiStreamHdr[currentsong->CurrentHdr]))
173
174
175
BlockOut(currentsong);
break;
case MOM_POSITIONCB:
Jan 1, 2012
Jan 1, 2012
176
177
178
179
180
181
182
183
184
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)&currentsong->MidiStreamHdr[currentsong->CurrentHdr])) {
if (currentsong->Loops) {
--currentsong->Loops;
currentsong->NewPos=0;
BlockOut(currentsong);
} else {
currentsong->MusicPlaying=0;
}
}
185
186
187
188
189
190
break;
default:
break;
}
}
Aug 19, 2001
Aug 19, 2001
191
int native_midi_detect()
192
193
194
195
{
MMRESULT merr;
HMIDISTRM MidiStream;
Sep 26, 2009
Sep 26, 2009
196
merr=midiStreamOpen(&MidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
197
198
if (merr!=MMSYSERR_NOERROR)
return 0;
Sep 26, 2009
Sep 26, 2009
199
200
midiStreamClose(MidiStream);
return 1;
201
202
}
Dec 31, 2011
Dec 31, 2011
203
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw)
Jul 9, 2005
Jul 9, 2005
204
{
Jul 16, 2005
Jul 16, 2005
205
206
207
208
NativeMidiSong *newsong;
MIDIEvent *evntlist = NULL;
newsong=malloc(sizeof(NativeMidiSong));
Dec 31, 2011
Dec 31, 2011
209
210
211
212
if (!newsong) {
if (freerw) {
SDL_RWclose(rw);
}
Jul 16, 2005
Jul 16, 2005
213
return NULL;
Dec 31, 2011
Dec 31, 2011
214
}
Jul 16, 2005
Jul 16, 2005
215
216
217
218
219
220
221
memset(newsong,0,sizeof(NativeMidiSong));
/* Attempt to load the midi file */
evntlist = CreateMIDIEventList(rw, &newsong->ppqn);
if (!evntlist)
{
free(newsong);
Dec 31, 2011
Dec 31, 2011
222
223
224
if (freerw) {
SDL_RWclose(rw);
}
Jul 16, 2005
Jul 16, 2005
225
226
227
228
229
230
231
return NULL;
}
MIDItoStream(newsong, evntlist);
FreeMIDIEventList(evntlist);
Dec 31, 2011
Dec 31, 2011
232
233
234
if (freerw) {
SDL_RWclose(rw);
}
Jul 16, 2005
Jul 16, 2005
235
return newsong;
Jul 9, 2005
Jul 9, 2005
236
237
}
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
void native_midi_freesong(NativeMidiSong *song)
{
if (hMidiStream)
{
midiStreamStop(hMidiStream);
midiStreamClose(hMidiStream);
}
if (song)
{
if (song->NewEvents)
free(song->NewEvents);
free(song);
}
}
Jan 1, 2012
Jan 1, 2012
253
void native_midi_start(NativeMidiSong *song, int loops)
254
255
256
257
258
259
260
{
MMRESULT merr;
MIDIPROPTIMEDIV mptd;
native_midi_stop();
if (!hMidiStream)
{
Feb 16, 2010
Feb 16, 2010
261
merr=midiStreamOpen(&hMidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
262
263
if (merr!=MMSYSERR_NOERROR)
{
Feb 16, 2010
Feb 16, 2010
264
hMidiStream = NULL; // should I do midiStreamClose(hMidiStream) before?
265
266
267
268
269
270
return;
}
//midiStreamStop(hMidiStream);
currentsong=song;
currentsong->NewPos=0;
currentsong->MusicPlaying=1;
Jan 1, 2012
Jan 1, 2012
271
currentsong->Loops=loops;
272
mptd.cbStruct=sizeof(MIDIPROPTIMEDIV);
Sep 6, 2001
Sep 6, 2001
273
mptd.dwTimeDiv=currentsong->ppqn;
274
275
276
277
278
279
280
281
282
283
284
285
286
merr=midiStreamProperty(hMidiStream,(LPBYTE)&mptd,MIDIPROP_SET | MIDIPROP_TIMEDIV);
BlockOut(song);
merr=midiStreamRestart(hMidiStream);
}
}
void native_midi_stop()
{
if (!hMidiStream)
return;
midiStreamStop(hMidiStream);
midiStreamClose(hMidiStream);
currentsong=NULL;
Feb 16, 2010
Feb 16, 2010
287
hMidiStream = NULL;
288
289
290
291
292
293
294
295
296
}
int native_midi_active()
{
return currentsong->MusicPlaying;
}
void native_midi_setvolume(int volume)
{
Oct 6, 2003
Oct 6, 2003
297
298
299
300
301
302
303
304
int calcVolume;
if (volume > 128)
volume = 128;
if (volume < 0)
volume = 0;
calcVolume = (65535 * volume / 128);
midiOutSetVolume((HMIDIOUT)hMidiStream, MAKELONG(calcVolume , calcVolume));
305
306
}
Sep 26, 2009
Sep 26, 2009
307
const char *native_midi_error(void)
308
309
310
311
{
return "";
}
Aug 19, 2001
Aug 19, 2001
312
#endif /* Windows native MIDI support */