Skip to content

Latest commit

 

History

History
324 lines (287 loc) · 7.75 KB

native_midi_win32.c

File metadata and controls

324 lines (287 loc) · 7.75 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
}
Sep 26, 2009
Sep 26, 2009
203
NativeMidiSong *native_midi_loadsong(const char *midifile)
Dec 31, 2011
Dec 31, 2011
205
SDL_RWops *rw;
Sep 6, 2001
Sep 6, 2001
206
Jul 16, 2005
Jul 16, 2005
207
208
/* Attempt to load the midi file */
rw = SDL_RWFromFile(midifile, "rb");
Dec 31, 2011
Dec 31, 2011
209
210
if (!rw) {
return NULL;
Jul 16, 2005
Jul 16, 2005
211
}
Dec 31, 2011
Dec 31, 2011
212
return native_midi_loadsong_RW(rw, 1);
213
214
}
Dec 31, 2011
Dec 31, 2011
215
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw)
Jul 9, 2005
Jul 9, 2005
216
{
Jul 16, 2005
Jul 16, 2005
217
218
219
220
NativeMidiSong *newsong;
MIDIEvent *evntlist = NULL;
newsong=malloc(sizeof(NativeMidiSong));
Dec 31, 2011
Dec 31, 2011
221
222
223
224
if (!newsong) {
if (freerw) {
SDL_RWclose(rw);
}
Jul 16, 2005
Jul 16, 2005
225
return NULL;
Dec 31, 2011
Dec 31, 2011
226
}
Jul 16, 2005
Jul 16, 2005
227
228
229
230
231
232
233
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
234
235
236
if (freerw) {
SDL_RWclose(rw);
}
Jul 16, 2005
Jul 16, 2005
237
238
239
240
241
242
243
return NULL;
}
MIDItoStream(newsong, evntlist);
FreeMIDIEventList(evntlist);
Dec 31, 2011
Dec 31, 2011
244
245
246
if (freerw) {
SDL_RWclose(rw);
}
Jul 16, 2005
Jul 16, 2005
247
return newsong;
Jul 9, 2005
Jul 9, 2005
248
249
}
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
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
265
void native_midi_start(NativeMidiSong *song, int loops)
266
267
268
269
270
271
272
{
MMRESULT merr;
MIDIPROPTIMEDIV mptd;
native_midi_stop();
if (!hMidiStream)
{
Feb 16, 2010
Feb 16, 2010
273
merr=midiStreamOpen(&hMidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
274
275
if (merr!=MMSYSERR_NOERROR)
{
Feb 16, 2010
Feb 16, 2010
276
hMidiStream = NULL; // should I do midiStreamClose(hMidiStream) before?
277
278
279
280
281
282
return;
}
//midiStreamStop(hMidiStream);
currentsong=song;
currentsong->NewPos=0;
currentsong->MusicPlaying=1;
Jan 1, 2012
Jan 1, 2012
283
currentsong->Loops=loops;
284
mptd.cbStruct=sizeof(MIDIPROPTIMEDIV);
Sep 6, 2001
Sep 6, 2001
285
mptd.dwTimeDiv=currentsong->ppqn;
286
287
288
289
290
291
292
293
294
295
296
297
298
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
299
hMidiStream = NULL;
300
301
302
303
304
305
306
307
308
}
int native_midi_active()
{
return currentsong->MusicPlaying;
}
void native_midi_setvolume(int volume)
{
Oct 6, 2003
Oct 6, 2003
309
310
311
312
313
314
315
316
int calcVolume;
if (volume > 128)
volume = 128;
if (volume < 0)
volume = 0;
calcVolume = (65535 * volume / 128);
midiOutSetVolume((HMIDIOUT)hMidiStream, MAKELONG(calcVolume , calcVolume));
317
318
}
Sep 26, 2009
Sep 26, 2009
319
const char *native_midi_error(void)
320
321
322
323
{
return "";
}
Aug 19, 2001
Aug 19, 2001
324
#endif /* Windows native MIDI support */