Skip to content

Latest commit

 

History

History
321 lines (284 loc) · 7.94 KB

native_midi_win32.c

File metadata and controls

321 lines (284 loc) · 7.94 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
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)&currentsong->MidiStreamHdr[currentsong->CurrentHdr])) {
if (currentsong->Loops) {
Jul 9, 2013
Jul 9, 2013
178
179
if (currentsong->Loops > 0)
--currentsong->Loops;
Jan 1, 2012
Jan 1, 2012
180
181
182
183
184
185
currentsong->NewPos=0;
BlockOut(currentsong);
} else {
currentsong->MusicPlaying=0;
}
}
186
187
188
189
190
191
break;
default:
break;
}
}
Oct 17, 2017
Oct 17, 2017
192
int native_midi_detect(void)
193
194
195
196
{
MMRESULT merr;
HMIDISTRM MidiStream;
Sep 26, 2009
Sep 26, 2009
197
merr=midiStreamOpen(&MidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
198
199
if (merr!=MMSYSERR_NOERROR)
return 0;
Sep 26, 2009
Sep 26, 2009
200
201
midiStreamClose(MidiStream);
return 1;
202
203
}
Jun 2, 2013
Jun 2, 2013
204
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *src, int freesrc)
Jul 9, 2005
Jul 9, 2005
205
{
May 22, 2013
May 22, 2013
206
207
NativeMidiSong *newsong;
MIDIEvent *evntlist = NULL;
Jul 16, 2005
Jul 16, 2005
208
May 22, 2013
May 22, 2013
209
210
211
212
213
newsong=malloc(sizeof(NativeMidiSong));
if (!newsong) {
return NULL;
}
memset(newsong,0,sizeof(NativeMidiSong));
Jul 16, 2005
Jul 16, 2005
214
May 22, 2013
May 22, 2013
215
/* Attempt to load the midi file */
Jun 2, 2013
Jun 2, 2013
216
evntlist = CreateMIDIEventList(src, &newsong->ppqn);
May 22, 2013
May 22, 2013
217
218
219
220
221
if (!evntlist)
{
free(newsong);
return NULL;
}
Jul 16, 2005
Jul 16, 2005
222
May 22, 2013
May 22, 2013
223
MIDItoStream(newsong, evntlist);
Jul 16, 2005
Jul 16, 2005
224
May 22, 2013
May 22, 2013
225
FreeMIDIEventList(evntlist);
Jul 16, 2005
Jul 16, 2005
226
Jun 2, 2013
Jun 2, 2013
227
228
if (freesrc) {
SDL_RWclose(src);
May 22, 2013
May 22, 2013
229
230
}
return newsong;
Jul 9, 2005
Jul 9, 2005
231
232
}
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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
248
void native_midi_start(NativeMidiSong *song, int loops)
249
250
251
252
253
254
255
{
MMRESULT merr;
MIDIPROPTIMEDIV mptd;
native_midi_stop();
if (!hMidiStream)
{
Feb 16, 2010
Feb 16, 2010
256
merr=midiStreamOpen(&hMidiStream,&MidiDevice,(DWORD)1,(DWORD_PTR)MidiProc,(DWORD_PTR)0,CALLBACK_FUNCTION);
257
258
if (merr!=MMSYSERR_NOERROR)
{
Feb 16, 2010
Feb 16, 2010
259
hMidiStream = NULL; // should I do midiStreamClose(hMidiStream) before?
260
261
262
263
264
265
return;
}
//midiStreamStop(hMidiStream);
currentsong=song;
currentsong->NewPos=0;
currentsong->MusicPlaying=1;
Jan 1, 2012
Jan 1, 2012
266
currentsong->Loops=loops;
267
mptd.cbStruct=sizeof(MIDIPROPTIMEDIV);
Sep 6, 2001
Sep 6, 2001
268
mptd.dwTimeDiv=currentsong->ppqn;
269
270
271
272
273
274
merr=midiStreamProperty(hMidiStream,(LPBYTE)&mptd,MIDIPROP_SET | MIDIPROP_TIMEDIV);
BlockOut(song);
merr=midiStreamRestart(hMidiStream);
}
}
Oct 18, 2017
Oct 18, 2017
275
276
277
278
279
280
281
282
283
284
285
286
287
288
void native_midi_pause(void)
{
if (!hMidiStream)
return;
midiStreamPause(hMidiStream);
}
void native_midi_resume(void)
{
if (!hMidiStream)
return;
midiStreamRestart(hMidiStream);
}
Oct 17, 2017
Oct 17, 2017
289
void native_midi_stop(void)
290
291
292
293
294
295
{
if (!hMidiStream)
return;
midiStreamStop(hMidiStream);
midiStreamClose(hMidiStream);
currentsong=NULL;
Feb 16, 2010
Feb 16, 2010
296
hMidiStream = NULL;
297
298
}
Oct 17, 2017
Oct 17, 2017
299
int native_midi_active(void)
300
301
302
303
304
305
{
return currentsong->MusicPlaying;
}
void native_midi_setvolume(int volume)
{
Oct 6, 2003
Oct 6, 2003
306
307
308
309
310
311
312
313
int calcVolume;
if (volume > 128)
volume = 128;
if (volume < 0)
volume = 0;
calcVolume = (65535 * volume / 128);
midiOutSetVolume((HMIDIOUT)hMidiStream, MAKELONG(calcVolume , calcVolume));
314
315
}
Sep 26, 2009
Sep 26, 2009
316
const char *native_midi_error(void)
317
318
319
320
{
return "";
}
Aug 19, 2001
Aug 19, 2001
321
#endif /* Windows native MIDI support */