gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog libmedia/AudioDecoderNellymoser...


From: Bastiaan Jacques
Subject: [Gnash-commit] gnash ChangeLog libmedia/AudioDecoderNellymoser...
Date: Fri, 08 Feb 2008 15:27:32 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Bastiaan Jacques <bjacques>     08/02/08 15:27:32

Modified files:
        .              : ChangeLog 
        libmedia       : AudioDecoderNellymoser.cpp 
                         AudioDecoderNellymoser.h Makefile.am 
                         sound_handler.h 
        server         : Makefile.am 
        server/asobj   : NetStreamGst.cpp 
Added files:
        libmedia/gst   : SoundGst.cpp SoundGst.h SoundHandlerGst.cpp 
                         SoundHandlerGst.h gstbuffersrc.c gstbuffersrc.h 
Removed files:
        libmedia/gst   : gstgnashsrc.c gstgnashsrc.h 

Log message:
                * libmedia/gst/SoundHandlerGst.{h,cpp}: New Gstreamer 
sound_handler
                implementation. Manages SoundGst objects.
                * libmedia/gst/SoundGst{h,cpp}: Sound class representing a 
single
                sound.
                * libmedia/gst/gstbuffersrc.{c,h}: Home-grown element derived 
from
                gstappsrc; it is a random-access element. Used for SoundGsts.
                * libmedia/AudioDecoderNellymoser.{cpp,h}: Add another decode()
                that returns floats, since Gstreamer can handle them.
                * libmedia/Makefile.am: Compile new files; stop compiling 
removed
                files.
                * libmedia/sound_handler.h: Drop unused (and evil)
                {att,de}tach_aux_streamer methods.
                * server/Makefile.am: Link in Gstreamer libs if requested.
                * server/asobj/NetStreamGst.cpp: Remove unused include.
        
        This fixes blockers #22092 and #21162.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5593&r2=1.5594
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderNellymoser.cpp?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderNellymoser.h?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/Makefile.am?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sound_handler.h?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundHandlerGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundHandlerGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstbuffersrc.c?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstbuffersrc.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstgnashsrc.c?cvsroot=gnash&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstgnashsrc.h?cvsroot=gnash&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.137&r2=1.138
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.cpp?cvsroot=gnash&r1=1.77&r2=1.78

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5593
retrieving revision 1.5594
diff -u -b -r1.5593 -r1.5594
--- ChangeLog   8 Feb 2008 13:22:07 -0000       1.5593
+++ ChangeLog   8 Feb 2008 15:27:30 -0000       1.5594
@@ -1,3 +1,20 @@
+2008-02-08 Bastiaan Jacques <address@hidden>
+
+       * libmedia/gst/SoundHandlerGst.{h,cpp}: New Gstreamer sound_handler
+       implementation. Manages SoundGst objects.
+       * libmedia/gst/SoundGst{h,cpp}: Sound class representing a single
+       sound.
+       * libmedia/gst/gstbuffersrc.{c,h}: Home-grown element derived from
+       gstappsrc; it is a random-access element. Used for SoundGsts.
+       * libmedia/AudioDecoderNellymoser.{cpp,h}: Add another decode()
+       that returns floats, since Gstreamer can handle them.
+       * libmedia/Makefile.am: Compile new files; stop compiling removed
+       files.
+       * libmedia/sound_handler.h: Drop unused (and evil)
+       {att,de}tach_aux_streamer methods.
+       * server/Makefile.am: Link in Gstreamer libs if requested.
+       * server/asobj/NetStreamGst.cpp: Remove unused include.
+
 2008-02-08 Sandro Santilli <address@hidden>
 
        * testsuite/misc-mtasc.all/level87.as, testsuite/swfdec/PASSING:

Index: libmedia/AudioDecoderNellymoser.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/AudioDecoderNellymoser.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- libmedia/AudioDecoderNellymoser.cpp 21 Jan 2008 23:10:13 -0000      1.7
+++ libmedia/AudioDecoderNellymoser.cpp 8 Feb 2008 15:27:30 -0000       1.8
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-// $Id: AudioDecoderNellymoser.cpp,v 1.7 2008/01/21 23:10:13 rsavoye Exp $
+// $Id: AudioDecoderNellymoser.cpp,v 1.8 2008/02/08 15:27:30 bjacques Exp $
 
 // This file incorporates work covered by the following copyright and 
permission
 // notice:
@@ -769,6 +769,25 @@
        }
 }
 
+float* AudioDecoderNellymoser::decode(boost::uint8_t* in_buf, boost::uint32_t 
inputSize, boost::uint32_t* outputSize)
+{
+        size_t out_buf_size = (inputSize / NELLY_BLOCK_LEN) * 256;
+       float* out_buf = new float[out_buf_size];
+       
+       boost::uint8_t* input_ptr = in_buf;
+       float* output_ptr = out_buf;
+
+       while (inputSize > 0) {
+               nelly_decode_block(_nh, input_ptr, output_ptr);
+               input_ptr += NELLY_BLOCK_LEN;
+               inputSize -= NELLY_BLOCK_LEN;
+               output_ptr += 256;
+       }
+       
+       *outputSize = out_buf_size;
+       
+       return out_buf; 
+}
 
 boost::uint8_t* AudioDecoderNellymoser::decode(boost::uint8_t* input, 
boost::uint32_t inputSize, boost::uint32_t& outputSize, boost::uint32_t& 
decodedBytes, bool /*parse*/)
 {
@@ -788,7 +807,7 @@
                        
        boost::uint8_t* tmp_raw_buffer = 
reinterpret_cast<boost::uint8_t*>(out_buf_start);
        boost::uint32_t tmp_raw_buffer_size = out_buf_size * 2;
-
+#if 0
        // If we need to convert samplerate or/and from mono to stereo...
        if (out_buf_size > 0 && (_sampleRate != 44100 || !_stereo)) {
 
@@ -816,8 +835,11 @@
                tmp_raw_buffer_size = adjusted_size;
 
        } else {
+#endif
                tmp_raw_buffer_size = out_buf_size;
+#if 0
        }
+#endif
 
        outputSize = tmp_raw_buffer_size;
        decodedBytes = inputSize;

Index: libmedia/AudioDecoderNellymoser.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/AudioDecoderNellymoser.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- libmedia/AudioDecoderNellymoser.h   21 Jan 2008 23:10:13 -0000      1.7
+++ libmedia/AudioDecoderNellymoser.h   8 Feb 2008 15:27:30 -0000       1.8
@@ -16,7 +16,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-// $Id: AudioDecoderNellymoser.h,v 1.7 2008/01/21 23:10:13 rsavoye Exp $
+// $Id: AudioDecoderNellymoser.h,v 1.8 2008/02/08 15:27:30 bjacques Exp $
 
 // This file incorporates work covered by the following copyright and 
permission
 // notice:
@@ -81,6 +81,9 @@
 
        boost::uint8_t* decode(boost::uint8_t* input, boost::uint32_t 
inputSize, boost::uint32_t& outputSize, boost::uint32_t& decodedBytes, bool 
parse);
 
+       /// @return a new[]-allocated pointer to decoded data in floats.
+       float* decode(boost::uint8_t* in_buf, boost::uint32_t inputSize, 
boost::uint32_t* outputSize);
+
 private:
 
        // The handle used by the decoder

Index: libmedia/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libmedia/Makefile.am,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- libmedia/Makefile.am        21 Jan 2008 23:10:14 -0000      1.11
+++ libmedia/Makefile.am        8 Feb 2008 15:27:30 -0000       1.12
@@ -38,6 +38,9 @@
        -I$(top_srcdir)/backend \
        -I$(top_srcdir)/libbase \
        -I$(top_srcdir)/server  \
+       -I$(top_srcdir)/server/vm \
+       -I$(top_srcdir)/server/parser \
+       -I$(top_srcdir)/libgeometry \
        $(PTHREAD_CFLAGS) \
        $(OPENGL_CFLAGS) \
        $(LIBXML_CFLAGS) \
@@ -95,28 +98,30 @@
 
 if USE_SOUND_GST
    libgnashmedia_la_SOURCES += \
-               gst/gstgnashsrc.c \
                gst/VideoDecoderGst.cpp \
                gst/AudioDecoderGst.cpp \
                gst/gstappbuffer.c \
                gst/gstappsink.c \
                gst/gstappsrc.c \
-               gst/sound_handler_gst.cpp \
+               gst/SoundHandlerGst.cpp \
+               gst/SoundGst.cpp \
                gst/MediaDecoderGst.cpp \
                gst/gstflvdemux.c \
-               gst/gstflvparse.c 
+               gst/gstflvparse.c \
+               gst/gstbuffersrc.c
        
    noinst_HEADERS += \
-               gst/gstgnashsrc.h \
                gst/gstappbuffer.h \
                gst/AudioDecoderGst.h \
                gst/VideoDecoderGst.h \
                gst/gstappsink.h \
                gst/gstappsrc.h \
-               gst/sound_handler_gst.h \
+               gst/SoundHandlerGst.h \
+               gst/SoundGst.h \
                gst/MediaDecoderGst.h \
                gst/gstflvdemux.h \
-               gst/gstflvparse.h
+               gst/gstflvparse.h \
+               gst/gstbuffersrc.h
 
    libgnashmedia_la_CPPFLAGS += \
                $(GSTREAMER_CFLAGS)

Index: libmedia/sound_handler.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sound_handler.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- libmedia/sound_handler.h    21 Jan 2008 23:10:14 -0000      1.8
+++ libmedia/sound_handler.h    8 Feb 2008 15:27:31 -0000       1.9
@@ -15,7 +15,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: sound_handler.h,v 1.8 2008/01/21 23:10:14 rsavoye Exp $ */
+/* $Id: sound_handler.h,v 1.9 2008/02/08 15:27:31 bjacques Exp $ */
 
 /// \page sound_handler_intro Sound handler introduction
 ///
@@ -355,45 +355,7 @@
        ///
        virtual bool    is_muted() = 0;
 
-       /// This is called by AS classes NetStream or Sound to attach callback, 
so
-       /// that audio from the classes will be played through the soundhandler.
-       //
-       /// This is actually only used by the SDL sound_handler. It uses these 
"auxiliary"
-       /// streamers to fetch decoded audio data to mix and send to the output 
channel.
-       ///
-       /// The "aux streamer" will be called with the 'udata' pointer as first 
argument,
-       /// then will be passed a buffer pointer as second argument and it's 
length
-       /// as third. The callbacks should fill the given buffer if possible.
-       /// The callback should return true if wants to remain attached, false 
if wants
-       /// to be detached. 
-       ///
-       /// @param ptr
-       ///     The pointer to the callback function
-       ///
-       /// @param udata
-       ///     User data pointer, passed as first argument to the registered 
callback.
-       ///     WARNING: this is currently also used to *identify* the callback 
for later
-       ///     removal, see detach_aux_streamer. TODO: stop using the data 
pointer for 
-       ///     identification purposes and use the callback pointer directly 
instead.
-       ///
-       virtual void    attach_aux_streamer(aux_streamer_ptr ptr, void* owner) 
= 0;
-
-       /// This is called by AS classes NetStream or Sound to dettach 
callback, so
-       /// that audio from the classes no longer will be played through the 
-       /// soundhandler.
-       //
-       /// @param udata
-       ///     The key identifying the auxiliary streamer.
-       ///     WARNING: this need currently be the 'udata' pointer passed to 
attach_aux_streamer.
-       ///     TODO: get the aux_streamer_ptr as key !!
-       ///
-       virtual void    detach_aux_streamer(void* udata) = 0;
 
-       sound_handler()
-               :
-               _soundsStarted(0),
-               _soundsStopped(0)
-       {}
 
        virtual ~sound_handler() {};
        
@@ -425,6 +387,13 @@
 
 protected:
 
+
+       sound_handler()
+               :
+               _soundsStarted(0),
+               _soundsStopped(0)
+       {}
+
        /// Special test-member. Stores count of started sounds.
        size_t _soundsStarted;
 

Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -b -r1.137 -r1.138
--- server/Makefile.am  21 Jan 2008 20:55:47 -0000      1.137
+++ server/Makefile.am  8 Feb 2008 15:27:32 -0000       1.138
@@ -203,6 +203,7 @@
 
 if USE_SOUND_GST
 AM_CPPFLAGS += $(GSTREAMER_CFLAGS)
+libgnashserver_la_LIBADD += $(GSTREAMER_LIBS)
 endif
 
 

Index: server/asobj/NetStreamGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.cpp,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -b -r1.77 -r1.78
--- server/asobj/NetStreamGst.cpp       3 Feb 2008 09:18:50 -0000       1.77
+++ server/asobj/NetStreamGst.cpp       8 Feb 2008 15:27:32 -0000       1.78
@@ -25,7 +25,6 @@
 #include "string_table.h"
 #include <boost/algorithm/string/case_conv.hpp> // for PROPNAME (shouldn't 
this include be in the header actualy defining PROPNAME, btw?)
 
-#include "gstgnashsrc.h"
 #include "Object.h"
 #include "gstflvdemux.h"
 #include <gst/gstelement.h>

Index: libmedia/gst/SoundGst.cpp
===================================================================
RCS file: libmedia/gst/SoundGst.cpp
diff -N libmedia/gst/SoundGst.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundGst.cpp   8 Feb 2008 15:27:31 -0000       1.1
@@ -0,0 +1,537 @@
+// 
+//   Copyright (C) 2008 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// derives from code subject to the following license:
+
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <address@hidden>
+ *               2000 Wim Taymans <address@hidden>
+ *               2004 Thomas Vander Stichele <address@hidden>
+ *
+ * gst-inspect.c: tool to inspect the GStreamer registry
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+// TODO:
+//
+// * Decode NellyMoser (easy)
+// * Implement "envelopes" (not so easy)
+
+#include "SoundGst.h"
+#include <iostream>
+#include "log.h"
+#include "AudioDecoderNellymoser.h"
+
+#include "gstbuffersrc.h"
+
+namespace gnash {
+namespace media {
+
+
+SoundGst::SoundGst(std::auto_ptr<SoundInfo>& sinfo)
+: _info(sinfo),
+  _dataSize(0)
+{
+  if (!gstBuildPipeline()) {
+    log_error("Failed to build an audio pipeline; no playback.");
+  }  
+}
+
+SoundGst::SoundGst(void* data, unsigned int data_bytes,
+           std::auto_ptr<SoundInfo>& sinfo)
+: _info(sinfo),
+  _dataSize(0),
+  _loop_count(0)
+{
+  assert(data_bytes);
+  
+  boost::uint8_t* data_ptr = reinterpret_cast<boost::uint8_t*>(data);
+
+  
+  if (!gstBuildPipeline()) {
+    log_error("Failed to build an audio pipeline; no playback.");
+  }
+  
+  pushData(data_ptr, data_bytes, 0);
+}
+
+SoundGst::~SoundGst()
+{  
+  gst_element_set_state (_pipeline, GST_STATE_NULL);
+  
+  gst_element_get_state (_pipeline, NULL, NULL, 0);
+  
+  gst_object_unref(GST_OBJECT(_pipeline));
+  
+  std::for_each(_data_vec.begin(), _data_vec.end(),
+                boost::checked_array_deleter<boost::uint8_t>());
+
+}
+ 
+
+long
+SoundGst::pushData(unsigned char* data, unsigned int data_bytes,
+                   unsigned int sample_count)
+{
+  assert(data);
+  
+  if (_info->getFormat() == AUDIO_CODEC_NELLYMOSER_8HZ_MONO ||
+      _info->getFormat() == AUDIO_CODEC_NELLYMOSER) {
+
+    AudioDecoderNellymoser decoder;
+    boost::uint32_t decoded_size;
+    float* decoded_data = decoder.decode(data, data_bytes, &decoded_size);
+    
+    delete [] data;
+    
+    // *whistles*
+    data = reinterpret_cast<unsigned char*>(decoded_data);      
+    data_bytes = decoded_size * sizeof(float);
+  }  
+  
+  _data_vec.push_back(data);
+
+  GstBuffer* buffer = gst_buffer_new();
+  GST_BUFFER_DATA(buffer) = data;
+  GST_BUFFER_SIZE(buffer) = data_bytes;
+  GST_BUFFER_MALLOCDATA(buffer) = NULL;
+  
+  gst_buffer_src_push_buffer_unowned (GST_BUFFER_SRC(_buffersrc), buffer);
+  
+  long ret = _dataSize;
+  _dataSize += data_bytes;
+
+  return ret;
+}
+
+// The offset parameter is used for ActionScript calls, while start is
+// used by the parser. The offset parameter is in seconds, while the start
+// parameter is in samples.
+void
+SoundGst::play(int loop_count, int offset, long start,
+            const std::vector<sound_handler::sound_envelope>* envelopes)
+{
+  GstState state = GST_STATE_NULL;
+  gst_element_get_state (_pipeline, &state, NULL, 0);
+  
+  if (state == GST_STATE_PLAYING) {
+    log_debug(_("Play request while we're already playing: repeat."));
+    if (_loop_count <= 0) {
+      _loop_count++;
+    }
+    return;
+  }
+  
+  _loop_count = loop_count;
+
+  gst_element_set_state (_pipeline, GST_STATE_PAUSED);
+  
+  gst_element_get_state (_pipeline, &state, NULL, 0);
+  
+  gst_element_seek(_pipeline, 1.0, GST_FORMAT_BYTES,
+                       GstSeekFlags(GST_SEEK_FLAG_SEGMENT | 
GST_SEEK_FLAG_FLUSH),
+                       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1);
+
+  gst_element_set_state (_pipeline, GST_STATE_PLAYING);
+  
+}
+
+
+// FIXME: check (and verify) the semantics of this call.
+void
+SoundGst::stop()
+{
+  gst_element_set_state (_pipeline, GST_STATE_NULL);
+}
+  
+unsigned int
+SoundGst::getVolume()
+{
+  gdouble volume = 10;
+  g_object_get(G_OBJECT(_volume), "volume", &volume, NULL);
+  return unsigned(volume * 10);
+}
+
+void
+SoundGst::setVolume(unsigned int new_volume)
+{
+  gdouble volume = new_volume / 10;
+  g_object_set(G_OBJECT(_volume), "volume", volume, NULL);
+}
+  
+void
+SoundGst::mute()
+{
+  g_object_set(G_OBJECT(_volume), "mute", TRUE, NULL);
+}
+
+void
+SoundGst::unmute()
+{
+  g_object_set(G_OBJECT(_volume), "mute", FALSE, NULL);
+}
+
+bool
+SoundGst::muted()
+{
+  gboolean mute = FALSE;
+  g_object_get(G_OBJECT(_volume), "mute", &mute, NULL);
+  return mute;
+}
+
+unsigned int
+SoundGst::duration()
+{
+  GstFormat format = GST_FORMAT_TIME;
+  gint64 duration;
+  bool success = gst_element_query_duration(_pipeline, &format, &duration);
+  
+  if (!success) {
+    return 0;
+  } 
+
+  return unsigned(duration / GST_MSECOND);
+}
+
+unsigned int
+SoundGst::position()
+{
+  GstFormat format = GST_FORMAT_TIME;
+  gint64 position;
+  bool success = gst_element_query_position(_pipeline, &format, &position);
+  
+  if (!success) {
+    return 0;
+  } 
+
+  return unsigned(position / GST_MSECOND);
+}
+  
+SoundInfo*
+SoundGst::getSoundInfo()
+{
+  return _info.get();
+}
+
+/// Creates a GstCaps corresponding to the SoundInfo attached to this SoundGst.
+/// @return a GstCaps pointer, or NULL if the codec type is invalid. The caller
+///         owns the returned pointer.
+GstCaps*
+SoundGst::getCaps()
+{
+  GstCaps* caps = NULL;
+  switch(_info->getFormat())
+  {
+    case AUDIO_CODEC_ADPCM:
+    {
+      caps = gst_caps_new_simple ("audio/x-adpcm",
+                                  "rate", G_TYPE_INT, _info->getSampleRate(),
+                                  "channels", G_TYPE_INT, _info->isStereo() ? 
2 : 1,
+                                  "layout", G_TYPE_STRING, "swf",
+                                  NULL);
+      break;
+    }
+    case AUDIO_CODEC_MP3:
+    {
+      caps = gst_caps_new_simple ("audio/mpeg",
+                                  "mpegversion", G_TYPE_INT, 1,
+                                  "layer", G_TYPE_INT, 3,
+                                  "rate", G_TYPE_INT, _info->getSampleRate(),
+                                  "channels", G_TYPE_INT, _info->isStereo() ? 
2 : 1,
+                                  NULL);
+      break;
+    }
+    case AUDIO_CODEC_RAW:
+    case AUDIO_CODEC_UNCOMPRESSED:
+    {
+
+      caps = gst_caps_new_simple ("audio/x-raw-int",
+                                  "rate", G_TYPE_INT, _info->getSampleRate(),
+                                  "channels", G_TYPE_INT, _info->isStereo() ? 
2 : 1,
+                                  "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, 
// FIXME: how do we know?
+                                  "width", G_TYPE_INT, (_info->is16bit() ? 16 
: 8),
+                                  "depth", G_TYPE_INT, (_info->is16bit() ? 16 
: 7),  // 7 magic?
+                                  "signed", G_TYPE_BOOLEAN, TRUE, // FIXME: 
how do we know?
+                                  NULL);
+      break;
+    }
+    case AUDIO_CODEC_NELLYMOSER_8HZ_MONO:
+    case AUDIO_CODEC_NELLYMOSER:
+    {      
+      std::cout << "nellymoser found" << std::endl;
+      caps = gst_caps_new_simple ("audio/x-raw-float",
+                                  "rate", G_TYPE_INT, _info->getSampleRate(),
+                                  "channels", G_TYPE_INT, _info->isStereo() ? 
2 : 1,
+                                  "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, 
// FIXME: how do we know?
+                                  "width", G_TYPE_INT, 32,
+                                  NULL);
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+  
+  return caps;
+}
+
+
+// This function is inspired by Gstreamer's gst-inspect.c.
+
+/// This function searches the default Gstreamer registry for a decoder that
+/// can sink the given caps.
+/// @param caps The capabilities to search for.
+/// @param name The name to create the new element with.
+/// @return A GstElement with the highest autoplugging rank that can sink the
+///         given caps. The caller owns the returned pointer. NULL if no
+///         capable factory was found.
+GstElement*
+SoundGst::gstFindDecoder(const GstCaps* caps, const gchar* name)
+{
+  GList *features, *l;
+  GstElementFactory *factory = NULL;
+
+  features = gst_registry_get_feature_list (gst_registry_get_default (),
+    GST_TYPE_ELEMENT_FACTORY);
+
+  for (l = features; l != NULL; l = l->next) {
+    GstPluginFeature *feature;
+
+    feature = GST_PLUGIN_FEATURE (l->data);
+    
+    GstElementFactory* cur_factory;
+
+    cur_factory = GST_ELEMENT_FACTORY (feature);
+      
+    if (gst_element_factory_can_sink_caps(cur_factory, caps)) {
+          
+      const gchar* klass = gst_element_factory_get_klass(cur_factory);      
+      if (!g_strrstr(klass, "Codec/Decoder/Audio")) {
+        continue;
+      }
+    
+      if (factory) {
+        guint oldrank = 
gst_plugin_feature_get_rank(GST_PLUGIN_FEATURE(factory));
+        guint newrank = gst_plugin_feature_get_rank(feature);
+        if (newrank < oldrank) {
+          continue;
+        }
+      }
+      
+      factory = cur_factory;      
+    }
+  }
+  
+  GstElement* decoder = NULL;
+  
+  if (factory) {
+    decoder = gst_element_factory_create(factory, NULL);
+  } else {
+    log_error(_("Gnash was unable to find an appropriate Gstreamer audio "
+                "decoder. Please consider installing gstreamer-ffmpeg and/or "
+                "gstreamer-plugins-bad."));
+  }
+
+  g_list_foreach (features, (GFunc) gst_object_unref, NULL);
+  g_list_free (features);
+
+  return decoder;
+}
+
+bool
+SoundGst::needDecoder()
+{
+  switch(_info->getFormat())
+  {
+    case AUDIO_CODEC_ADPCM:
+    case AUDIO_CODEC_MP3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+bool
+SoundGst::gstBuildPipeline()
+{
+  _pipeline = gst_pipeline_new(NULL);
+  
+  _buffersrc = gst_element_factory_make ("buffersrc", NULL);
+  
+  GstCaps* src_caps = getCaps();
+  
+  gst_buffer_src_set_caps (GST_BUFFER_SRC(_buffersrc), src_caps);
+  
+  GstElement* decoder = NULL;
+  
+  if (needDecoder()) {
+    if (_info->getFormat() == AUDIO_CODEC_MP3) {
+      decoder = gstFindDecoder(src_caps, NULL);
+    } else {
+      decoder = gst_bin_new(NULL);
+      
+      GstElement* audioparse = gst_element_factory_make ("mp3parse", NULL);
+      GstElement* actual_decoder = gstFindDecoder(src_caps, NULL);
+      gst_bin_add_many(GST_BIN(decoder), audioparse, actual_decoder, NULL);
+      gst_element_link(audioparse, actual_decoder);
+      
+      GstPad* srcpad = gst_element_get_static_pad (audioparse, "src");
+      GstPad* sinkpad = gst_element_get_static_pad (actual_decoder, "sink");
+      
+      gst_element_add_pad (decoder, gst_ghost_pad_new ("sink", sinkpad));
+      gst_element_add_pad (decoder, gst_ghost_pad_new ("src", srcpad));
+      
+      gst_object_unref (GST_OBJECT (srcpad));
+      gst_object_unref (GST_OBJECT (sinkpad));
+    }
+     
+    
+    // FIXME: if we fail to find a decoder, should we stop here?
+  }
+
+  GstElement* audioconvert = gst_element_factory_make ("audioconvert", NULL);
+
+  GstElement* audioresample = gst_element_factory_make ("audioresample", NULL);
+
+  _volume = gst_element_factory_make ("volume", NULL);
+
+  GstElement* audiosink = gst_element_factory_make ("autoaudiosink", NULL);
+  
+
+  if (decoder) {
+  
+    gst_bin_add_many(GST_BIN(_pipeline), _buffersrc, decoder, _volume,
+                     audioconvert, audioresample, audiosink, NULL);
+
+    gst_element_link_many(_buffersrc, decoder, _volume, audioconvert,
+                          audioresample, audiosink, NULL);
+  } else {    
+    gst_bin_add_many(GST_BIN(_pipeline), _buffersrc,
+                     audioconvert, audioresample, _volume, audiosink, NULL);
+
+    gst_element_link_many(_buffersrc, audioconvert, audioresample,
+                          _volume, audiosink, NULL);
+  
+  }
+  
+  gst_caps_unref(src_caps);
+  
+  if (!_volume || !audioconvert || !audioresample || !audiosink) {
+    log_error("Couldn't load the necessary Gstreamer modules for playback. "
+              "Please ensure a proper gstreamer-plugins-base installation.");
+    return false;
+  }
+  
+  return true;
+}
+
+void SoundGst::poll()
+{
+  if (!_pipeline) {
+    return;
+  }
+
+  GstBus* bus = gst_element_get_bus(_pipeline);
+
+  while (gst_bus_have_pending(bus)) {
+    GstMessage* msg = gst_bus_pop(bus);
+    handleMessage(msg);
+
+    gst_message_unref(msg);
+  }
+
+  gst_object_unref(GST_OBJECT(bus));
+}
+
+
+
+void
+SoundGst::handleMessage (GstMessage *message)
+{
+
+  switch (GST_MESSAGE_TYPE (message)) {
+    case GST_MESSAGE_ERROR:
+    {
+      GError *err;
+      gchar *debug;
+      gst_message_parse_error (message, &err, &debug);
+      
+      log_error(_("Embedded audio playback halted; module %s reported: %s\n"),
+                gst_element_get_name(GST_MESSAGE_SRC (message)), err->message);
+      
+      g_error_free (err);
+      g_free (debug);
+      
+      // Clear any buffers.
+      gst_element_set_state (_pipeline, GST_STATE_NULL);
+
+      break;
+    }
+    case GST_MESSAGE_EOS:
+      gst_element_set_state (_pipeline, GST_STATE_NULL);
+
+      break;    
+    case GST_MESSAGE_SEGMENT_DONE:
+    {      
+      if (_loop_count <= 0) {
+        // This seek from 0 to 0 obviously doesn't do much seeking. However, it
+        // makes sure that we will receive an EOS, since this is a non-flushing
+        // seek which will wait until the segment being played is done.        
+        gst_element_seek(_pipeline, 1.0, GST_FORMAT_BYTES,
+                       GST_SEEK_FLAG_NONE,
+                       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 0);
+        break;
+      }
+      
+      _loop_count--;
+      
+      gst_element_seek(_pipeline, 1.0, GST_FORMAT_BYTES,
+                       GST_SEEK_FLAG_SEGMENT /* non-flushing: seamless seek */,
+                       GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1);
+      break;
+    }    
+    default:
+    {
+#if 0
+      g_print("unhandled message\n");
+#endif
+    }
+  }
+
+}
+
+
+
+} // namespace media
+} // namespace gnash
+

Index: libmedia/gst/SoundGst.h
===================================================================
RCS file: libmedia/gst/SoundGst.h
diff -N libmedia/gst/SoundGst.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundGst.h     8 Feb 2008 15:27:31 -0000       1.1
@@ -0,0 +1,105 @@
+// 
+//   Copyright (C) 2008 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef __GNASH_SOUND_GST_H
+#define __GNASH_SOUND_GST_H
+
+#include <gst/gst.h>
+#include "sound_handler.h"
+#include <boost/utility.hpp>
+#include <boost/scoped_array.hpp>
+
+
+namespace gnash {
+namespace media {
+
+
+/// This class is intended to control a single sound (corresponding to a single
+/// SWF DefineSound or SoundStream set). Objects of this type will be managed
+/// by the sound_handler.
+
+class SoundGst : public boost::noncopyable
+{
+public:
+  SoundGst(std::auto_ptr<SoundInfo>& sinfo);
+  SoundGst(void* data, unsigned int data_bytes,
+           std::auto_ptr<SoundInfo>& sinfo);
+  ~SoundGst();
+ 
+
+  long pushData(unsigned char* data, unsigned int data_bytes,
+                unsigned int sample_count);
+  void play(int loop_count, int secondOffset, long start,
+            const std::vector<sound_handler::sound_envelope>* envelopes);
+  void stop();
+  
+  unsigned int getVolume();
+  void setVolume(unsigned int new_volume);
+  
+  void mute();
+  void unmute();
+  bool muted();
+  
+  
+  unsigned int duration();
+  unsigned int position();
+  
+  SoundInfo* getSoundInfo();
+
+  static void message_received (GstBus * bus, GstMessage * message,
+                                SoundGst* sound);
+                                
+  void poll();
+private: // methods
+
+  GstElement* gstFindDecoder(const GstCaps* caps, const gchar *name);
+  
+  bool gstBuildPipeline();
+  
+  GstCaps* getCaps();
+  
+  void handleMessage (GstMessage *message);
+
+
+
+  bool needDecoder();
+  
+  void setLoopCount(int count);
+
+private: // data fields
+
+  /// A vector of data pointers. There may be only one pointer in this vector
+  /// (in the case of a DefineSound), or several (in the case of a SoundStream)
+  /// This class has ownership of the new[]-allocated pointers.
+  std::vector<uint8_t*> _data_vec;
+  
+  std::auto_ptr<SoundInfo> _info;
+  
+  GstElement* _pipeline;
+  GstElement* _volume;
+  GstElement* _buffersrc;
+  
+  long _dataSize;
+  
+  int _loop_count;
+};
+
+
+} // namespace media
+} // namespace gnash
+
+#endif //__GNASH_SOUND_GST_H

Index: libmedia/gst/SoundHandlerGst.cpp
===================================================================
RCS file: libmedia/gst/SoundHandlerGst.cpp
diff -N libmedia/gst/SoundHandlerGst.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundHandlerGst.cpp    8 Feb 2008 15:27:31 -0000       1.1
@@ -0,0 +1,262 @@
+//   Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#include "SoundHandlerGst.h"
+
+#include <boost/bind.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/mem_fn.hpp>
+#include "log.h"
+#include "vm/VM.h"
+#include "builtin_function.h"
+#include "gnash.h"
+
+namespace gnash {
+namespace media {
+
+#define RETURN_IF_BAD_HANDLE(handle)                                          \
+  if (handle < 0 || handle > int(_sounds.size()) - 1) {                       \
+    return;                                                                   \
+  }
+
+#define RV_IF_BAD_HANDLE(handle, value)                                       \
+  if (handle < 0 || handle > int(_sounds.size()) - 1) {                       \
+    return value;                                                             \
+  }
+
+
+SoundHandlerGst::SoundHandlerGst()
+  : _timer_id(0)
+{
+  gst_init(NULL, NULL);
+  GNASH_REPORT_FUNCTION;
+}
+
+
+SoundHandlerGst::~SoundHandlerGst()
+{
+  std::for_each(_sounds.begin(), _sounds.end(), 
boost::checked_deleter<SoundGst>());
+  
+  _sounds.clear();
+  
+  VM::get().getRoot().clear_interval_timer(_timer_id);
+}
+
+void
+SoundHandlerGst::poll_sounds()
+{
+  std::for_each(_sounds.begin(), _sounds.end(),
+    boost::mem_fn(&SoundGst::poll));
+}
+
+  
+void
+SoundHandlerGst::start_timer()
+{
+  if (_timer_id) {
+    // Timer is already running.
+    return;
+  }
+  
+  boost::intrusive_ptr<builtin_function> poller =
+    new builtin_function(&SoundHandlerGst::poll_cb);
+    
+      
+  boost::intrusive_ptr<as_object> obj(new as_object);
+  
+  std::auto_ptr<Timer> timer (new Timer());
+
+  timer->setInterval(*poller, 50, obj);
+  _timer_id = VM::get().getRoot().add_interval_timer(timer, true);
+}
+
+
+int
+SoundHandlerGst::create_sound(void* data, unsigned int data_bytes,
+                              std::auto_ptr<SoundInfo> sinfo)
+{
+  if (!data) {
+    _sounds.push_back(new SoundGst(sinfo));
+  } else {
+    assert(data_bytes);
+
+    _sounds.push_back(new SoundGst(data, data_bytes, sinfo));
+  }
+
+  // This is our "unique identifier" or "handle". 
+  return _sounds.size()-1;
+}
+
+long
+SoundHandlerGst::fill_stream_data(unsigned char* data, unsigned int bytes,
+                                  unsigned int sample_count, int handle)
+{
+  RV_IF_BAD_HANDLE(handle, 0);
+  
+  return _sounds[handle]->pushData(data, bytes, sample_count);
+}
+
+SoundInfo*
+SoundHandlerGst::get_sound_info(int handle)
+{
+  RV_IF_BAD_HANDLE(handle, NULL);
+  
+  return _sounds[handle]->getSoundInfo();
+}
+
+void
+SoundHandlerGst::play_sound(int handle, int loop_count, int offset,
+           long start, const std::vector<sound_envelope>* envelopes)
+{
+  RETURN_IF_BAD_HANDLE(handle);
+    
+  start_timer();
+
+  _sounds[handle]->play(loop_count, offset, start, envelopes);
+  
+  _soundsStarted++;
+}
+
+void
+SoundHandlerGst::stop_all_sounds()
+{
+  std::for_each(_sounds.begin(), _sounds.end(), 
boost::mem_fn(&SoundGst::stop));
+}
+
+
+int
+SoundHandlerGst::get_volume(int handle)
+{
+  RV_IF_BAD_HANDLE(handle, 0);
+
+  return _sounds[handle]->getVolume();
+}
+       
+void
+SoundHandlerGst::set_volume(int handle, int volume)
+{
+  RETURN_IF_BAD_HANDLE(handle);
+  
+  _sounds[handle]->setVolume(volume);
+}
+               
+void
+SoundHandlerGst::stop_sound(int handle)
+{
+  RETURN_IF_BAD_HANDLE(handle);
+  
+  _sounds[handle]->stop();
+  
+  _soundsStopped++;
+}
+               
+void
+SoundHandlerGst::delete_sound(int handle)
+{
+  RETURN_IF_BAD_HANDLE(handle);
+  
+  std::vector<SoundGst*>::iterator it =
+    std::find(_sounds.begin(), _sounds.end(), _sounds[handle]);
+  
+  SoundGst* sound = *it;
+  
+  _sounds.erase(it);
+  
+  delete sound;
+}
+
+unsigned int
+SoundHandlerGst::get_duration(int handle)
+{
+  RV_IF_BAD_HANDLE(handle, 0);
+  
+  return _sounds[handle]->duration();
+
+}
+
+unsigned int
+SoundHandlerGst::get_position(int handle)
+{
+  RV_IF_BAD_HANDLE(handle, 0);
+  
+  return _sounds[handle]->position();
+}
+
+
+void
+SoundHandlerGst::reset()
+{
+  stop_all_sounds();
+}
+
+void
+SoundHandlerGst::mute()
+{
+  std::for_each(_sounds.begin(), _sounds.end(),
+                boost::mem_fn(&SoundGst::mute));
+}
+
+void
+SoundHandlerGst::unmute()
+{
+  std::for_each(_sounds.begin(), _sounds.end(),
+                boost::mem_fn(&SoundGst::unmute));
+}
+
+
+bool
+SoundHandlerGst::is_muted()
+{
+  using namespace boost;
+
+  std::vector<SoundGst*>::iterator it = std::find_if(_sounds.begin(),
+    _sounds.end(), bind( std::logical_not<bool>(), 
+                         bind(&SoundGst::muted, _1) ) );
+    
+  return (it == _sounds.end());
+}
+
+#undef RETURN_IF_BAD_HANDLE
+#undef RV_IF_BAD_HANDLE
+
+/* static */ as_value
+SoundHandlerGst::poll_cb(const fn_call& /*fn*/)
+{
+  sound_handler* handler = get_sound_handler();
+  SoundHandlerGst* handler_gst = dynamic_cast<SoundHandlerGst*>(handler);
+  assert(handler_gst);
+  
+  handler_gst->poll_sounds();
+  
+  return as_value();
+}
+
+
+
+sound_handler* create_sound_handler_gst()
+// Factory.
+{
+  GNASH_REPORT_FUNCTION;
+       return new SoundHandlerGst;
+}
+
+
+} // namespace media
+} // namespace gnash
+
+
+
+

Index: libmedia/gst/SoundHandlerGst.h
===================================================================
RCS file: libmedia/gst/SoundHandlerGst.h
diff -N libmedia/gst/SoundHandlerGst.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundHandlerGst.h      8 Feb 2008 15:27:31 -0000       1.1
@@ -0,0 +1,82 @@
+//   Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef __SOUND_HANDLER_GST_H
+#define __SOUND_HANDLER_GST_H
+
+#include "SoundGst.h"
+#include "timers.h"
+#include "as_value.h"
+
+namespace gnash {
+namespace media {
+
+class SoundHandlerGst : public sound_handler
+{
+public:
+  SoundHandlerGst();
+  ~SoundHandlerGst();
+
+  int create_sound(void* data, unsigned int data_bytes,
+                   std::auto_ptr<SoundInfo> sinfo);
+
+  long fill_stream_data(unsigned char* data, unsigned int data_bytes,
+                        unsigned int sample_count, int handle_id);
+
+  SoundInfo* get_sound_info(int sound_handle);
+
+  void play_sound(int sound_handle, int loop_count, int secondOffset,
+                  long start, const std::vector<sound_envelope>* envelopes);
+
+  void stop_all_sounds();
+
+  int get_volume(int sound_handle);
+       
+  void set_volume(int sound_handle, int volume);
+               
+  void stop_sound(int sound_handle);
+               
+  void delete_sound(int sound_handle);
+  
+  void poll_sounds();
+
+  void reset();
+               
+  void mute();
+
+  void unmute();
+
+  bool is_muted();
+
+  unsigned int get_duration(int sound_handle);
+
+  unsigned int get_position(int sound_handle);
+  
+  void start_timer();
+  
+  static as_value poll_cb(const fn_call& fn);
+
+private:
+  std::vector<SoundGst*> _sounds;
+  unsigned int _timer_id;  
+}; // SoundHandlerGst
+
+} // namespace media
+} // namespace gnash
+
+
+#endif // __SOUND_HANDLER_GST_H
+

Index: libmedia/gst/gstbuffersrc.c
===================================================================
RCS file: libmedia/gst/gstbuffersrc.c
diff -N libmedia/gst/gstbuffersrc.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstbuffersrc.c 8 Feb 2008 15:27:31 -0000       1.1
@@ -0,0 +1,424 @@
+// 
+//   Copyright (C) 2008 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// 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.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// This file incorporates work covered by the following copyright and 
permission
+// notice:
+
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include "gstbuffersrc.h"
+
+
+GST_DEBUG_CATEGORY (buffer_src_debug);
+#define GST_CAT_DEFAULT buffer_src_debug
+
+static const GstElementDetails buffer_src_details = GST_ELEMENT_DETAILS 
("BufferSrc",
+    "FIXME",
+    "FIXME",
+    "autogenerated by makefilter");
+
+enum
+{
+  PROP_0
+};
+
+static GstStaticPadTemplate gst_buffer_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS_ANY);
+
+static void gst_buffer_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_buffer_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_buffer_src_dispose (GObject * object);
+static GstFlowReturn gst_buffer_src_create (GstBaseSrc *src, guint64 offset, 
guint size, GstBuffer **buf);
+static gboolean gst_buffer_src_start (GstBaseSrc * psrc);
+static gboolean gst_buffer_src_stop (GstBaseSrc * psrc);
+static gboolean gst_buffer_is_seekable (GstBaseSrc *src);
+static gboolean gst_buffer_get_size (GstBaseSrc *src, guint64 *size);
+static gboolean gst_buffer_check_get_range (GstBaseSrc *src);
+
+GST_BOILERPLATE (GstBufferSrc, gst_buffer_src, GstBaseSrc, GST_TYPE_BASE_SRC);
+
+
+static void
+gst_buffer_src_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  GST_DEBUG_CATEGORY_INIT (buffer_src_debug, "buffersrc", 0, "buffersrc 
element");
+
+  gst_element_class_set_details (element_class, &buffer_src_details);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_buffer_src_template));
+
+}
+
+static void
+gst_buffer_src_class_init (GstBufferSrcClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass;
+
+  gobject_class->set_property = gst_buffer_src_set_property;
+  gobject_class->get_property = gst_buffer_src_get_property;
+  gobject_class->dispose = gst_buffer_src_dispose;
+
+  basesrc_class->create = gst_buffer_src_create;
+  basesrc_class->is_seekable = gst_buffer_is_seekable;
+  basesrc_class->start = gst_buffer_src_start;
+  basesrc_class->stop = gst_buffer_src_stop;
+  basesrc_class->get_size = gst_buffer_get_size;
+  basesrc_class->check_get_range = gst_buffer_check_get_range;
+}
+
+static void
+gst_buffer_src_dispose (GObject * obj)
+{
+  GstBufferSrc *buffersrc = GST_BUFFER_SRC (obj);
+
+  if (buffersrc->queue) {
+    gst_buffer_src_flush (buffersrc);
+    g_queue_free (buffersrc->queue);
+    buffersrc->queue = NULL;
+  }
+  if (buffersrc->caps) {
+    gst_caps_unref (buffersrc->caps);
+    buffersrc->caps = NULL;
+  }
+  if (buffersrc->mutex) {
+    g_mutex_free (buffersrc->mutex);
+    buffersrc->mutex = NULL;
+  }
+  if (buffersrc->cond) {
+    g_cond_free (buffersrc->cond);
+    buffersrc->cond = NULL;
+  }
+
+
+  G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+gst_buffer_src_init (GstBufferSrc * buffersrc, GstBufferSrcClass * klass)
+{
+  UNUSEDPAR(klass);
+
+  buffersrc->mutex = g_mutex_new ();
+  buffersrc->cond = g_cond_new ();
+  buffersrc->queue = g_queue_new ();
+  buffersrc->total_size = 0;
+}
+
+static void
+gst_buffer_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  UNUSEDPAR(value);
+  GstBufferSrc *buffersrc = GST_BUFFER_SRC (object);
+
+  GST_OBJECT_LOCK (buffersrc);
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (buffersrc);
+}
+
+static void
+gst_buffer_src_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  UNUSEDPAR(value);
+  GstBufferSrc *buffersrc = GST_BUFFER_SRC (object);
+
+  GST_OBJECT_LOCK (buffersrc);
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (buffersrc);
+}
+
+static gboolean
+gst_buffer_src_start (GstBaseSrc * psrc)
+{
+  UNUSEDPAR(psrc);
+
+#if 0
+  /* FIXME: I don't know if this makes sense */
+  buffersrc->end_of_stream = FALSE;
+  buffersrc->flush = FALSE;
+#endif
+
+  return TRUE;
+}
+
+static gboolean
+gst_buffer_src_stop (GstBaseSrc * psrc)
+{
+  UNUSEDPAR(psrc);
+
+  return TRUE;
+}
+
+
+static GstBuffer*
+gst_buffer_src_find_offset (GstBufferSrc * buffersrc, guint64* offset)
+{
+  guint i;
+
+  guint64 bytes = 0;
+  guint64 prev_bytes = 0;
+  
+  for (i = 0; i < g_queue_get_length(buffersrc->queue); ++i) {
+    GstBuffer* buf = g_queue_peek_nth(buffersrc->queue, i);
+    assert(buf);
+    
+    prev_bytes = bytes;
+    bytes += GST_BUFFER_SIZE(buf);
+
+    if (bytes > *offset) {
+      *offset = *offset - prev_bytes;
+      return buf;
+    }
+  }
+ 
+  return NULL;
+}
+
+static GstFlowReturn
+gst_buffer_src_create (GstBaseSrc *src, guint64 offset, guint size,
+                                GstBuffer **buf)
+{  
+  GstBufferSrc *buffersrc = GST_BUFFER_SRC (src);
+  int ret = GST_FLOW_ERROR;
+
+  g_mutex_lock (buffersrc->mutex);
+
+  while (1) {
+    if (!g_queue_is_empty (buffersrc->queue)) {
+
+      guint64 buf_offset = offset;
+      GstBuffer* bigbuf = gst_buffer_src_find_offset (buffersrc, &buf_offset);
+    
+      if (!bigbuf) {
+        ret = GST_FLOW_UNEXPECTED;  // EOS
+        break;
+      }
+
+      guint avail_size = GST_BUFFER_SIZE(bigbuf) - buf_offset;
+
+      guint subsize = MIN(avail_size, size);
+
+      *buf = gst_buffer_create_sub (bigbuf, buf_offset, subsize);
+
+      GST_BUFFER_OFFSET(*buf) = offset;
+      GST_BUFFER_OFFSET_END(*buf) = offset + subsize;
+
+      gst_buffer_set_caps (*buf, buffersrc->caps);
+
+      ret = GST_FLOW_OK;
+      break;
+    }
+    if (buffersrc->end_of_stream) {
+      buffersrc->end_of_stream = FALSE;
+      ret = GST_FLOW_UNEXPECTED;
+      break;
+    }
+    if (buffersrc->flush) {
+      buffersrc->flush = FALSE;
+      /* FIXME: I don't really know how to do this */
+      break;
+    }
+    g_cond_wait (buffersrc->cond, buffersrc->mutex);
+  }
+
+  g_mutex_unlock (buffersrc->mutex);
+  return ret;
+}
+
+static gboolean 
+gst_buffer_is_seekable  (GstBaseSrc *src)
+{
+  UNUSEDPAR(src);
+
+  return TRUE;
+}
+
+static gboolean 
+gst_buffer_get_size (GstBaseSrc *src, guint64 *size)
+{
+  GstBufferSrc* buffersrc = (GstBufferSrc*)src;
+  
+  g_mutex_lock (buffersrc->mutex);
+
+  *size = buffersrc->total_size;
+
+  g_mutex_unlock (buffersrc->mutex);
+  
+  return TRUE;
+}
+
+static gboolean
+gst_buffer_check_get_range (GstBaseSrc* src)
+{
+  UNUSEDPAR(src);
+  return TRUE;
+}
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  GST_DEBUG_CATEGORY_INIT (buffer_src_debug, "buffersrc", 0, "Application 
source");
+
+  if (!gst_element_register (plugin, "buffersrc", GST_RANK_PRIMARY,
+          gst_buffer_src_get_type ()))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR,
+    "buffersrc", "Element application source",
+    plugin_init, VERSION, "LGPL", "Gnash's buffer source", "Gnash")
+
+
+/* external API */
+
+/**
+ * gst_buffer_src_push_buffer_unowned:
+ *  @buffersrc:
+ *  @buffer:
+ * 
+ * Adds a buffer to the queue of buffers that the buffersrc element will
+ * push to its source pad, when requested.
+ *
+ * This function does NOT take ownership of the buffer. The caller is
+ * responsible for destroying the buffer, but can only do so after it has
+ * cleared the pipeline and the buffer_src's internal queue has been flushed.
+ *
+ * This function will create sub-buffers of the passed buffer as needed, so
+ * its size does not matter.
+ */
+void
+gst_buffer_src_push_buffer_unowned (GstBufferSrc * buffersrc, GstBuffer * 
buffer)
+{
+  g_return_if_fail (buffersrc);
+  g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+  g_mutex_lock (buffersrc->mutex);
+
+  g_queue_push_tail (buffersrc->queue, buffer);
+  buffersrc->total_size += GST_BUFFER_SIZE(buffer);
+
+  g_cond_signal (buffersrc->cond);
+  g_mutex_unlock (buffersrc->mutex);
+}
+
+
+/**
+ * gst_buffer_src_set_caps:
+ * @buffersrc:
+ * @caps:
+ *
+ * Set the capabilities on the buffersrc element.  This function takes
+ * ownership of the caps structure.
+ */
+void
+gst_buffer_src_set_caps (GstBufferSrc * buffersrc, GstCaps * caps)
+{
+  g_return_if_fail (buffersrc);
+  g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+  gst_caps_replace (&buffersrc->caps, caps);
+}
+
+/**
+ * gst_buffer_src_flush:
+ * @buffersrc:
+ *
+ * Flushes all queued buffers from the buffersrc element.
+ */
+void
+gst_buffer_src_flush (GstBufferSrc * buffersrc)
+{
+  GstBuffer *buffer;
+
+  g_return_if_fail (buffersrc);
+  g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+  g_mutex_lock (buffersrc->mutex);
+
+  while ((buffer = g_queue_pop_head (buffersrc->queue))) {
+    gst_buffer_unref (buffer);
+  }
+  buffersrc->flush = TRUE;
+
+  g_cond_signal (buffersrc->cond);
+  g_mutex_unlock (buffersrc->mutex);
+}
+
+/**
+ * gst_buffer_src_end_of_stream:
+ * @buffersrc:
+ *
+ * Indicates to the buffersrc element that the last buffer queued in the
+ * element is the last buffer of the stream.
+ */
+void
+gst_buffer_src_end_of_stream (GstBufferSrc * buffersrc)
+{
+  g_return_if_fail (buffersrc);
+  g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+  g_mutex_lock (buffersrc->mutex);
+
+  buffersrc->end_of_stream = TRUE;
+
+  g_cond_signal (buffersrc->cond);
+  g_mutex_unlock (buffersrc->mutex);
+}

Index: libmedia/gst/gstbuffersrc.h
===================================================================
RCS file: libmedia/gst/gstbuffersrc.h
diff -N libmedia/gst/gstbuffersrc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstbuffersrc.h 8 Feb 2008 15:27:31 -0000       1.1
@@ -0,0 +1,95 @@
+// 
+//   Copyright (C) 2008 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// 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.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// This file incorporates work covered by the following copyright and 
permission
+// notice:
+
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+ 
+#ifndef _GNASH_BUFFER_SRC_H_
+#define _GNASH_BUFFER_SRC_H_
+
+#define UNUSEDPAR(x)  { x = x; }
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesrc.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_BUFFER_SRC \
+  (gst_buffer_src_get_type())
+#define GST_BUFFER_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BUFFER_SRC,GstBufferSrc))
+#define GST_BUFFER_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BUFFER_SRC,GstBufferSrcClass))
+#define GST_IS_BUFFER_SRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BUFFER_SRC))
+#define GST_IS_BUFFER_SRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BUFFER_SRC))
+
+typedef struct _GstBufferSrc GstBufferSrc;
+typedef struct _GstBufferSrcClass GstBufferSrcClass;
+
+struct _GstBufferSrc
+{
+  GstBaseSrc basesrc;
+
+  /*< private >*/
+  GCond *cond;
+  GMutex *mutex;
+  GQueue *queue;
+  GstCaps *caps;
+  gboolean end_of_stream;
+  gboolean flush;
+  guint64 total_size;
+};
+
+struct _GstBufferSrcClass
+{
+  GstBaseSrcClass basesrc_class;
+};
+
+GType gst_buffer_src_get_type(void);
+
+GST_DEBUG_CATEGORY_EXTERN (buffer_src_debug);
+
+
+void gst_buffer_src_push_buffer_unowned (GstBufferSrc *buffersrc, GstBuffer 
*buffer);
+void gst_buffer_src_set_caps (GstBufferSrc *buffersrc, GstCaps *caps);
+void gst_buffer_src_end_of_stream (GstBufferSrc *buffersrc);
+void gst_buffer_src_flush (GstBufferSrc * buffersrc);
+
+G_END_DECLS
+
+#endif
+

Index: libmedia/gst/gstgnashsrc.c
===================================================================
RCS file: libmedia/gst/gstgnashsrc.c
diff -N libmedia/gst/gstgnashsrc.c
--- libmedia/gst/gstgnashsrc.c  21 Jan 2008 23:10:15 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,328 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// 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.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-// 
-// Based on the filesrc and fdsrc element in Gstreamer-core.
-//
-
-/* $Id: gstgnashsrc.c,v 1.2 2008/01/21 23:10:15 rsavoye Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "gnashconfig.h"
-#endif
-
-#include "gstgnashsrc.h"
-
-static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS_ANY);
-
-
-GST_DEBUG_CATEGORY_STATIC (gst_gnash_src_debug);
-#define GST_CAT_DEFAULT gst_gnash_src_debug
-
-static const GstElementDetails gst_gnash_src_details =
-GST_ELEMENT_DETAILS ("Gnash source",
-    "Gnash",
-    "Use callback to read from Gnash",
-    "Gnash team");
-
-/* GnashSrc signals and args */
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-#define DEFAULT_BLOCKSIZE      4*1024
-#define DEFAULT_DATA           NULL
-#define DEFAULT_CALLBACKS      NULL
-
-enum
-{
-  ARG_0,
-  ARG_DATA,
-  ARG_CALLBACKS
-};
-
-static void gst_gnash_src_finalize (GObject * object);
-
-static void gst_gnash_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_gnash_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-
-static gboolean gst_gnash_src_start (GstBaseSrc * basesrc);
-static gboolean gst_gnash_src_stop (GstBaseSrc * basesrc);
-
-static gboolean gst_gnash_src_is_seekable (GstBaseSrc * src);
-static gboolean gst_gnash_src_get_size (GstBaseSrc * src, guint64 * size);
-static GstFlowReturn gst_gnash_src_create (GstPushSrc * src, GstBuffer ** 
buffer);
-static gboolean gst_gnash_src_do_seek (GstBaseSrc * src, GstSegment * s);
-
-static void
-_do_init (GType gnashsrc_type)
-{
-       UNUSEDPAR(gnashsrc_type);
-/*  static const GInterfaceInfo urihandler_info = {
-    gst_gnash_src_uri_handler_init,
-    NULL,
-    NULL
-  };*/
-
-  GST_DEBUG_CATEGORY_INIT (gst_gnash_src_debug, "gnashsrc", 0, "gnashsrc 
element");
-}
-
-GST_BOILERPLATE_FULL (GstGnashSrc, gst_gnash_src, GstElement, 
GST_TYPE_PUSH_SRC, _do_init);
-
-static void
-gst_gnash_src_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&srctemplate));
-
-  gst_element_class_set_details (gstelement_class, &gst_gnash_src_details);
-}
-
-static void
-gst_gnash_src_class_init (GstGnashSrcClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-  GstBaseSrcClass *gstbasesrc_class;
-  GstPushSrcClass *gstpush_src_class;
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gstelement_class = GST_ELEMENT_CLASS (klass);
-  gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
-  gstpush_src_class = GST_PUSH_SRC_CLASS (klass);
-
-  gobject_class->set_property = gst_gnash_src_set_property;
-  gobject_class->get_property = gst_gnash_src_get_property;
-
-  g_object_class_install_property (gobject_class, ARG_DATA,
-      g_param_spec_pointer ("data", NULL, NULL, 
(GParamFlags)G_PARAM_READWRITE));
-
-  g_object_class_install_property (gobject_class, ARG_CALLBACKS,
-      g_param_spec_pointer ("callbacks", NULL, NULL, 
(GParamFlags)G_PARAM_READWRITE));
-
-  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gnash_src_finalize);
-
-  gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnash_src_start);
-  gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnash_src_stop);
-  gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR 
(gst_gnash_src_is_seekable);
-  gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnash_src_get_size);
-  gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_gnash_src_do_seek);
-
-  gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_gnash_src_create);
-}
-
-static void
-gst_gnash_src_init (GstGnashSrc * src, GstGnashSrcClass * g_class)
-{
-  UNUSEDPAR(g_class);
-  src->data = NULL;
-  src->callbacks = NULL;
-  src->read_position = 0;
-}
-
-static void
-gst_gnash_src_finalize (GObject * object)
-{
-  GstGnashSrc *src;
-
-  src = GST_GNASH_SRC (object);
-
-  free (src->callbacks);
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_gnash_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGnashSrc *src;
-
-  g_return_if_fail (GST_IS_GNASH_SRC (object));
-
-  src = GST_GNASH_SRC (object);
-
-  switch (prop_id) {
-    case ARG_DATA:
-      src->data = g_value_get_pointer (value);
-      break;
-    case ARG_CALLBACKS:
-      src->callbacks = g_value_get_pointer (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_gnash_src_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
-{
-  GstGnashSrc *src;
-  UNUSEDPAR(value);
-  g_return_if_fail (GST_IS_GNASH_SRC (object));
-
-  src = GST_GNASH_SRC (object);
-
-  switch (prop_id) {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-//
-// Below is the functions used get make this plugin work.
-//
-
-// Used for seeking
-static gboolean
-gst_gnash_src_do_seek (GstBaseSrc * basesrc, GstSegment * seg)
-{
-
-  GstGnashSrc *src;
-  off_t res;
-  src = GST_GNASH_SRC (basesrc);
-
-  if (seg->format != GST_FORMAT_BYTES) return FALSE;
-
-  struct gnashsrc_callback *gc;
-  gc = src->callbacks;
-  res = gc->seek (src->data, seg->start, SEEK_CUR);
-  return TRUE;
-
-}
-
-// Output the next buffer
-static GstFlowReturn
-gst_gnash_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
-{
-  GstGnashSrc *src;
-  src = GST_GNASH_SRC (psrc);
-  int ret, blocksize;
-  GstBuffer *buf;
-
-  struct gnashsrc_callback *gc;
-  gc = src->callbacks;
-
-  blocksize = GST_BASE_SRC (src)->blocksize;
-  buf = gst_buffer_new_and_alloc (blocksize);
-
-  GST_LOG_OBJECT (src, "Reading %d bytes", blocksize);
-
-  ret = gc->read(src->data, (void*)GST_BUFFER_DATA(buf), blocksize);
-       
-  if (G_UNLIKELY (ret < 0)) goto could_not_read;
-
-  /* other files should eos if they read 0 and more was requested */
-  if (G_UNLIKELY (ret == 0 && blocksize > 0))
-    goto eos;
-
-  blocksize = ret;
-
-  GST_BUFFER_SIZE (buf) = blocksize;
-  GST_BUFFER_OFFSET (buf) = src->read_position;
-  GST_BUFFER_OFFSET_END (buf) = src->read_position + blocksize;
-
-  *outbuf = buf;
-
-  src->read_position += blocksize;
-
-  return GST_FLOW_OK;
-
-  /* ERROR */
-could_not_read:
-  {
-    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
-    gst_buffer_unref (buf);
-    return GST_FLOW_ERROR;
-  }
-eos:
-  {
-    GST_DEBUG ("non-regular file hits EOS");
-    gst_buffer_unref (buf);
-    return GST_FLOW_UNEXPECTED;
-  }
-}
-
-static gboolean
-gst_gnash_src_is_seekable (GstBaseSrc * basesrc)
-{
-  GstGnashSrc *src = GST_GNASH_SRC (basesrc);
-
-  return src->seekable;
-}
-
-// Get size of the file. Not sure how we shall handles this...
-static gboolean
-gst_gnash_src_get_size (GstBaseSrc * basesrc, guint64 * size)
-{
-  GstGnashSrc *src;
-
-  src = GST_GNASH_SRC (basesrc);
-
-  if (!src->seekable) {
-    /* If it isn't seekable, we won't know the length (but fstat will still
-     * succeed, and wrongly say our length is zero. */
-    return FALSE;
-  }
-  return FALSE;
-
-  // Since it's a streamed video file we probably don't know the length, so we
-  // tell it's 50000. Maybe we should just return FALSE?
-  *size = 500000;
-  return TRUE;
-
-}
-
-/* open the file and mmap it, necessary to go to READY state */
-static gboolean
-gst_gnash_src_start (GstBaseSrc * basesrc)
-{
-  GstGnashSrc *src = GST_GNASH_SRC (basesrc);
-
-  if (src->data == NULL || src->callbacks == NULL) {
-    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,(("No data or callback struct 
supplied.")), (NULL));
-    return FALSE;
-  }
-
-  src->read_position = 0;
-  GST_INFO_OBJECT (src, "Ready for reading using callbacks");
-
-  // TODO: set seekable to false when real streaming
-  src->seekable = TRUE;
-
-  return TRUE;
-
-}
-
-/* stop and free */
-static gboolean
-gst_gnash_src_stop (GstBaseSrc * basesrc)
-{
-  GstGnashSrc *src = GST_GNASH_SRC (basesrc);
-  UNUSEDPAR(src);
-  return TRUE;
-}
-

Index: libmedia/gst/gstgnashsrc.h
===================================================================
RCS file: libmedia/gst/gstgnashsrc.h
diff -N libmedia/gst/gstgnashsrc.h
--- libmedia/gst/gstgnashsrc.h  21 Jan 2008 23:10:15 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,81 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// 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.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-// 
-// Based on the filesrc and fdsrc element in Gstreamer-core
-//
-
-/* $Id: gstgnashsrc.h,v 1.2 2008/01/21 23:10:15 rsavoye Exp $ */
-
-#ifndef __GST_GNASH_SRC_H__
-#define __GST_GNASH_SRC_H__
-
-#define UNUSEDPAR(x)  { x = x; }
-
-
-#include <gst/gst.h>
-#include <gst/base/gstpushsrc.h>
-
-// Struct to contain the callback functions
-struct gnashsrc_callback {
-       int (*read)(void* data, char* buf, int buf_size);
-       int (*seek)(void* data, int offset, int whence);
-};
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNASH_SRC \
-  (gst_gnash_src_get_type())
-#define GST_GNASH_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNASH_SRC,GstGnashSrc))
-#define GST_GNASH_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNASH_SRC,GstGnashSrcClass))
-#define GST_IS_GNASH_SRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNASH_SRC))
-#define GST_IS_GNASH_SRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNASH_SRC))
-
-typedef struct _GstGnashSrc GstGnashSrc;
-typedef struct _GstGnashSrcClass GstGnashSrcClass;
-
-/**
- * GstGnashSrc:
- *
- * Opaque #GstGnashSrc structure.
- */
-struct _GstGnashSrc {
-  GstPushSrc element;
-
-  /*< private >*/
-
-  guint64 read_position;       // position in the stream
-
-  gpointer data;                // data passes with the callbacks
-  gpointer callbacks;          // struct with the callbacks
-
-  gboolean seekable;           // seekable or not
-
-};
-
-struct _GstGnashSrcClass {
-  GstPushSrcClass parent_class;
-};
-
-GType gst_gnash_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNASH_SRC_H__ */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]