Skip to content

Commit

Permalink
Better fix for looping on Mac OS X. This also gives event perfect loo…
Browse files Browse the repository at this point in the history
…ping on Windows and theoretically on Haiku.
  • Loading branch information
slouken committed Jan 1, 2012
1 parent 1423cb0 commit 091f055
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 70 deletions.
29 changes: 14 additions & 15 deletions music.c
Expand Up @@ -199,10 +199,17 @@ static int music_halt_or_loop (void)

if (!music_internal_playing())
{
/* Native MIDI handles looping internally */
if (music_playing->type == MUS_MID && native_midi_ok) {
music_loops = 0;
}

/* Restart music if it has to loop at a high level */
if (music_loops && --music_loops)
if (music_loops)
{
Mix_Fading current_fade = music_playing->fading;
Mix_Fading current_fade;
--music_loops;
current_fade = music_playing->fading;
music_internal_play(music_playing, 0.0);
music_playing->fading = current_fade;
}
Expand Down Expand Up @@ -791,7 +798,7 @@ static int music_internal_play(Mix_Music *music, double position)
case MUS_MID:
#ifdef USE_NATIVE_MIDI
if ( native_midi_ok ) {
native_midi_start(music->data.nativemidi);
native_midi_start(music->data.nativemidi, music_loops);
goto skip;
}
#endif
Expand Down Expand Up @@ -889,6 +896,10 @@ int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position)
SDL_LockAudio();
}
music_active = 1;
if (loops == 1) {
/* Loop is the number of times to play the audio */
loops = 0;
}
music_loops = loops;
retval = music_internal_play(music, position);
SDL_UnlockAudio();
Expand Down Expand Up @@ -920,18 +931,6 @@ int music_internal_position(double position)
MOD_jump_to_time(music_playing->data.module, position);
break;
#endif
#ifdef MID_MUSIC
case MUS_MID:
#ifdef USE_NATIVE_MIDI
if ( native_midi_ok ) {
retval = native_midi_jump_to_time(music_playing->data.nativemidi, position);
break;
}
#endif
/* TODO: Implement this for other music backends */
retval = -1;
break;
#endif
#ifdef OGG_MUSIC
case MUS_OGG:
OGG_jump_to_time(music_playing->data.ogg, position);
Expand Down
3 changes: 1 addition & 2 deletions native_midi/native_midi.h
Expand Up @@ -30,8 +30,7 @@ int native_midi_detect();
NativeMidiSong *native_midi_loadsong(const char *midifile);
NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw, int freerw);
void native_midi_freesong(NativeMidiSong *song);
void native_midi_start(NativeMidiSong *song);
int native_midi_jump_to_time(NativeMidiSong *song, double time);
void native_midi_start(NativeMidiSong *song, int loops);
void native_midi_stop();
int native_midi_active();
void native_midi_setvolume(int volume);
Expand Down
34 changes: 18 additions & 16 deletions native_midi/native_midi_haiku.cpp
Expand Up @@ -45,6 +45,7 @@ class MidiEventsStore : public BMidi
MidiEventsStore()
{
fPlaying = false;
fLoops = 0;
}
virtual status_t Import(SDL_RWops *rw)
{
Expand All @@ -66,8 +67,16 @@ class MidiEventsStore : public BMidi
MIDIEvent *ev = fEvs;

uint32 startTime = B_NOW;
while (KeepRunning() && ev)
while (KeepRunning())
{
if (!ev) {
if (fLoops && fEvs) {
--fLoops;
fPos = 0;
ev = fEvs;
} else
break;
}
SprayEvent(ev, ev->time + startTime);
ev = ev->next;
fPos++;
Expand All @@ -82,25 +91,22 @@ class MidiEventsStore : public BMidi
fEvs = 0;
}

int CurrentEvent()
{
return fPos;
}
int CountEvents()
bool IsPlaying()
{
return fTotal;
return fPlaying;
}

bool IsPlaying()
void SetLoops(int loops)
{
return fPlaying;
fLoops = loops;
}

protected:
MIDIEvent *fEvs;
Uint16 fDivision;

int fPos, fTotal;
int fLoops;
bool fPlaying;

void SprayEvent(MIDIEvent *ev, uint32 time)
Expand Down Expand Up @@ -251,18 +257,14 @@ void native_midi_freesong(NativeMidiSong *song)
delete song->store;
delete song; song = 0;
}
void native_midi_start(NativeMidiSong *song)
void native_midi_start(NativeMidiSong *song, int loops)
{
native_midi_stop();
song->store->Connect(&synth);
song->store->SetLoops(loops);
song->store->Start();
currentSong = song;
}
int native_midi_jump_to_time(NativeMidiSong *song, double time)
{
/* Not yet implemented */
return -1;
}
void native_midi_stop()
{
if (currentSong == NULL) return;
Expand All @@ -275,7 +277,7 @@ void native_midi_stop()
int native_midi_active()
{
if (currentSong == NULL) return 0;
return currentSong->store->CurrentEvent() < currentSong->store->CountEvents();
return currentSong->store->IsPlaying();
}

const char* native_midi_error(void)
Expand Down
11 changes: 4 additions & 7 deletions native_midi/native_midi_mac.c
Expand Up @@ -192,12 +192,15 @@ void native_midi_freesong(NativeMidiSong *song)
}
}

void native_midi_start(NativeMidiSong *song)
void native_midi_start(NativeMidiSong *song, int loops)
{
UInt32 queueFlags = 0;
ComponentResult tpError;

assert (gTunePlayer != NULL);

/* FIXME: is this code even used anymore? */
assert (loops == 0);

SDL_PauseAudio(1);
SDL_UnlockAudio();
Expand Down Expand Up @@ -254,12 +257,6 @@ void native_midi_start(NativeMidiSong *song)
SDL_PauseAudio(0);
}

int native_midi_jump_to_time(NativeMidiSong *song, double time)
{
/* Not yet implemented */
return -1;
}

void native_midi_stop()
{
if (gTunePlayer == NULL)
Expand Down
22 changes: 12 additions & 10 deletions native_midi/native_midi_macosx.c
Expand Up @@ -41,6 +41,7 @@ struct _NativeMidiSong
MusicSequence sequence;
MusicTimeStamp endTime;
AudioUnit audiounit;
int loops;
};

static NativeMidiSong *currentsong = NULL;
Expand Down Expand Up @@ -250,7 +251,7 @@ void native_midi_freesong(NativeMidiSong *song)
}
}

void native_midi_start(NativeMidiSong *song)
void native_midi_start(NativeMidiSong *song, int loops)
{
int vol;

Expand All @@ -264,6 +265,7 @@ void native_midi_start(NativeMidiSong *song)
MusicPlayerStop(currentsong->player);

currentsong = song;
currentsong->loops = loops;

MusicPlayerPreroll(song->player);
MusicPlayerSetTime(song->player, 0);
Expand All @@ -279,13 +281,6 @@ void native_midi_start(NativeMidiSong *song)
SDL_PauseAudio(0);
}

int native_midi_jump_to_time(NativeMidiSong *song, double time)
{
if (MusicPlayerSetTime(song->player, time) != noErr)
return -1;
return 0;
}

void native_midi_stop()
{
if (currentsong) {
Expand All @@ -305,8 +300,15 @@ int native_midi_active()
return 0;

MusicPlayerGetTime(currentsong->player, &currentTime);
return ((currentTime < currentsong->endTime) ||
(currentTime >= kMusicTimeStamp_EndOfTrack));
if ((currentTime < currentsong->endTime) ||
(currentTime >= kMusicTimeStamp_EndOfTrack)) {
return 1;
} else if (currentsong->loops) {
--currentsong->loops;
MusicPlayerSetTime(currentsong->player, 0);
return 1;
}
return 0;
}

void native_midi_setvolume(int volume)
Expand Down
48 changes: 28 additions & 20 deletions native_midi/native_midi_win32.c
Expand Up @@ -36,9 +36,11 @@
struct _NativeMidiSong {
int MusicLoaded;
int MusicPlaying;
MIDIHDR MidiStreamHdr;
int Loops;
int CurrentHdr;
MIDIHDR MidiStreamHdr[2];
MIDIEVENT *NewEvents;
Uint16 ppqn;
Uint16 ppqn;
int Size;
int NewPos;
};
Expand All @@ -51,27 +53,31 @@ static int BlockOut(NativeMidiSong *song)
{
MMRESULT err;
int BlockSize;
MIDIHDR *hdr;

if ((song->MusicLoaded) && (song->NewEvents))
{
// proff 12/8/98: Added for savety
midiOutUnprepareHeader((HMIDIOUT)hMidiStream,&song->MidiStreamHdr,sizeof(MIDIHDR));
// proff 12/8/98: Added for safety
song->CurrentHdr = !song->CurrentHdr;
hdr = &song->MidiStreamHdr[song->CurrentHdr];
midiOutUnprepareHeader((HMIDIOUT)hMidiStream,hdr,sizeof(MIDIHDR));
if (song->NewPos>=song->Size)
return 0;
BlockSize=(song->Size-song->NewPos);
if (BlockSize<=0)
return 0;
if (BlockSize>36000)
BlockSize=36000;
song->MidiStreamHdr.lpData=(void *)((unsigned char *)song->NewEvents+song->NewPos);
hdr->lpData=(void *)((unsigned char *)song->NewEvents+song->NewPos);
song->NewPos+=BlockSize;
song->MidiStreamHdr.dwBufferLength=BlockSize;
song->MidiStreamHdr.dwBytesRecorded=BlockSize;
song->MidiStreamHdr.dwFlags=0;
err=midiOutPrepareHeader((HMIDIOUT)hMidiStream,&song->MidiStreamHdr,sizeof(MIDIHDR));
hdr->dwBufferLength=BlockSize;
hdr->dwBytesRecorded=BlockSize;
hdr->dwFlags=0;
hdr->dwOffset=0;
err=midiOutPrepareHeader((HMIDIOUT)hMidiStream,hdr,sizeof(MIDIHDR));
if (err!=MMSYSERR_NOERROR)
return 0;
err=midiStreamOut(hMidiStream,&song->MidiStreamHdr,sizeof(MIDIHDR));
err=midiStreamOut(hMidiStream,hdr,sizeof(MIDIHDR));
return 0;
}
return 1;
Expand Down Expand Up @@ -163,12 +169,19 @@ void CALLBACK MidiProc( HMIDIIN hMidi, UINT uMsg, DWORD_PTR dwInstance,
switch( uMsg )
{
case MOM_DONE:
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)&currentsong->MidiStreamHdr))
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)&currentsong->MidiStreamHdr[currentsong->CurrentHdr]))
BlockOut(currentsong);
break;
case MOM_POSITIONCB:
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)&currentsong->MidiStreamHdr))
currentsong->MusicPlaying=0;
if ((currentsong->MusicLoaded) && (dwParam1 == (DWORD_PTR)&currentsong->MidiStreamHdr[currentsong->CurrentHdr])) {
if (currentsong->Loops) {
--currentsong->Loops;
currentsong->NewPos=0;
BlockOut(currentsong);
} else {
currentsong->MusicPlaying=0;
}
}
break;
default:
break;
Expand Down Expand Up @@ -249,7 +262,7 @@ void native_midi_freesong(NativeMidiSong *song)
}
}

void native_midi_start(NativeMidiSong *song)
void native_midi_start(NativeMidiSong *song, int loops)
{
MMRESULT merr;
MIDIPROPTIMEDIV mptd;
Expand All @@ -267,6 +280,7 @@ void native_midi_start(NativeMidiSong *song)
currentsong=song;
currentsong->NewPos=0;
currentsong->MusicPlaying=1;
currentsong->Loops=loops;
mptd.cbStruct=sizeof(MIDIPROPTIMEDIV);
mptd.dwTimeDiv=currentsong->ppqn;
merr=midiStreamProperty(hMidiStream,(LPBYTE)&mptd,MIDIPROP_SET | MIDIPROP_TIMEDIV);
Expand All @@ -275,12 +289,6 @@ void native_midi_start(NativeMidiSong *song)
}
}

int native_midi_jump_to_time(NativeMidiSong *song, double time)
{
/* Not yet implemented */
return -1;
}

void native_midi_stop()
{
if (!hMidiStream)
Expand Down

0 comments on commit 091f055

Please sign in to comment.