[Commits] SDL_mixer: Better fix for looping on Mac OS X. This also gives ...

libsdl.org revision control commits-owner at libsdl.org
Sun Jan 1 13:48:51 PST 2012


details:   http://hg.libsdl.org/SDL_mixer/rev/f19368c22ebd
changeset: 533:f19368c22ebd
user:      Sam Lantinga <slouken at libsdl.org>
date:      Sun Jan 01 16:45:58 2012 -0500
description:
Better fix for looping on Mac OS X.  This also gives event perfect looping on Windows and theoretically on Haiku.

diffstat:

 music.c                           |  29 +++++++++++------------
 native_midi/native_midi.h         |   3 +-
 native_midi/native_midi_haiku.cpp |  36 +++++++++++++++-------------
 native_midi/native_midi_mac.c     |  11 +++-----
 native_midi/native_midi_macosx.c  |  22 +++++++++--------
 native_midi/native_midi_win32.c   |  48 ++++++++++++++++++++++----------------
 6 files changed, 78 insertions(+), 71 deletions(-)

diffs (369 lines):

diff -r b8e8ae4852b2 -r f19368c22ebd music.c
--- a/music.c	Sun Jan 01 14:40:22 2012 -0500
+++ b/music.c	Sun Jan 01 16:45:58 2012 -0500
@@ -199,10 +199,17 @@
 	
 	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;
 		} 
@@ -791,7 +798,7 @@
 	    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
@@ -889,6 +896,10 @@
 		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();
@@ -920,18 +931,6 @@
 		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);
diff -r b8e8ae4852b2 -r f19368c22ebd native_midi/native_midi.h
--- a/native_midi/native_midi.h	Sun Jan 01 14:40:22 2012 -0500
+++ b/native_midi/native_midi.h	Sun Jan 01 16:45:58 2012 -0500
@@ -30,8 +30,7 @@
 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);
diff -r b8e8ae4852b2 -r f19368c22ebd native_midi/native_midi_haiku.cpp
--- a/native_midi/native_midi_haiku.cpp	Sun Jan 01 14:40:22 2012 -0500
+++ b/native_midi/native_midi_haiku.cpp	Sun Jan 01 16:45:58 2012 -0500
@@ -45,6 +45,7 @@
   MidiEventsStore()
   {
     fPlaying = false;
+    fLoops = 0;
   }
   virtual status_t Import(SDL_RWops *rw)
   {
@@ -66,8 +67,16 @@
     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++;
@@ -82,25 +91,22 @@
     fEvs = 0;
   }
 
-  int CurrentEvent()
-  {
-    return fPos;
-  }
-  int CountEvents()
-  {
-    return fTotal;
-  }
-
   bool IsPlaying()
   {
     return fPlaying;
   }
 
+  void SetLoops(int loops)
+  {
+    fLoops = loops;
+  }
+
   protected:
   MIDIEvent *fEvs;
   Uint16 fDivision;
 
   int fPos, fTotal;
+  int fLoops;
   bool fPlaying;
 
   void SprayEvent(MIDIEvent *ev, uint32 time)
@@ -251,18 +257,14 @@
   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;
@@ -275,7 +277,7 @@
 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)
diff -r b8e8ae4852b2 -r f19368c22ebd native_midi/native_midi_mac.c
--- a/native_midi/native_midi_mac.c	Sun Jan 01 14:40:22 2012 -0500
+++ b/native_midi/native_midi_mac.c	Sun Jan 01 16:45:58 2012 -0500
@@ -192,12 +192,15 @@
 	}
 }
 
-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();
@@ -254,12 +257,6 @@
 	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)
diff -r b8e8ae4852b2 -r f19368c22ebd native_midi/native_midi_macosx.c
--- a/native_midi/native_midi_macosx.c	Sun Jan 01 14:40:22 2012 -0500
+++ b/native_midi/native_midi_macosx.c	Sun Jan 01 16:45:58 2012 -0500
@@ -41,6 +41,7 @@
     MusicSequence sequence;
     MusicTimeStamp endTime;
     AudioUnit audiounit;
+    int loops;
 };
 
 static NativeMidiSong *currentsong = NULL;
@@ -250,7 +251,7 @@
     }
 }
 
-void native_midi_start(NativeMidiSong *song)
+void native_midi_start(NativeMidiSong *song, int loops)
 {
     int vol;
 
@@ -264,6 +265,7 @@
         MusicPlayerStop(currentsong->player);
 
     currentsong = song;
+    currentsong->loops = loops;
 
     MusicPlayerPreroll(song->player);
     MusicPlayerSetTime(song->player, 0);
@@ -279,13 +281,6 @@
     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) {
@@ -305,8 +300,15 @@
         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)
diff -r b8e8ae4852b2 -r f19368c22ebd native_midi/native_midi_win32.c
--- a/native_midi/native_midi_win32.c	Sun Jan 01 14:40:22 2012 -0500
+++ b/native_midi/native_midi_win32.c	Sun Jan 01 16:45:58 2012 -0500
@@ -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;
 };
@@ -51,11 +53,14 @@
 {
   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);
@@ -63,15 +68,16 @@
       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;
@@ -163,12 +169,19 @@
     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;
@@ -249,7 +262,7 @@
   }
 }
 
-void native_midi_start(NativeMidiSong *song)
+void native_midi_start(NativeMidiSong *song, int loops)
 {
   MMRESULT merr;
   MIDIPROPTIMEDIV mptd;
@@ -267,6 +280,7 @@
     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);
@@ -275,12 +289,6 @@
   }
 }
 
-int native_midi_jump_to_time(NativeMidiSong *song, double time)
-{
-	/* Not yet implemented */
-	return -1;
-}
-
 void native_midi_stop()
 {
   if (!hMidiStream)


More information about the commits mailing list