Fixed binary compatibility, added Sound_GetDuration().
authorRyan C. Gordon <icculus@icculus.org>
Wed, 12 May 2004 02:15:00 +0000
changeset 477 3e705c9180e5
parent 475 f0b8865577db
child 478 15a540505a02
Fixed binary compatibility, added Sound_GetDuration().
CHANGELOG
SDL_sound.c
SDL_sound.h
SDL_sound_internal.h
decoders/aiff.c
decoders/au.c
decoders/flac.c
decoders/midi.c
decoders/mikmod.c
decoders/modplug.c
decoders/mpglib.c
decoders/ogg.c
decoders/quicktime.c
decoders/raw.c
decoders/shn.c
decoders/smpeg.c
decoders/voc.c
decoders/wav.c
--- a/CHANGELOG	Sat May 08 22:06:14 2004 +0000
+++ b/CHANGELOG	Wed May 12 02:15:00 2004 +0000
@@ -2,7 +2,9 @@
  * CHANGELOG.
  */
 
-
+05112004 - Added Sound_GetDuration() and moved total_time out of Sound_Sample
+           struct and into it's opaque data...this fixes binary compatibility
+           with apps written for SDL_sound 1.0.
 05082004 - Started 1.1.0 development branch with code to determine the total
            length of a sample (thanks to Wesley, Eric, Wang, and Ahilan!)...
            this patch was originally committed to CVS on 10252003, but it is
--- a/SDL_sound.c	Sat May 08 22:06:14 2004 +0000
+++ b/SDL_sound.c	Wed May 12 02:15:00 2004 +0000
@@ -901,5 +901,12 @@
 } /* Sound_Rewind */
 
 
+Sint32 Sound_GetDuration(Sound_Sample *sample)
+{
+    BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, -1);
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
+    return(internal->total_time);
+} /* Sound_GetDuration */
+
 /* end of SDL_sound.c ... */
 
--- a/SDL_sound.h	Sat May 08 22:06:14 2004 +0000
+++ b/SDL_sound.h	Wed May 12 02:15:00 2004 +0000
@@ -185,7 +185,6 @@
     void *buffer;  /**< Decoded sound data lands in here. */
     Uint32 buffer_size;  /**< Current size of (buffer), in bytes (Uint8). */
     Sound_SampleFlags flags;  /**< Flags relating to this sample. */
-    Sint32 total_time;  /**< Total length of song or track */
 } Sound_Sample;
 
 
@@ -501,6 +500,31 @@
 
 
 /**
+ * \fn Sint32 Sound_GetDuration(Sound_Sample *sample)
+ * \brief Retrieve total play time of sample, in milliseconds.
+ *
+ * Report total time length of sample, in milliseconds. This is a fast
+ *  call. Duration is calculated during Sound_NewSample*, so this is just
+ *  an accessor into otherwise opaque data.
+ *
+ * Please note that not all formats can determine a total time, some can't
+ *  be exact without fully decoding the data, and thus will estimate the
+ *  duration. Many decoders will require the ability to seek in the data
+ *  stream to calculate this, so even if we can tell you how long an .ogg
+ *  file will be, the same data set may fail if it's, say, streamed over an
+ *  HTTP connection. Plan accordingly.
+ *
+ * Most people won't need this function to just decode and playback, but it
+ *  can be useful for informational purposes in, say, a music player's UI.
+ *
+ *    \param sample Sound_Sample from which to retrieve duration information.
+ *   \return Sample length in milliseconds, or -1 if duration can't be
+ *           determined for any reason.
+ */
+SNDDECLSPEC Sint32 SDLCALL Sound_GetDuration(Sound_Sample *sample);
+
+
+/**
  * \fn int Sound_SetBufferSize(Sound_Sample *sample, Uint32 new_size)
  * \brief Change the current buffer size for a sample.
  *
--- a/SDL_sound_internal.h	Sat May 08 22:06:14 2004 +0000
+++ b/SDL_sound_internal.h	Wed May 12 02:15:00 2004 +0000
@@ -255,6 +255,7 @@
     void *buffer;
     Uint32 buffer_size;
     void *decoder_private;
+    Sint32 total_time;
 } Sound_SampleInternal;
 
 
--- a/decoders/aiff.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/aiff.c	Wed May 12 02:15:00 2004 +0000
@@ -477,9 +477,9 @@
     sample->actual.rate = c.sampleRate;
 
     /* Really, sample->total_time = (c.numSampleFrames*1000) c.sampleRate */
-    sample->total_time = (c.numSampleFrames / c.sampleRate) * 1000;
-    sample->total_time += (c.numSampleFrames % c.sampleRate) 
-                       *  1000 / c.sampleRate;
+    internal->total_time = (c.numSampleFrames / c.sampleRate) * 1000;
+    internal->total_time += (c.numSampleFrames % c.sampleRate)
+                             *  1000 / c.sampleRate;
 
     if (c.sampleSize <= 8)
     {
--- a/decoders/au.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/au.c	Wed May 12 02:15:00 2004 +0000
@@ -246,10 +246,10 @@
 
     bytes_per_second = ( ( dec->encoding == AU_ENC_LINEAR_16 ) ? 2 : 1 )
         * sample->actual.rate * sample->actual.channels ;
-    sample->total_time = ((dec->remaining == -1) ? (-1) :
-			  ( ( dec->remaining / bytes_per_second ) * 1000 ) +
-			  ( ( dec->remaining % bytes_per_second ) * 1000 /
-                          bytes_per_second ) );
+    internal->total_time = ((dec->remaining == -1) ? (-1) :
+                            ( ( dec->remaining / bytes_per_second ) * 1000 ) +
+                            ( ( dec->remaining % bytes_per_second ) * 1000 /
+                              bytes_per_second ) );
 
     sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
     dec->total = dec->remaining;
--- a/decoders/flac.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/flac.c	Wed May 12 02:15:00 2004 +0000
@@ -233,6 +233,8 @@
     void *client_data)
 {
     flac_t *f = (flac_t *) client_data;
+    Sound_Sample *sample = f->sample;
+    Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
 
     SNDDBG(("FLAC: Metadata callback.\n"));
 
@@ -244,24 +246,27 @@
         SNDDBG(("FLAC: Metadata is streaminfo.\n"));
 
         f->is_flac = 1;
-        f->sample->actual.channels = metadata->data.stream_info.channels;
-        f->sample->actual.rate = metadata->data.stream_info.sample_rate;
+        sample->actual.channels = metadata->data.stream_info.channels;
+        sample->actual.rate = metadata->data.stream_info.sample_rate;
 
-	if (metadata->data.stream_info.sample_rate == 0 ||
+        if (metadata->data.stream_info.sample_rate == 0 ||
             metadata->data.stream_info.total_samples == 0)
-	  f->sample->total_time = -1;
-	else {
-	    f->sample->total_time = (metadata->data.stream_info.total_samples)
+        {
+            internal->total_time = -1;
+        } /* if */
+        else
+        {
+            internal->total_time = (metadata->data.stream_info.total_samples)
                 / metadata->data.stream_info.sample_rate * 1000;
-	    f->sample->total_time += (metadata->data.stream_info.total_samples
+            internal->total_time += (metadata->data.stream_info.total_samples
                 % metadata->data.stream_info.sample_rate) * 1000
                 / metadata->data.stream_info.sample_rate;
-	}
+        } /* else */
 
         if (metadata->data.stream_info.bits_per_sample > 8)
-            f->sample->actual.format = AUDIO_S16MSB;
+            sample->actual.format = AUDIO_S16MSB;
         else
-            f->sample->actual.format = AUDIO_S8;
+            sample->actual.format = AUDIO_S8;
     } /* if */
 } /* metadata_callback */
 
--- a/decoders/midi.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/midi.c	Wed May 12 02:15:00 2004 +0000
@@ -107,13 +107,13 @@
     SNDDBG(("MIDI: Accepting data stream.\n"));
 
     internal->decoder_private = (void *) song;
+    internal->total_time = Timidity_GetSongLength(song);
 
     sample->actual.channels = 2;
     sample->actual.rate = 44100;
     sample->actual.format = AUDIO_S16SYS;
+    sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
     
-    sample->total_time = Timidity_GetSongLength(song);
-    sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
     return(1); /* we'll handle this data. */
 } /* MIDI_open */
 
--- a/decoders/mikmod.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/mikmod.c	Wed May 12 02:15:00 2004 +0000
@@ -282,9 +282,9 @@
 
     /*
      *   module->sngtime = current song time in 2^-10 seconds
-     *   sample->total_time = (module->sngtime * 1000) / (1<<10)
+     *   internal->total_time = (module->sngtime * 1000) / (1<<10)
      */
-    sample->total_time = (module->sngtime * 1000) / (1<<10);
+    internal->total_time = (module->sngtime * 1000) / (1<<10);
 
     SNDDBG(("MIKMOD: Name: %s\n", module->songname));
     SNDDBG(("MIKMOD: Type: %s\n", module->modtype));
@@ -322,7 +322,7 @@
      * For each position (which corresponds to a particular pattern),
      * get the speed values and compute the time length of the segment
      */
-    sample->total_time = 0;
+    internal->total_time = 0;
     for (i = 0; i < module->numpos; i++)
     {
         Player_SetPosition(i);
@@ -378,7 +378,7 @@
                           125.0 / module->bpm);
     } /* for */
     /* Now convert to milliseconds and store the value */
-    sample->total_time = (Sint32)(segment_time * 1000); 
+    internal->total_time = (Sint32)(segment_time * 1000);
 
     /* Reset the sample to the beginning */
     Player_SetPosition(0);
@@ -462,7 +462,7 @@
         return(1);
     } /* if */
 
-    if (ms >= sample->total_time)
+    if (ms >= internal->total_time)
         Player_SetPosition(module->numpos);
 
     /* Convert time to seconds (double) to make comparisons easier */
--- a/decoders/modplug.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/modplug.c	Wed May 12 02:15:00 2004 +0000
@@ -270,7 +270,7 @@
     if (modplug_mutex != NULL)
         SDL_UnlockMutex(modplug_mutex);
 
-    sample->total_time = ModPlug_GetLength(module);
+    internal->total_time = ModPlug_GetLength(module);
     SNDDBG(("MODPLUG: [%d ms] %s\n",
             ModPlug_GetLength(module), ModPlug_GetName(module)));
 
--- a/decoders/mpglib.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/mpglib.c	Wed May 12 02:15:00 2004 +0000
@@ -197,8 +197,8 @@
         if (SDL_RWseek(internal->rw, pos, SEEK_SET) != pos) {
             BAIL_MACRO("MPGLIB: Cannot go back to save spot in file.", 0);
 	}
-        sample->total_time = total_byte_size / mpg->mp.fr.bitrate * 8.0;
-        sample->total_time += (total_byte_size % mpg->mp.fr.bitrate) * 8.0
+        internal->total_time = total_byte_size / mpg->mp.fr.bitrate * 8.0;
+        internal->total_time += (total_byte_size % mpg->mp.fr.bitrate) * 8.0
             / mpg->mp.fr.bitrate;
     }
 
--- a/decoders/ogg.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/ogg.c	Wed May 12 02:15:00 2004 +0000
@@ -212,9 +212,9 @@
     sample->actual.channels = (Uint8) info->channels;
     total_time = ov_time_total(vf, -1);
     if (OV_EINVAL == total_time)
-      sample->total_time = -1;
+      internal->total_time = -1;
     else
-      sample->total_time = (Sint32)(total_time * 1000.0 + 0.5);
+      internal->total_time = (Sint32)(total_time * 1000.0 + 0.5);
 
 
     /*
--- a/decoders/quicktime.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/quicktime.c	Wed May 12 02:15:00 2004 +0000
@@ -547,7 +547,7 @@
   instance = QT_open_internal(sample, ext);
   internal->decoder_private = (void*)instance;
 
-  sample->total_time = -1;  /* return -1 for total time of song for now */ 
+  internal->total_time = -1;  /* return -1 for total time of song for now */
 
   return(instance != NULL);
     
--- a/decoders/raw.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/raw.c	Wed May 12 02:15:00 2004 +0000
@@ -135,8 +135,8 @@
 
     sample_rate =  (sample->actual.rate * sample->actual.channels
       * ( (sample->actual.format & 0x0018) >> 3) );
-    sample->total_time = ( pos ) / sample_rate * 1000;
-    sample->total_time += (pos % sample_rate) * 1000 / sample_rate;
+    internal->total_time = ( pos ) / sample_rate * 1000;
+    internal->total_time += (pos % sample_rate) * 1000 / sample_rate;
 
     return(1); /* we'll handle this data. */
 } /* RAW_open */
--- a/decoders/shn.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/shn.c	Wed May 12 02:15:00 2004 +0000
@@ -580,8 +580,8 @@
     BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* 'data' header */
     BAIL_IF_MACRO(u32 != dataID,  "SHN: No 'data' header.", 0);
     BAIL_IF_MACRO(!verb_ReadLE32(shn, rw, &u32), NULL, 0); /* chunksize */
-    sample->total_time = u32 / bytes_per_second * 1000;
-    sample->total_time += (u32 % bytes_per_second) * 1000 / bytes_per_second;
+    internal->total_time = u32 / bytes_per_second * 1000;
+    internal->total_time += (u32 % bytes_per_second) * 1000 / bytes_per_second;
     return(1);
 } /* parse_riff_header */
 
--- a/decoders/smpeg.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/smpeg.c	Wed May 12 02:15:00 2004 +0000
@@ -212,7 +212,7 @@
     sample->actual.rate = spec.freq;
     sample->actual.channels = spec.channels;
     sample->flags = SOUND_SAMPLEFLAG_CANSEEK;
-    sample->total_time = smpeg_info.total_time * 1000;
+    internal->total_time = smpeg_info.total_time * 1000;
     internal->decoder_private = smpeg;
 
     SMPEG_play(smpeg);
--- a/decoders/voc.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/voc.c	Wed May 12 02:15:00 2004 +0000
@@ -245,9 +245,9 @@
 
                 bytes_per_second = sample->actual.rate
                     * sample->actual.channels;
-                sample->total_time += ( v->rest ) / bytes_per_second * 1000;
-		sample->total_time += (v->rest % bytes_per_second) * 1000
-		    / bytes_per_second;
+                internal->total_time += ( v->rest ) / bytes_per_second * 1000;
+                internal->total_time += (v->rest % bytes_per_second) * 1000
+                                            / bytes_per_second;
                 return 1;
 
             case VOC_DATA_16:
@@ -281,11 +281,11 @@
                     return 0;
                 v->rest = sblen - 12;
 
-		bytes_per_second = ((v->size == ST_SIZE_WORD) ? (2) : (1)) *
-		    sample->actual.rate * v->channels;
-                sample->total_time += v->rest / bytes_per_second * 1000;
-                sample->total_time += ( v->rest % bytes_per_second ) * 1000
-		    / bytes_per_second;
+                bytes_per_second = ((v->size == ST_SIZE_WORD) ? (2) : (1)) *
+                                    sample->actual.rate * v->channels;
+                internal->total_time += v->rest / bytes_per_second * 1000;
+                internal->total_time += ( v->rest % bytes_per_second ) * 1000
+                                            / bytes_per_second;
                 return 1;
 
             case VOC_CONT:
@@ -315,8 +315,8 @@
                 v->rest = period;
                 v->silent = 1;
 
-		sample->total_time += (period) / (v->rate) * 1000;
-		sample->total_time += (period % v->rate) * 1000 / v->rate; 
+                internal->total_time += (period) / (v->rate) * 1000;
+                internal->total_time += (period % v->rate) * 1000 / v->rate;
                 return 1;
 
             case VOC_LOOP:
--- a/decoders/wav.c	Sat May 08 22:06:14 2004 +0000
+++ b/decoders/wav.c	Wed May 12 02:15:00 2004 +0000
@@ -724,9 +724,9 @@
                                sample->actual.channels );
     internal->decoder_private = (void *) w;
 
-    sample->total_time = (fmt->total_bytes / fmt->dwAvgBytesPerSec) * 1000;
-    sample->total_time += (fmt->total_bytes % fmt->dwAvgBytesPerSec)
-                       *  1000 / fmt->dwAvgBytesPerSec;
+    internal->total_time = (fmt->total_bytes / fmt->dwAvgBytesPerSec) * 1000;
+    internal->total_time += (fmt->total_bytes % fmt->dwAvgBytesPerSec)
+                              *  1000 / fmt->dwAvgBytesPerSec;
 
     sample->flags = SOUND_SAMPLEFLAG_NONE;
     if (fmt->seek_sample != NULL)