Skip to content

Latest commit

 

History

History
306 lines (271 loc) · 7.69 KB

native_midi_win32.c

File metadata and controls

306 lines (271 loc) · 7.69 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)
May 22, 2013
May 22, 2013
109
110
111
112
113
114
115
116
117
118
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:
Sep 6, 2001
Sep 6, 2001
119
newevent->dwDeltaTime=event->time;
May 22, 2013
May 22, 2013
120
newevent->dwEvent=(event->status|0x80)|(event->data[0]<<8)|(event->data[1]<<16)|(MEVT_SHORTMSG<<24);
Sep 6, 2001
Sep 6, 2001
121
122
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
eventcount++;
May 22, 2013
May 22, 2013
123
break;
Sep 6, 2001
Sep 6, 2001
124
May 22, 2013
May 22, 2013
125
126
127
128
129
130
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];
Sep 6, 2001
Sep 6, 2001
131
newevent->dwDeltaTime=event->time;
May 22, 2013
May 22, 2013
132
newevent->dwEvent=(MEVT_TEMPO<<24) | tempo;
Sep 6, 2001
Sep 6, 2001
133
134
newevent=(MIDIEVENT*)((char*)newevent+(3*sizeof(DWORD)));
eventcount++;
May 22, 2013
May 22, 2013
135
136
}
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
}
Jun 2, 2013
Jun 2, 2013
203
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *src, int freesrc)
Jul 9, 2005
Jul 9, 2005
204
{
May 22, 2013
May 22, 2013
205
206
NativeMidiSong *newsong;
MIDIEvent *evntlist = NULL;
Jul 16, 2005
Jul 16, 2005
207
May 22, 2013
May 22, 2013
208
209
210
211
212
newsong=malloc(sizeof(NativeMidiSong));
if (!newsong) {
return NULL;
}
memset(newsong,0,sizeof(NativeMidiSong));
Jul 16, 2005
Jul 16, 2005
213
May 22, 2013
May 22, 2013
214
/* Attempt to load the midi file */
Jun 2, 2013
Jun 2, 2013
215
evntlist = CreateMIDIEventList(src, &newsong->ppqn);
May 22, 2013
May 22, 2013
216
217
218
219
220
if (!evntlist)
{
free(newsong);
return NULL;
}
Jul 16, 2005
Jul 16, 2005
221
May 22, 2013
May 22, 2013
222
MIDItoStream(newsong, evntlist);
Jul 16, 2005
Jul 16, 2005
223
May 22, 2013
May 22, 2013
224
FreeMIDIEventList(evntlist);
Jul 16, 2005
Jul 16, 2005
225
Jun 2, 2013
Jun 2, 2013
226
227
if (freesrc) {
SDL_RWclose(src);
May 22, 2013
May 22, 2013
228
229
}
return newsong;
Jul 9, 2005
Jul 9, 2005
230
231
}
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
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
247
void native_midi_start(NativeMidiSong *song, int loops)
248
249
250
251
252
253
254
{
MMRESULT merr;
MIDIPROPTIMEDIV mptd;
native_midi_stop();
if (!hMidiStream)
{
Feb 16, 2010
Feb 16, 2010
255
merr=midiStreamOpen(&hMidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
256
257
if (merr!=MMSYSERR_NOERROR)
{
Feb 16, 2010
Feb 16, 2010
258
hMidiStream = NULL; // should I do midiStreamClose(hMidiStream) before?
259
260
261
262
263
264
return;
}
//midiStreamStop(hMidiStream);
currentsong=song;
currentsong->NewPos=0;
currentsong->MusicPlaying=1;
Jan 1, 2012
Jan 1, 2012
265
currentsong->Loops=loops;
266
mptd.cbStruct=sizeof(MIDIPROPTIMEDIV);
Sep 6, 2001
Sep 6, 2001
267
mptd.dwTimeDiv=currentsong->ppqn;
268
269
270
271
272
273
274
275
276
277
278
279
280
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
281
hMidiStream = NULL;
282
283
284
285
286
287
288
289
290
}
int native_midi_active()
{
return currentsong->MusicPlaying;
}
void native_midi_setvolume(int volume)
{
Oct 6, 2003
Oct 6, 2003
291
292
293
294
295
296
297
298
int calcVolume;
if (volume > 128)
volume = 128;
if (volume < 0)
volume = 0;
calcVolume = (65535 * volume / 128);
midiOutSetVolume((HMIDIOUT)hMidiStream, MAKELONG(calcVolume , calcVolume));
299
300
}
Sep 26, 2009
Sep 26, 2009
301
const char *native_midi_error(void)
302
303
304
305
{
return "";
}
Aug 19, 2001
Aug 19, 2001
306
#endif /* Windows native MIDI support */