]> git.sesse.net Git - vlc/blobdiff - modules/demux/gme.c
contrib: growl: fix build
[vlc] / modules / demux / gme.c
index 77ce03a773a2b9928a22cd75d701f5751fac72dc..5d6d214a1bac343cf5ee444c58535fcc8777e72c 100644 (file)
@@ -5,20 +5,20 @@
 /*****************************************************************************
  * Copyright © 2010 Rémi Denis-Courmont
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- ****************************************************************************/
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -29,8 +29,8 @@
 #include <assert.h>
 
 #include <vlc_common.h>
+#include <vlc_input.h>
 #include <vlc_demux.h>
-#include <vlc_aout.h>
 #include <vlc_plugin.h>
 
 #include <gme/gme.h>
@@ -52,8 +52,13 @@ vlc_module_end ()
 struct demux_sys_t
 {
     Music_Emu   *emu;
+    unsigned     track_id;
+
     es_out_id_t *es;
     date_t       pts;
+
+    input_title_t **titlev;
+    unsigned        titlec;
 };
 
 
@@ -70,6 +75,7 @@ static int Open (vlc_object_t *obj)
      || size > LONG_MAX /* too big for GME */)
         return VLC_EGENERIC;
 
+    /* Auto detection */
     const uint8_t *peek;
     if (stream_Peek (demux->s, &peek, 4) < 4)
         return VLC_EGENERIC;
@@ -79,6 +85,7 @@ static int Open (vlc_object_t *obj)
         return VLC_EGENERIC;
     msg_Dbg (obj, "detected file type %s", type);
 
+    /* Initialization */
     demux_sys_t *sys = malloc (sizeof (*sys));
     if (unlikely(sys == NULL))
         return VLC_ENOMEM;
@@ -90,7 +97,7 @@ static int Open (vlc_object_t *obj)
         return VLC_ENOMEM;
     }
     gme_load_custom (sys->emu, Reader, size, demux->s);
-    gme_start_track (sys->emu, 0);
+    gme_start_track (sys->emu, sys->track_id = 0);
 
     es_format_t fmt;
     es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16N);
@@ -106,6 +113,31 @@ static int Open (vlc_object_t *obj)
     date_Init (&sys->pts, RATE, 1);
     date_Set (&sys->pts, 0);
 
+    /* Titles */
+    unsigned n = gme_track_count (sys->emu);
+    sys->titlev = malloc (n * sizeof (*sys->titlev));
+    if (unlikely(sys->titlev == NULL))
+        n = 0;
+    sys->titlec = n;
+    for (unsigned i = 0; i < n; i++)
+    {
+         input_title_t *title = vlc_input_title_New ();
+         sys->titlev[i] = title;
+         if (unlikely(title == NULL))
+             continue;
+
+         gme_info_t *infos;
+         if (gme_track_info (sys->emu, &infos, i))
+             continue;
+         msg_Dbg (obj, "track %u: %s %d ms", i, infos->song, infos->length);
+         if (infos->length != -1)
+             title->i_length = infos->length * INT64_C(1000);
+         if (infos->song[0])
+             title->psz_name = strdup (infos->song);
+         gme_free_info (infos);
+    }
+
+    /* Callbacks */
     demux->pf_demux = Demux;
     demux->pf_control = Control;
     demux->p_sys = sys;
@@ -118,6 +150,9 @@ static void Close (vlc_object_t *obj)
     demux_t *demux = (demux_t *)obj;
     demux_sys_t *sys = demux->p_sys;
 
+    for (unsigned i = 0, n = sys->titlec; i < n; i++)
+        vlc_input_title_Delete (sys->titlev[i]);
+    free (sys->titlev);
     gme_delete (sys->emu);
     free (sys);
 }
@@ -139,12 +174,19 @@ static int Demux (demux_t *demux)
 {
     demux_sys_t *sys = demux->p_sys;
 
+    /* Next track */
     if (gme_track_ended (sys->emu))
     {
-        msg_Dbg (demux, "track ended");
-        return 0;
+        msg_Dbg (demux, "track %u ended", sys->track_id);
+        if (++sys->track_id >= (unsigned)gme_track_count (sys->emu))
+            return 0;
+
+        demux->info.i_update |= INPUT_UPDATE_TITLE;
+        demux->info.i_title = sys->track_id;
+        gme_start_track (sys->emu, sys->track_id);
     }
 
+
     block_t *block = block_Alloc (2 * 2 * SAMPLES);
     if (unlikely(block == NULL))
         return 0;
@@ -171,27 +213,85 @@ static int Control (demux_t *demux, int query, va_list args)
 
     switch (query)
     {
-        case DEMUX_GET_POSITION: // TODO
+        case DEMUX_GET_POSITION:
         {
             double *pos = va_arg (args, double *);
-            *pos = 0.;
+
+            if (unlikely(sys->track_id >= sys->titlec)
+             || (sys->titlev[sys->track_id]->i_length == 0))
+                *pos = 0.;
+            else
+                *pos = (double)(gme_tell (sys->emu))
+                    / (double)(sys->titlev[sys->track_id]->i_length / 1000);
+            return VLC_SUCCESS;
+        }
+
+        case DEMUX_SET_POSITION:
+        {
+            double pos = va_arg (args, double);
+
+            if (unlikely(sys->track_id >= sys->titlec)
+             || (sys->titlev[sys->track_id]->i_length == 0))
+                break;
+
+            int seek = (sys->titlev[sys->track_id]->i_length / 1000) * pos;
+            if (seek > INT_MAX || gme_seek (sys->emu, seek))
+                break;
+            return VLC_SUCCESS;
+        }
+
+        case DEMUX_GET_LENGTH:
+        {
+            int64_t *v = va_arg (args, int64_t *);
+
+            if (unlikely(sys->track_id >= sys->titlec)
+             || (sys->titlev[sys->track_id]->i_length == 0))
+                break;
+            *v = sys->titlev[sys->track_id]->i_length;
             return VLC_SUCCESS;
         }
 
-        //case DEMUX_SET_POSITION: TODO
-        //case DEMUX_GET_LENGTH: TODO
         case DEMUX_GET_TIME:
         {
             int64_t *v = va_arg (args, int64_t *);
-            *v = gme_tell (sys->emu) * 1000;
+            *v = gme_tell (sys->emu) * INT64_C(1000);
             return VLC_SUCCESS;
         }
 
         case DEMUX_SET_TIME:
         {
-            int64_t v = va_arg (args, int64_t);
-            if (v > INT_MAX || gme_seek (sys->emu, v / 1000))
-                return VLC_EGENERIC;
+            int64_t v = va_arg (args, int64_t) / 1000;
+            if (v > INT_MAX || gme_seek (sys->emu, v))
+                break;
+            return VLC_SUCCESS;
+        }
+
+        case DEMUX_GET_TITLE_INFO:
+        {
+            input_title_t ***titlev = va_arg (args, input_title_t ***);
+            int *titlec = va_arg (args, int *);
+            *(va_arg (args, int *)) = 0; /* Title offset */
+            *(va_arg (args, int *)) = 0; /* Chapter offset */
+
+            unsigned n = sys->titlec;
+            *titlev = malloc (sizeof (**titlev) * n);
+            if (unlikely(titlev == NULL))
+                n = 0;
+            *titlec = n;
+            for (unsigned i = 0; i < n; i++)
+                (*titlev)[i] = vlc_input_title_Duplicate (sys->titlev[i]);
+            return VLC_SUCCESS;
+        }
+
+        case DEMUX_SET_TITLE:
+        {
+            int track_id = va_arg (args, int);
+            if (track_id >= gme_track_count (sys->emu))
+                break;
+            gme_start_track (sys->emu, track_id);
+            demux->info.i_update |= INPUT_UPDATE_TITLE;
+            demux->info.i_title = track_id;
+            sys->track_id = track_id;
             return VLC_SUCCESS;
         }
     }