1998-12-22 00:00:00 +00:00
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#include <windows.h>
|
|
|
|
#include <mmsystem.h>
|
|
|
|
|
|
|
|
#include "m_argv.h"
|
|
|
|
#include "i_music.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "c_consol.h"
|
|
|
|
#include "c_dispch.h"
|
|
|
|
#include "z_zone.h"
|
|
|
|
#include "mid2strm.h"
|
|
|
|
#include "mus2strm.h"
|
|
|
|
|
|
|
|
#include "../midas/include/midasdll.h"
|
|
|
|
|
|
|
|
#define TYPE_MUS 0
|
|
|
|
#define TYPE_MIDI 1
|
|
|
|
#define TYPE_MOD 2
|
|
|
|
|
|
|
|
#define STATE_STOPPED 0
|
|
|
|
#define STATE_PLAYING 1
|
|
|
|
#define STATE_PAUSED 2
|
|
|
|
|
|
|
|
struct MusInfo {
|
|
|
|
int type;
|
|
|
|
int status;
|
|
|
|
PSTREAMBUF currBuffer;
|
|
|
|
enum {
|
|
|
|
cb_play,
|
1999-02-17 00:00:00 +00:00
|
|
|
cb_die,
|
|
|
|
cb_dead
|
1998-12-22 00:00:00 +00:00
|
|
|
} callbackStatus;
|
|
|
|
union {
|
|
|
|
MIDASmodulePlayHandle handle;
|
|
|
|
HMIDISTRM midiStream;
|
|
|
|
};
|
|
|
|
union {
|
|
|
|
MIDASmodule module;
|
|
|
|
PSTREAMBUF buffers;
|
|
|
|
};
|
|
|
|
BOOL looping;
|
|
|
|
};
|
|
|
|
typedef struct MusInfo info_t;
|
|
|
|
|
|
|
|
static info_t *currSong;
|
|
|
|
static HANDLE BufferReturnEvent;
|
|
|
|
static int nomusic = 0;
|
|
|
|
static char modName[512];
|
|
|
|
static int musicvolume;
|
|
|
|
static DWORD midivolume;
|
|
|
|
static cvar_t *snd_mididevice;
|
|
|
|
static DWORD nummididevices;
|
|
|
|
static UINT mididevice;
|
|
|
|
|
|
|
|
void I_SetMIDIVolume (float volume)
|
|
|
|
{
|
|
|
|
DWORD wooba = (DWORD)(volume * 0xffff) & 0xffff;
|
|
|
|
midivolume = (wooba << 16) | wooba;
|
|
|
|
if (currSong && (currSong->type == TYPE_MIDI || currSong->type == TYPE_MUS))
|
|
|
|
midiOutSetVolume ((HMIDIOUT)currSong->midiStream, midivolume);
|
|
|
|
}
|
|
|
|
|
|
|
|
void I_SetMusicVolume (int volume)
|
|
|
|
{
|
|
|
|
if (volume != 127) {
|
|
|
|
// Internal state variable.
|
|
|
|
musicvolume = volume;
|
|
|
|
// Now set volume on output device.
|
|
|
|
if (currSong && currSong->type == TYPE_MOD)
|
|
|
|
MIDASsetMusicVolume (currSong->handle, musicvolume);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ChangeMIDIDevice (cvar_t *var)
|
|
|
|
{
|
|
|
|
UINT oldmididev = mididevice;
|
|
|
|
|
|
|
|
if (((int)var->value >= (signed)nummididevices) || (var->value < -1.0f)) {
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "ID out of range. Using MIDI mapper.\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
SetCVarFloat (var, -1.0f);
|
|
|
|
return;
|
|
|
|
} else if (var->value < 0) {
|
|
|
|
mididevice = MIDI_MAPPER;
|
|
|
|
} else {
|
|
|
|
mididevice = (int)var->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If a song is playing, move it to the new device.
|
|
|
|
if (oldmididev != mididevice && currSong) {
|
|
|
|
info_t *song = currSong;
|
|
|
|
I_StopSong ((int)song);
|
|
|
|
I_PlaySong ((int)song, song->looping);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ListMIDIDevices (void *plyr, int argc, char **argv)
|
|
|
|
{
|
|
|
|
UINT id;
|
|
|
|
MIDIOUTCAPS caps;
|
|
|
|
MMRESULT res;
|
|
|
|
|
|
|
|
if (nummididevices) {
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "-1. MIDI Mapper\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
} else {
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "No MIDI devices installed.\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (id = 0; id < nummididevices; id++) {
|
|
|
|
res = midiOutGetDevCaps (id, &caps, sizeof(caps));
|
|
|
|
if (res == MMSYSERR_NODRIVER) {
|
|
|
|
strcpy (caps.szPname, "<Driver not installed>");
|
|
|
|
} else if (res == MMSYSERR_NOMEM) {
|
|
|
|
strcpy (caps.szPname, "<No memory for description>");
|
|
|
|
} else if (res != MMSYSERR_NOERROR) {
|
|
|
|
continue;
|
|
|
|
}
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "% 2d. %s\n", id, caps.szPname);
|
1998-12-22 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void I_InitMusic (void)
|
|
|
|
{
|
|
|
|
char *temp;
|
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "I_InitMusic\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
|
|
|
|
snd_mididevice = cvar ("snd_mididevice", "-1", CVAR_ARCHIVE|CVAR_CALLBACK);
|
|
|
|
snd_mididevice->u.callback = ChangeMIDIDevice;
|
|
|
|
nummididevices = midiOutGetNumDevs ();
|
|
|
|
ChangeMIDIDevice (snd_mididevice);
|
|
|
|
C_RegisterCommand ("snd_listmididevices", ListMIDIDevices);
|
|
|
|
|
|
|
|
nomusic = !!M_CheckParm("-nomusic") || !!M_CheckParm("-nosound") || !nummididevices;
|
|
|
|
|
|
|
|
if (!nomusic) {
|
|
|
|
if ((BufferReturnEvent = CreateEvent (NULL, FALSE, FALSE, NULL)) == NULL) {
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "Could not create MIDI callback event.\nMIDI music will be disabled.\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
nomusic = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create temporary file name for MIDAS */
|
|
|
|
temp = getenv("TEMP");
|
|
|
|
if (temp == NULL)
|
|
|
|
temp = ".";
|
|
|
|
strcpy (modName, temp);
|
|
|
|
FixPathSeperator (modName);
|
|
|
|
|
|
|
|
while (modName[strlen(modName)-1] == '/')
|
|
|
|
modName[strlen(modName)-1] = 0;
|
|
|
|
|
|
|
|
strcat (modName, "/doommus.tmp");
|
|
|
|
|
|
|
|
atexit (I_ShutdownMusic);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
void STACK_ARGS I_ShutdownMusic(void)
|
1998-12-22 00:00:00 +00:00
|
|
|
{
|
|
|
|
if (currSong) {
|
|
|
|
I_UnRegisterSong ((int)currSong);
|
|
|
|
currSong = NULL;
|
|
|
|
}
|
|
|
|
remove (modName);
|
|
|
|
if (BufferReturnEvent)
|
|
|
|
CloseHandle (BufferReturnEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void MCIError (MMRESULT res, const char *descr)
|
|
|
|
{
|
|
|
|
char errorStr[256];
|
|
|
|
|
|
|
|
mciGetErrorString (res, errorStr, 255);
|
|
|
|
Printf_Bold ("An error occured while %s:\n", descr);
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "%s\n", errorStr);
|
1998-12-22 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void UnprepareMIDIHeaders (info_t *info)
|
|
|
|
{
|
|
|
|
PSTREAMBUF buffer = info->buffers;
|
|
|
|
|
|
|
|
while (buffer) {
|
|
|
|
if (buffer->prepared) {
|
|
|
|
MMRESULT res = midiOutUnprepareHeader ((HMIDIOUT)info->midiStream,
|
|
|
|
&buffer->midiHeader, sizeof(buffer->midiHeader));
|
|
|
|
if (res != MMSYSERR_NOERROR)
|
|
|
|
MCIError (res, "unpreparing headers");
|
|
|
|
else
|
|
|
|
buffer->prepared = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = buffer->pNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL PrepareMIDIHeaders (info_t *info)
|
|
|
|
{
|
|
|
|
MMRESULT res;
|
|
|
|
PSTREAMBUF buffer = info->buffers;
|
|
|
|
|
|
|
|
while (buffer) {
|
|
|
|
if (!buffer->prepared) {
|
|
|
|
memset (&buffer->midiHeader, 0, sizeof(MIDIHDR));
|
|
|
|
buffer->midiHeader.lpData = buffer->pBuffer;
|
|
|
|
buffer->midiHeader.dwBufferLength = CB_STREAMBUF;
|
|
|
|
buffer->midiHeader.dwBytesRecorded = CB_STREAMBUF - buffer->cbLeft;
|
|
|
|
res = midiOutPrepareHeader ((HMIDIOUT)info->midiStream,
|
|
|
|
&buffer->midiHeader, sizeof(MIDIHDR));
|
|
|
|
if (res != MMSYSERR_NOERROR) {
|
|
|
|
MCIError (res, "preparing headers");
|
|
|
|
UnprepareMIDIHeaders (info);
|
|
|
|
return false;
|
|
|
|
} else
|
|
|
|
buffer->prepared = true;
|
|
|
|
}
|
|
|
|
buffer = buffer->pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SubmitMIDIBuffer (info_t *info)
|
|
|
|
{
|
|
|
|
MMRESULT res;
|
|
|
|
|
|
|
|
res = midiStreamOut (info->midiStream,
|
|
|
|
&info->currBuffer->midiHeader, sizeof(MIDIHDR));
|
|
|
|
|
|
|
|
if (res != MMSYSERR_NOERROR)
|
|
|
|
MCIError (res, "sending MIDI stream");
|
|
|
|
|
|
|
|
info->currBuffer = info->currBuffer->pNext;
|
|
|
|
if (info->currBuffer == NULL && info->looping)
|
|
|
|
info->currBuffer = info->buffers;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void AllChannelsOff (info_t *info)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 16; i++)
|
|
|
|
midiOutShortMsg ((HMIDIOUT)info->midiStream, MIDI_NOTEOFF | i | (64<<16) | (60<<8));
|
|
|
|
Sleep (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CALLBACK MidiProc (HMIDIIN hMidi, UINT uMsg, info_t *info,
|
|
|
|
DWORD dwParam1, DWORD dwParam2 )
|
|
|
|
{
|
1999-02-17 00:00:00 +00:00
|
|
|
if (info->callbackStatus == cb_dead)
|
|
|
|
return;
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
switch (uMsg) {
|
|
|
|
case MOM_DONE:
|
1999-02-17 00:00:00 +00:00
|
|
|
if (info->callbackStatus == cb_die) {
|
1998-12-22 00:00:00 +00:00
|
|
|
SetEvent (BufferReturnEvent);
|
1999-02-17 00:00:00 +00:00
|
|
|
info->callbackStatus = cb_dead;
|
|
|
|
} else {
|
1998-12-22 00:00:00 +00:00
|
|
|
if (info->currBuffer == info->buffers) {
|
|
|
|
// Stop all notes before restarting the song
|
|
|
|
// in case any are left hanging.
|
|
|
|
AllChannelsOff (info);
|
|
|
|
} else if (info->currBuffer == NULL) {
|
|
|
|
SetEvent (BufferReturnEvent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SubmitMIDIBuffer (info);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void I_PlaySong (int handle, int _looping)
|
|
|
|
{
|
|
|
|
info_t *info = (info_t *)handle;
|
|
|
|
|
|
|
|
if (!info || nomusic)
|
|
|
|
return;
|
|
|
|
|
|
|
|
info->status = STATE_STOPPED;
|
|
|
|
info->looping = _looping;
|
|
|
|
|
|
|
|
switch (info->type) {
|
|
|
|
case TYPE_MUS:
|
|
|
|
case TYPE_MIDI: {
|
|
|
|
MMRESULT res;
|
|
|
|
|
|
|
|
// note: midiStreamOpen changes mididevice if it's set to MIDI_MAPPER
|
|
|
|
// (interesting undocumented behavior)
|
|
|
|
if ((res = midiStreamOpen (&info->midiStream,
|
|
|
|
&mididevice,
|
|
|
|
(DWORD)1, (DWORD)MidiProc,
|
|
|
|
(DWORD)info,
|
|
|
|
CALLBACK_FUNCTION)) == MMSYSERR_NOERROR)
|
|
|
|
{
|
|
|
|
MIDIPROPTIMEDIV timedivProp;
|
|
|
|
|
|
|
|
timedivProp.cbStruct = sizeof(timedivProp);
|
|
|
|
timedivProp.dwTimeDiv = midTimeDiv;
|
|
|
|
res = midiStreamProperty (info->midiStream, (LPBYTE)&timedivProp,
|
|
|
|
MIDIPROP_SET | MIDIPROP_TIMEDIV);
|
|
|
|
if (res != MMSYSERR_NOERROR)
|
|
|
|
MCIError (res, "setting time division");
|
|
|
|
|
|
|
|
res = midiOutSetVolume ((HMIDIOUT)info->midiStream, midivolume);
|
|
|
|
|
|
|
|
// Preload all instruments into soundcard RAM (if necessary).
|
|
|
|
// On my GUS PnP, this is necessary because it will fail to
|
|
|
|
// play some instruments on some songs until the song loops
|
|
|
|
// if the instrument isn't already in memory. (Why it doesn't
|
|
|
|
// load them when they're needed is beyond me, because it's only
|
|
|
|
// some instruments it doesn't play properly the first time--and
|
|
|
|
// I don't know exactly which ones those are.) The 250 ms delay
|
|
|
|
// between note on and note off is fairly lengthy, so I try and
|
|
|
|
// get the instruments going on multiple channels to reduce the
|
|
|
|
// number of times I have to sleep.
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
DPrintf ("MIDI uses instruments:\n");
|
|
|
|
for (i = j = 0; i < 127; i++)
|
|
|
|
if (UsedPatches[i]) {
|
|
|
|
DPrintf (" %d", i);
|
|
|
|
midiOutShortMsg ((HMIDIOUT)info->midiStream,
|
|
|
|
MIDI_PRGMCHANGE | (i<<8) | j);
|
|
|
|
midiOutShortMsg ((HMIDIOUT)info->midiStream,
|
|
|
|
MIDI_NOTEON | (60<<8) | (1<<16) | j);
|
|
|
|
if (++j == 10) {
|
|
|
|
Sleep (250);
|
|
|
|
for (j = 0; j < 10; j++)
|
|
|
|
midiOutShortMsg ((HMIDIOUT)info->midiStream,
|
|
|
|
MIDI_NOTEOFF | (60<<8) | (64<<16) | j);
|
|
|
|
j = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (j > 0) {
|
|
|
|
Sleep (250);
|
|
|
|
for (i = 0; i < j; i++)
|
|
|
|
midiOutShortMsg ((HMIDIOUT)info->midiStream,
|
|
|
|
MIDI_NOTEOFF | (60<<8) | (64<<16) | i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
DPrintf ("\nMIDI uses percussion keys:\n");
|
|
|
|
for (i = 0; i < 127; i++)
|
|
|
|
if (UsedPatches[i+128]) {
|
|
|
|
DPrintf (" %d", i);
|
|
|
|
midiOutShortMsg ((HMIDIOUT)info->midiStream,
|
|
|
|
MIDI_NOTEON | (i<<8) | (1<<16) | 10);
|
|
|
|
Sleep (235);
|
|
|
|
midiOutShortMsg ((HMIDIOUT)info->midiStream,
|
|
|
|
MIDI_NOTEOFF | (i<<8) | (64<<16));
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
DPrintf ("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PrepareMIDIHeaders (info)) {
|
|
|
|
info->callbackStatus = cb_play;
|
|
|
|
info->currBuffer = info->buffers;
|
|
|
|
SubmitMIDIBuffer (info);
|
|
|
|
res = midiStreamRestart (info->midiStream);
|
|
|
|
if (res == MMSYSERR_NOERROR)
|
|
|
|
info->status = STATE_PLAYING;
|
|
|
|
else {
|
|
|
|
MCIError (res, "starting playback");
|
|
|
|
UnprepareMIDIHeaders (info);
|
|
|
|
midiStreamClose (info->midiStream);
|
|
|
|
info->midiStream = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
UnprepareMIDIHeaders (info);
|
|
|
|
midiStreamClose (info->midiStream);
|
|
|
|
info->midiStream = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
MCIError (res, "opening MIDI stream");
|
|
|
|
if (snd_mididevice->value != -1) {
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "Trying again with MIDI mapper\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
SetCVarFloat (snd_mididevice, -1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TYPE_MOD:
|
|
|
|
if (info->handle = MIDASplayModule (info->module, _looping)) {
|
|
|
|
MIDASsetMusicVolume (info->handle, musicvolume);
|
|
|
|
info->status = STATE_PLAYING;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
currSong = info;
|
|
|
|
}
|
|
|
|
|
|
|
|
void I_PauseSong (int handle)
|
|
|
|
{
|
|
|
|
info_t *info = (info_t *)handle;
|
|
|
|
|
|
|
|
if (!info || info->status != STATE_PLAYING)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (info->type) {
|
|
|
|
case TYPE_MUS:
|
|
|
|
case TYPE_MIDI:
|
|
|
|
if (info->midiStream && midiStreamPause (info->midiStream) == MMSYSERR_NOERROR)
|
|
|
|
info->status = STATE_PAUSED;
|
|
|
|
break;
|
|
|
|
case TYPE_MOD:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void I_ResumeSong (int handle)
|
|
|
|
{
|
|
|
|
info_t *info = (info_t *)handle;
|
|
|
|
|
|
|
|
if (!info || info->status != STATE_PAUSED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (info->type) {
|
|
|
|
case TYPE_MUS:
|
|
|
|
case TYPE_MIDI:
|
|
|
|
if (info->midiStream && midiStreamRestart (info->midiStream) == MMSYSERR_NOERROR)
|
|
|
|
info->status = STATE_PLAYING;
|
|
|
|
break;
|
|
|
|
case TYPE_MOD:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void I_StopSong (int handle)
|
|
|
|
{
|
|
|
|
info_t *info = (info_t *)handle;
|
|
|
|
|
|
|
|
if (!info || info->status == STATE_STOPPED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
info->status = STATE_STOPPED;
|
|
|
|
|
|
|
|
switch (info->type) {
|
|
|
|
case TYPE_MUS:
|
|
|
|
case TYPE_MIDI:
|
|
|
|
if (info->midiStream) {
|
1999-02-17 00:00:00 +00:00
|
|
|
if (info->callbackStatus != cb_dead)
|
|
|
|
info->callbackStatus = cb_die;
|
1998-12-22 00:00:00 +00:00
|
|
|
midiStreamStop (info->midiStream);
|
1999-02-17 00:00:00 +00:00
|
|
|
WaitForSingleObject (BufferReturnEvent, 5000);
|
1998-12-22 00:00:00 +00:00
|
|
|
midiOutReset ((HMIDIOUT)info->midiStream);
|
|
|
|
UnprepareMIDIHeaders (info);
|
|
|
|
midiStreamClose (info->midiStream);
|
|
|
|
info->midiStream = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TYPE_MOD:
|
|
|
|
MIDASstopModule (info->handle);
|
|
|
|
info->handle = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (info == currSong)
|
|
|
|
currSong = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void I_UnRegisterSong (int handle)
|
|
|
|
{
|
|
|
|
info_t *info = (info_t *)handle;
|
|
|
|
|
|
|
|
if (info) {
|
|
|
|
I_StopSong (handle);
|
|
|
|
switch (info->type) {
|
|
|
|
case TYPE_MUS:
|
|
|
|
mus2strmCleanup ();
|
|
|
|
info->buffers = NULL;
|
|
|
|
break;
|
|
|
|
case TYPE_MIDI:
|
|
|
|
mid2strmCleanup ();
|
|
|
|
info->buffers = NULL;
|
|
|
|
break;
|
|
|
|
case TYPE_MOD:
|
|
|
|
MIDASfreeModule (info->module);
|
|
|
|
info->module = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free (info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int I_RegisterSong (void *data, int musicLen)
|
|
|
|
{
|
|
|
|
info_t *info;
|
|
|
|
|
|
|
|
if (!(info = malloc (sizeof(info_t))))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
info->status = STATE_STOPPED;
|
|
|
|
|
|
|
|
if (*(int *)data == (('M')|(('U')<<8)|(('S')<<16)|((0x1a)<<24))) {
|
|
|
|
// This is a mus file
|
|
|
|
info->type = TYPE_MUS;
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!nummididevices
|
|
|
|
|| !(info->buffers = mus2strmConvert ((LPBYTE)data, musicLen))) {
|
1998-12-22 00:00:00 +00:00
|
|
|
free (info);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (*(int *)data == (('M')|(('T')<<8)|(('h')<<16)|(('d')<<24))) {
|
|
|
|
// This is a midi file
|
|
|
|
info->type = TYPE_MIDI;
|
1999-02-17 00:00:00 +00:00
|
|
|
if (!nummididevices
|
|
|
|
|| !(info->buffers = mid2strmConvert ((LPBYTE)data, musicLen))) {
|
1998-12-22 00:00:00 +00:00
|
|
|
free (info);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
if ((f = fopen (modName, "wb")) == NULL) {
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "Unable to open temporary music file %s\n", modName);
|
1998-12-22 00:00:00 +00:00
|
|
|
free (info);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (fwrite (data, musicLen, 1, f) != 1) {
|
|
|
|
fclose (f);
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "Unable to write temporary music file\n");
|
1998-12-22 00:00:00 +00:00
|
|
|
free (info);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
if ( (info->module = MIDASloadModule (modName)) ) {
|
|
|
|
// This is a module
|
|
|
|
info->type = TYPE_MOD;
|
|
|
|
} else {
|
|
|
|
// This is not any known music format
|
|
|
|
// (or could not load mod)
|
|
|
|
free (info);
|
|
|
|
info = NULL;
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "midas failed to load song:\n%s\n", MIDASgetErrorMessage(MIDASgetLastError()));
|
1998-12-22 00:00:00 +00:00
|
|
|
}
|
|
|
|
remove (modName);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (int)info;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is the song playing?
|
|
|
|
int I_QrySongPlaying (int handle)
|
|
|
|
{
|
|
|
|
info_t *info = (info_t *)handle;
|
|
|
|
|
|
|
|
if (!info)
|
|
|
|
return 0;
|
|
|
|
else if (info->looping == 1)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return info->status;
|
|
|
|
}
|