gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog backend/Makefile.am backend/gna...


From: Tomas Groth
Subject: [Gnash-commit] gnash ChangeLog backend/Makefile.am backend/gna...
Date: Mon, 24 Jul 2006 13:30:51 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Tomas Groth <tgc>       06/07/24 13:30:51

Modified files:
        .              : ChangeLog 
        backend        : Makefile.am gnash.cpp sound_handler_sdl.cpp 
        gui            : gnash.cpp 
        macros         : gstreamer.m4 
        plugin         : player.cpp 
        server         : gnash.h impl.cpp sound.cpp 
        server/swf     : tag_loaders.h 
Added files:
        backend        : sound_handler_gst.cpp 

Log message:
        Added the new Gstreamer based soundbackend. It still needs some work!

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.503&r2=1.504
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/Makefile.am?cvsroot=gnash&r1=1.25&r2=1.26
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/gnash.cpp?cvsroot=gnash&r1=1.46&r2=1.47
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_sdl.cpp?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_gst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/gnash.cpp?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/macros/gstreamer.m4?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/plugin/player.cpp?cvsroot=gnash&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/gnash/server/gnash.h?cvsroot=gnash&r1=1.32&r2=1.33
http://cvs.savannah.gnu.org/viewcvs/gnash/server/impl.cpp?cvsroot=gnash&r1=1.46&r2=1.47
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sound.cpp?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/tag_loaders.h?cvsroot=gnash&r1=1.4&r2=1.5

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.503
retrieving revision 1.504
diff -u -b -r1.503 -r1.504
--- ChangeLog   23 Jul 2006 00:15:41 -0000      1.503
+++ ChangeLog   24 Jul 2006 13:30:50 -0000      1.504
@@ -1,3 +1,10 @@
+2006-07-24 Tomas Groth Christensen <address@hidden>
+
+        * Makefile.am, backend/Makefile.am, backend/gnash.cpp, 
+       backend/sound_handler_gst.cpp gui/gnash.cpp, plugin/player.cpp, 
+       server/gnash.h: Added the new Gstreamer based soundbackend. It still
+       needs some work!
+
 2006-07-23 Sandro Santilli <address@hidden>
 
        * gui/gnash.cpp: fixed delay to respect FPS.

Index: backend/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/backend/Makefile.am,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -b -r1.25 -r1.26
--- backend/Makefile.am 22 Jul 2006 23:47:55 -0000      1.25
+++ backend/Makefile.am 24 Jul 2006 13:30:50 -0000      1.26
@@ -46,7 +46,8 @@
        $(X_LIBS)               \
        $(DMALLOC_LIBS)         \
        $(MP3_LIBS)             \
-       $(PTHREAD_LIBS)
+       $(PTHREAD_LIBS)         \
+       $(GSTREAMER_LIBS)
 
 INCLUDES = -I.. \
         -I$(top_srcdir)        \
@@ -69,7 +70,8 @@
        $(PNG_CFLAGS)           \
        $(JPEG_CFLAGS)          \
        $(MP3_CFLAGS)           \
-       $(OGG_CFLAGS)
+       $(OGG_CFLAGS)           \
+       $(GSTREAMER_CFLAGS)
 
 # bin_PROGRAMS = gnash
 
@@ -86,6 +88,7 @@
 libgnashbackend_la_SOURCES = \
        $(RENDER_SOURCES) \
        sound_handler_sdl.cpp \
+       sound_handler_gst.cpp \
        gtksup.cpp gtksup.h
 
 # gnash_SOURCES = gnash.cpp

Index: backend/gnash.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/gnash.cpp,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -b -r1.46 -r1.47
--- backend/gnash.cpp   10 Jul 2006 13:48:06 -0000      1.46
+++ backend/gnash.cpp   24 Jul 2006 13:30:50 -0000      1.47
@@ -429,6 +429,10 @@
             sound = gnash::create_sound_handler_sdl();
             gnash::set_sound_handler(sound);
 #endif
+#ifdef HAVE_GST_GST_H
+            sound = gnash::create_sound_handler_gst();
+            gnash::set_sound_handler(sound);
+#endif
         }
     }
     

Index: backend/sound_handler_sdl.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/sound_handler_sdl.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- backend/sound_handler_sdl.cpp       7 Jun 2006 03:03:22 -0000       1.11
+++ backend/sound_handler_sdl.cpp       24 Jul 2006 13:30:50 -0000      1.12
@@ -106,7 +106,8 @@
                int sample_count,
                format_type format,
                int sample_rate,
-               bool stereo)
+               bool stereo,
+               bool stream)
        // Called to create a sample.  We'll return a sample ID that
        // can use for playing it.
        {

Index: gui/gnash.cpp
===================================================================
RCS file: /sources/gnash/gnash/gui/gnash.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- gui/gnash.cpp       23 Jul 2006 00:15:42 -0000      1.15
+++ gui/gnash.cpp       24 Jul 2006 13:30:50 -0000      1.16
@@ -280,6 +280,11 @@
         (gnash::create_sound_handler_sdl());
       gnash::set_sound_handler(sound.get());
 #endif
+#ifdef HAVE_GST_GST_H
+      sound = std::auto_ptr<gnash::sound_handler>
+        (gnash::create_sound_handler_gst());
+      gnash::set_sound_handler(sound.get());
+#endif
     }
 
     // Get info about the width & height of the movie.

Index: macros/gstreamer.m4
===================================================================
RCS file: /sources/gnash/gnash/macros/gstreamer.m4,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- macros/gstreamer.m4 24 May 2006 11:26:04 -0000      1.6
+++ macros/gstreamer.m4 24 Jul 2006 13:30:50 -0000      1.7
@@ -122,10 +122,10 @@
           for i in $libslist; do
            if test -f $i/libgstreamer-${gnash_gstreamer_version}.a -o -f 
$i/libgstreamer-${gnash_gstreamer_version}.so; then
              if test x"$i" != x"/usr/lib"; then
-               ac_cv_path_gstreamer_lib="-L$i -lgstreamer"
+               ac_cv_path_gstreamer_lib="-L$i 
-lgstreamer-${gnash_gstreamer_version}"
                break
               else
-               ac_cv_path_gstreamer_lib="-lgstreamer"
+               
ac_cv_path_gstreamer_lib="-lgstreamer-${gnash_gstreamer_version}"
                break
              fi
            else

Index: plugin/player.cpp
===================================================================
RCS file: /sources/gnash/gnash/plugin/player.cpp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- plugin/player.cpp   8 May 2006 21:12:24 -0000       1.14
+++ plugin/player.cpp   24 Jul 2006 13:30:50 -0000      1.15
@@ -340,6 +340,12 @@
        gnash::set_sound_handler(sound);
     }
 #endif
+#ifdef HAVE_GST_GST_H
+    if (do_sound) {
+       sound = gnash::create_sound_handler_sdl();
+       gnash::set_sound_handler(sound);
+    }
+#endif
     inst->lockDisplay();
     render = gnash::create_render_handler_ogl();
     gnash::set_render_handler(render);

Index: server/gnash.h
===================================================================
RCS file: /sources/gnash/gnash/server/gnash.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- server/gnash.h      21 Jun 2006 08:46:03 -0000      1.32
+++ server/gnash.h      24 Jul 2006 13:30:51 -0000      1.33
@@ -161,6 +161,7 @@
 render_handler*        create_render_handler_cairo(void* cairohandle);
 
 sound_handler* create_sound_handler_sdl();
+sound_handler* create_sound_handler_gst();
 
 class font;
 struct character_def;
@@ -404,9 +405,13 @@
                int             sample_count,
                format_type     format,
                int             sample_rate,    /* one of 5512, 11025, 22050, 
44100 */
-               bool            stereo
+               bool            stereo,
+               bool            stream
                ) = 0;
-               
+#ifdef HAVE_GST_GST_H
+       // gnash calls this to fill up soundstreams data
+       virtual void    fill_stream_data(void* data, int data_bytes) = 0;
+#endif
        // gnash calls this when it wants you to play the defined sound.
        //
        // loop_count == 0 means play the sound once (1 means play it twice, 
etc)

Index: server/impl.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/impl.cpp,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -b -r1.46 -r1.47
--- server/impl.cpp     7 Jul 2006 13:49:40 -0000       1.46
+++ server/impl.cpp     24 Jul 2006 13:30:51 -0000      1.47
@@ -207,8 +207,8 @@
        register_tag_loader(SWF::STARTSOUND,    start_sound_loader);
        // 16 _UNKNOWN_ unimplemented
        register_tag_loader(SWF::DEFINEBUTTONSOUND, button_sound_loader);
-       register_tag_loader(SWF::SOUNDSTREAMHEAD, fixme_loader); // 18
-       register_tag_loader(SWF::SOUNDSTREAMBLOCK, fixme_loader); // 19
+       register_tag_loader(SWF::SOUNDSTREAMHEAD, sound_stream_head_loader); // 
18
+       register_tag_loader(SWF::SOUNDSTREAMBLOCK, sound_stream_block_loader); 
// 19
        register_tag_loader(SWF::DEFINELOSSLESS, define_bits_lossless_2_loader);
        register_tag_loader(SWF::DEFINEBITSJPEG2, define_bits_jpeg2_loader);
        register_tag_loader(SWF::DEFINESHAPE2,  define_shape_loader);
@@ -235,7 +235,7 @@
        register_tag_loader(SWF::DEFINETEXTFORMAT, fixme_loader); // 42
        register_tag_loader(SWF::FRAMELABEL,    frame_label_loader);
        // 44 - _UNKNOWN_ unimplemented
-       register_tag_loader(SWF::SOUNDSTREAMHEAD2, fixme_loader); // 45
+       register_tag_loader(SWF::SOUNDSTREAMHEAD2, sound_stream_head_loader); 
// 45
        register_tag_loader(SWF::DEFINEMORPHSHAPE, define_shape_morph_loader);
        register_tag_loader(SWF::FRAMETAG,      fixme_loader); // 47
        register_tag_loader(SWF::DEFINEFONT2,   define_font_loader);

Index: server/sound.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/sound.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- server/sound.cpp    7 Jun 2006 03:03:21 -0000       1.9
+++ server/sound.cpp    24 Jul 2006 13:30:51 -0000      1.10
@@ -112,7 +112,50 @@
                }
        };
 
+#ifdef HAVE_GST_GST_H
+       // Used to simulate a start_sound_tag when we have a stream
+       struct start_stream_sound_tag : public execute_tag
+       {
+               uint16_t        m_handler_id;
+               int     m_loop_count;
+               bool    m_stop_playback;
 
+               start_stream_sound_tag()
+                       :
+                       m_handler_id(0),
+                       m_loop_count(0),
+                       m_stop_playback(false)
+               {
+               }
+
+
+               void    read(movie_definition* m, const sound_sample_impl* sam)
+               // Initialize this StartSound tag from the stream & given 
sample.
+               // Insert ourself into the movie.
+               {
+                       assert(sam);
+
+                       m_handler_id = sam->m_sound_handler_id;
+                       m->add_execute_tag(this);
+               }
+
+
+               void    execute(movie* m)
+               {
+                       if (s_sound_handler)
+                       {
+                               if (m_stop_playback)
+                               {
+                                       
s_sound_handler->stop_sound(m_handler_id);
+                               }
+                               else
+                               {
+                                       
s_sound_handler->play_sound(m_handler_id, m_loop_count, 0);
+                               }
+                       }
+               }
+       };
+#endif
 
 
        // void define_button_sound(...) ???
@@ -401,7 +444,8 @@
                        sample_count,
                        format,
                        s_sample_rate_table[sample_rate],
-                       stereo);
+                       stereo,
+                       false);
                sound_sample*   sam = new sound_sample_impl(handler_id);
                m->add_sound_sample(character_id, sam);
 
@@ -437,6 +481,102 @@
        
 }
 
+
+
+// Load a SoundStreamHead(2) tag.
+void
+sound_stream_head_loader(stream* in, tag_type tag, movie_definition* m)
+{
+#ifdef HAVE_GST_GST_H
+       assert(tag == 18 || tag == 45);
+
+       // FIXME:
+       // no character id for soundstreams... so we make one up... 
+       // This only works if there is only one stream in the movie...
+       // The right way to do it is to make seperate structures for streams
+       // in movie_def_impl.
+       uint16_t        character_id = 10000;
+       
+       // extract garbage data
+       int     garbage = in->read_uint(8);
+
+       sound_handler::format_type      format = (sound_handler::format_type) 
in->read_uint(4);
+       int     sample_rate = in->read_uint(2); // multiples of 5512.5
+       bool    sample_16bit = in->read_uint(1) ? true : false;
+       bool    stereo = in->read_uint(1) ? true : false;
+       
+       // checks if this is a new streams header or just one in the row
+       if (format == 0 && sample_rate == 0 && sample_16bit == 0 && stereo == 
0) return;
+       
+       int     sample_count = in->read_u32();
+       if (format == 2) garbage = in->read_uint(16);
+
+       static int      s_sample_rate_table[] = { 5512, 11025, 22050, 44100 };
+
+       log_parse("sound stream head: ch=%d, format=%d, rate=%d, 16=%d, 
stereo=%d, ct=%d\n",
+                 character_id, int(format), sample_rate, int(sample_16bit), 
int(stereo), sample_count);
+
+       // If we have a sound_handler, ask it to init this sound.
+       if (s_sound_handler)
+       {
+               int     data_bytes = 0;
+               unsigned char*  data = NULL;
+
+               int     handler_id = s_sound_handler->create_sound(
+                       data,
+                       data_bytes,
+                       sample_count,
+                       format,
+                       s_sample_rate_table[sample_rate],
+                       stereo,
+                       true);
+               sound_sample*   sam = new sound_sample_impl(handler_id);
+               m->add_sound_sample(character_id, sam);
+
+               sound_sample_impl*      sam_impl = (sound_sample_impl*) 
m->get_sound_sample(10000);
+               start_stream_sound_tag* ssst = new start_stream_sound_tag();
+               ssst->read(m, sam_impl);
+
+               delete [] data;
+       }
+#endif
+}
+
+
+// Load a SoundStreamBlock tag.
+void
+sound_stream_block_loader(stream* in, tag_type tag, movie_definition* m)
+{
+#ifdef HAVE_GST_GST_H
+       assert(tag == 19);
+
+       // extract garbage data
+       int     garbage = in->read_uint(32);
+
+       // If we have a sound_handler, store the data with the appropiate sound.
+       if (s_sound_handler)
+       {
+               int     data_bytes = 0;
+               unsigned char*  data = NULL;
+
+               // @@ This is pretty awful -- lots of copying, slow reading.
+               data_bytes = in->get_tag_end_position() - in->get_position();
+               data = new unsigned char[data_bytes];
+               for (int i = 0; i < data_bytes; i++)
+               {
+                       data[i] = in->read_u8();
+               }
+
+               // Swap bytes on behalf of the host, to make it easier for the 
handler.
+               // @@ I'm assuming this is a good idea?  Most sound handlers 
will prefer native endianness?
+               s_sound_handler->fill_stream_data(data, data_bytes);
+
+               delete [] data;
+       }
+#endif
+}
+
+
 } // namespace gnash::SWF::tag_loaders
 } // namespace gnash::SWF
 

Index: server/swf/tag_loaders.h
===================================================================
RCS file: /sources/gnash/gnash/server/swf/tag_loaders.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/swf/tag_loaders.h    20 May 2006 19:31:39 -0000      1.4
+++ server/swf/tag_loaders.h    24 Jul 2006 13:30:51 -0000      1.5
@@ -137,7 +137,10 @@
 
 void   do_init_action_loader(stream*, tag_type, movie_definition*);
 
-// sound_stream_loader();      // head, head2, block
+void   sound_stream_head_loader(stream*, tag_type, movie_definition*);
+
+void   sound_stream_block_loader(stream*, tag_type, movie_definition*);
+
 
 
 } // namespace gnash::SWF::tag_loaders

Index: backend/sound_handler_gst.cpp
===================================================================
RCS file: backend/sound_handler_gst.cpp
diff -N backend/sound_handler_gst.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ backend/sound_handler_gst.cpp       24 Jul 2006 13:30:50 -0000      1.1
@@ -0,0 +1,634 @@
+//   Copyright (C) 2005, 2006 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 2 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 sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
+// which has been donated to the Public Domain.
+
+
+/*  TODO:
+       * dealloker elementer efter brug (sinkXX stiger: 1go_menu.swf) brug 
bus_callback'en? event_probe!
+       * hvordan fikser vi traaden? stopper vi loop, eller pauser vi 
pipelinen? Begge dele! :)
+       * streams
+       * Not really a todo... ATM Gstreamer can't handle multiple elements 
trying to cennect at the same time.
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_GST_GST_H
+#include "gnash.h"
+#include "container.h"
+#include "log.h"
+#include "types.h"     // for IF_VERBOSE_* macros
+#include <pthread.h>
+#include <math.h>
+
+#include <gst/gst.h>
+
+#define BUFFER_SIZE 5000
+
+// Used to hold the gstreamer when doing on-demand-decoding
+typedef struct
+{
+       // gstreamer objects
+       GstElement *input;
+       GstElement *decoder;
+       GstElement *capsfilter;
+       GstElement *audioconvert;
+       GstElement *audioresample;
+       GstElement *volume;
+       GstElement *bin;
+       
+       // position in the stream
+       long position;
+
+       // The (un)compressed data
+       guint8* data;
+
+       // data size
+       long data_size;
+
+       long loop_count;
+       
+} gst_elements;
+
+
+// Used to hold the sounddata when doing on-demand-decoding
+typedef struct
+{
+       // The (un)compressed data
+       guint8* data;
+
+       // data format
+       int format;
+
+       // data size
+       long data_size;
+
+       // stereo or not
+       bool stereo;
+
+       // number of samples
+       int sample_count;
+
+       // sample rate
+       int sample_rate;
+
+       // Volume, SWF range: 0-100, GST range 0-10 (we only use 0-1, the rest 
is amplified)
+       // It's the SWF range that is represented here
+       int volume;
+
+       // gstreamer objects
+       std::vector<gst_elements*>      m_gst_elements;
+
+} sound_data;
+
+// Use gstreamer to handle sounds.
+struct GST_sound_handler : gnash::sound_handler
+{
+       // gstreamer pipeline objects
+
+       // the main bin containing the adder and output (sink)
+       GstElement *pipeline;
+
+       GstElement *adder;
+       GstElement *audiosink;
+
+       // Sound data.
+       std::vector<sound_data*>        m_sound_data;
+
+       // Keeps track of numbers of playing sounds
+       int soundsPlaying;
+       
+       // Is the loop running?
+       bool looping;
+       
+       // latest sound stream we've created - we expect some data to arrive
+       int currentStream;
+       
+       GST_sound_handler()
+       {
+               // init gstreamer
+               gst_init(NULL, NULL);
+
+               // create main pipeline
+               pipeline = gst_pipeline_new (NULL);
+
+               // create adder
+               adder = gst_element_factory_make ("adder", NULL);
+
+               // create an audio sink - use oss, alsa or...? make a 
commandline option?
+               // we first try alsa, then oss, then esd, then...?
+               audiosink = gst_element_factory_make ("alsasink", NULL);
+               if (!audiosink) audiosink = gst_element_factory_make 
("osssink", NULL);
+               if (!audiosink) audiosink = gst_element_factory_make 
("esdsink", NULL);
+
+               // Check if the creation of the gstreamer pipeline, adder and 
audiosink was a succes
+               if (!pipeline || !adder || !audiosink) {
+                       gnash::log_error("One gstreamer element could not be 
created\n");
+               }
+
+               // link adder and output to bin
+               gst_bin_add (GST_BIN (pipeline), adder);
+               gst_bin_add (GST_BIN (pipeline), audiosink);
+
+               // link adder and audiosink
+               gst_element_link (adder, audiosink);
+
+               soundsPlaying = 0;
+               
+               looping = false;
+               
+       }
+
+       ~GST_sound_handler()
+       {
+
+               for (int i = 0; i < m_sound_data.size(); i++) {
+                       stop_sound(i);
+                       delete_sound(i);
+               }
+               m_sound_data.clear();
+
+               gst_object_unref (GST_OBJECT (pipeline));
+
+       }
+
+
+       virtual int     create_sound(
+               void* data,
+               int data_bytes,
+               int sample_count,
+               format_type format,
+               int sample_rate,
+               bool stereo,
+               bool stream)
+       // Called to create a sample.  We'll return a sample ID that
+       // can be use for playing it.
+       {
+               // Add something similar... check gst elements?
+               /*if (m_opened == false)
+               {
+                       return 0;
+               }*/
+
+               int16_t* adjusted_data = 0;
+               int     adjusted_size = 0;
+
+               sound_data *sounddata = new sound_data;
+               if (sounddata == NULL) {
+                       gnash::log_error("could not allocate memory for 
sounddata !\n");
+                       return -1;
+               }
+
+               sounddata->format = format;
+               sounddata->data_size = data_bytes;
+               sounddata->stereo = stereo;
+               sounddata->sample_count = sample_count;
+               sounddata->sample_rate = sample_rate;
+               sounddata->volume = 100;
+
+               switch (format)
+               {
+               // TODO: Do we need to do the raw-data-convert? Can't Gstreamer 
handle it?
+               case FORMAT_RAW:
+/*     caps info:
+      audio/x-raw-int
+                   rate: [ 1, 2147483647 ]
+               channels: [ 1, 8 ]
+             endianness: { 1234, 4321 }
+                  width: 8
+                  depth: [ 1, 8 ]
+                 signed: { true, false }*/
+                       /*convert_raw_data(&adjusted_data, &adjusted_size, 
data, sample_count, 1, sample_rate, stereo);
+                       sounddata->data = (guint8*) malloc(adjusted_size);
+                       memcpy(sounddata->data, adjusted_data, adjusted_size);*/
+
+                       sounddata->data = (guint8*) malloc(data_bytes);
+                       memcpy(sounddata->data, data, data_bytes);
+                       break;
+
+               case FORMAT_NATIVE16:
+/*     caps info:
+      audio/x-raw-int
+                   rate: [ 1, 2147483647 ]
+               channels: [ 1, 8 ]
+             endianness: { 1234, 4321 }
+                  width: 16
+                  depth: [ 1, 16 ]
+                 signed: { true, false }*/
+                       /*convert_raw_data(&adjusted_data, &adjusted_size, 
data, sample_count, 2, sample_rate, stereo);
+                       sounddata->data = (guint8*) malloc(adjusted_size);
+                       memcpy(sounddata->data, adjusted_data, adjusted_size);*/
+                       
+                       sounddata->data = (guint8*) malloc(data_bytes);
+                       memcpy(sounddata->data, data, data_bytes);
+                       break;
+
+               case FORMAT_MP3:
+               //case FORMAT_VORBIS:
+                       sounddata->data = (guint8*) malloc(data_bytes);
+                       memcpy(sounddata->data, data, data_bytes);
+
+                       break;
+               default:
+                       // Unhandled format.
+                       gnash::log_error("unknown format sound requested; this 
demo does not handle it\n");
+                       break;
+               }
+
+               m_sound_data.push_back(sounddata);
+
+               
+               if (stream) currentStream = m_sound_data.size()-1;
+
+               return m_sound_data.size()-1;
+       }
+
+
+       // this gets called when a stream gets more data
+       virtual void    fill_stream_data(void* data, int data_bytes)
+       {
+               
+               if (currentStream >= 0 && currentStream < m_sound_data.size())
+               {
+                       m_sound_data[currentStream]->data = (guint8*) 
realloc(m_sound_data[currentStream]->data, data_bytes + 
m_sound_data[currentStream]->data_size);
+                       memcpy(m_sound_data[currentStream]->data + 
m_sound_data[currentStream]->data_size, data, data_bytes);
+                       m_sound_data[currentStream]->data_size += data_bytes;
+               }
+               // FIXME: if the playback of the stream has already started 
we'll need to update the struct
+
+
+       }
+
+
+
+       // The callback function which refills the buffer with data
+       static void callback_handoff (GstElement *c, GstBuffer *buffer, GstPad  
*pad, gpointer user_data)
+       {
+               gst_elements *gstelements = (gst_elements*) user_data;
+
+               // First callback
+               if (GST_BUFFER_SIZE(buffer) == 0) {
+                       if (gstelements->data_size > BUFFER_SIZE) {
+                               GST_BUFFER_SIZE(buffer) = BUFFER_SIZE;
+                       } else {
+                               GST_BUFFER_SIZE(buffer) = 
gstelements->data_size;
+                       }
+                       GST_BUFFER_DATA(buffer) = (guint8*) 
realloc(GST_BUFFER_DATA(buffer),GST_BUFFER_SIZE(buffer));
+               }
+
+               // This shouldn't happen
+               if (gstelements->position > gstelements->data_size) {
+                       return;
+               }
+
+               // Last callback - the last re-fill
+               if (gstelements->position+BUFFER_SIZE > gstelements->data_size) 
{
+                       // Check if we should loop. If loop_count is 0 we have 
we just
+                       // played the sound for the last (and perhaps first) 
time.
+                       // If loop_count is anything else we continue to loop.
+                       if (gstelements->loop_count == 0) {
+                               GST_BUFFER_SIZE(buffer) = 
gstelements->data_size-gstelements->position;
+                               memcpy(GST_BUFFER_DATA(buffer), (guint8*) 
gstelements->data+gstelements->position, 
gstelements->data_size-gstelements->position);
+                               gstelements->position += BUFFER_SIZE;
+
+                               gst_element_set_state (GST_ELEMENT 
(gstelements->input), GST_STATE_PAUSED);
+
+                       } else {
+                               // Copy what's left of the data, and then fill 
the rest with "new" data.
+                               //int chunck_size = 
(gstelements->data_size-gstelements->position);
+                               memcpy(GST_BUFFER_DATA(buffer), (guint8*) 
gstelements->data+gstelements->position,  
(gstelements->data_size-gstelements->position));
+                               memcpy(GST_BUFFER_DATA(buffer)+ 
(gstelements->data_size-gstelements->position), (guint8*) gstelements->data, 
GST_BUFFER_SIZE(buffer)- (gstelements->data_size-gstelements->position));
+                               gstelements->position = 
GST_BUFFER_SIZE(buffer)- (gstelements->data_size-gstelements->position);
+                               gstelements->loop_count--;
+
+                       }
+
+                       return;
+
+               }
+
+               // Standard re-fill
+               memcpy(GST_BUFFER_DATA(buffer), 
(guint8*)gstelements->data+gstelements->position, BUFFER_SIZE);
+               gstelements->position += BUFFER_SIZE;
+
+       }
+
+
+       /*static void event_callback (GstPad*, GstMiniObject *o, gpointer 
user_data)
+       {
+
+               GstEvent *event = (GstEvent*) o;
+               if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
+                       // Find the instance of this sound which needs to be 
deleted
+                       sound_data *sounddata = (sound_data*) user_data;
+                       for (int i = 0; i < m_gst_elements.size(); i++) {
+                               if (m_gst_elements.at(i)->position > 
m_gst_elements.at(i)->data_size)
+                       }
+                       printf("EOS detected! :D\n");
+                       gst_object_unref (GST_OBJECT (
+               }
+
+       }*/
+
+
+       virtual void    play_sound(int sound_handle, int loop_count, int offset)
+       // Play the index'd sample.
+       {
+
+               // Check if the sound exists.
+               if (sound_handle < 0 || sound_handle >= m_sound_data.size())
+               {
+                       // Invalid handle.
+                       return;
+               }
+               
+
+               // Make a "gst_elements" for this sound which is latter placed 
on the vector of instances of this sound being played
+               gst_elements* gst_element = new gst_elements;
+               if (gst_element == NULL) {
+                       gnash::log_error ("could not allocate memory for 
gst_element !\n");
+                       return;
+               }
+               // Copy data-info to the "gst_elements"
+               gst_element->data_size = m_sound_data[sound_handle]->data_size;
+               gst_element->data = m_sound_data[sound_handle]->data;
+               gst_element->position = 0;
+
+               // Set number of loop we should do. -1 is infinte loop, 0 plays 
it once, 1 twice etc.
+               gst_element->loop_count = loop_count;
+
+               gst_element->bin = gst_bin_new(NULL);
+               gst_element->input = gst_element_factory_make ("fakesrc", NULL);
+               gst_element->capsfilter = gst_element_factory_make 
("capsfilter", NULL);
+               gst_element->audioconvert = gst_element_factory_make 
("audioconvert", NULL);
+               gst_element->audioresample = gst_element_factory_make 
("audioresample", NULL);
+               gst_element->volume = gst_element_factory_make ("volume", NULL);
+
+               // Put the gstreamer elements in the pipeline
+               gst_bin_add_many (GST_BIN (gst_element->bin), 
gst_element->input,
+                                               gst_element->capsfilter,
+                                               gst_element->audioconvert,
+                                               gst_element->audioresample, 
+                                               gst_element->volume, NULL);
+
+               // Test if the fakesrc, typefind and audio* elements was 
correctly created
+               if (!gst_element->input
+                       || !gst_element->capsfilter
+                       || !gst_element->audioconvert
+                       || !gst_element->audioresample) {
+
+                       gnash::log_error("One gstreamer element could not be 
created\n");
+                       return;
+               }
+
+               // Create a gstreamer decoder for the chosen sound.
+
+               if (m_sound_data[sound_handle]->format == FORMAT_MP3) { // || 
sound_data[m_sound_handle]->format == FORMAT_VORBIS) {
+                       gst_element->decoder = gst_element_factory_make ("mad", 
NULL);
+                       if (!gst_element->decoder) gst_element_factory_make 
("ffdec_mp3", NULL);
+                       //if (!gst_element->decoder) gst_element_factory_make 
("ffdec_mp3", NULL); what is the fluendo decoder called?
+
+                       // Check if the element was correctly created
+                       if (!gst_element->decoder) {
+                               gnash::log_error("A gstreamer mp3-decoder 
element could not be created\n");
+                               return;
+                       }
+                       gst_bin_add (GST_BIN (gst_element->bin), 
gst_element->decoder);
+
+                       // Set the info about the stream so that gstreamer 
knows what it is.
+                       GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
+                               "mpegversion", G_TYPE_INT, 1,
+                               "layer", G_TYPE_INT, 3,
+                               "rate", G_TYPE_INT, 
m_sound_data[sound_handle]->sample_rate,
+                               "channels", G_TYPE_INT, 
m_sound_data[sound_handle]->stereo ? 2 : 1, NULL);
+                       g_object_set (G_OBJECT (gst_element->capsfilter), 
"caps", caps, NULL);
+                       gst_caps_unref (caps);
+
+                       // number of buffers to send
+                       int numBuf = 
(int)ceil((float)m_sound_data[sound_handle]->data_size / (float)BUFFER_SIZE);
+                       if (loop_count == -1) {
+                               numBuf = -1;
+                       } else if (loop_count > 0) {
+                               numBuf = numBuf * (loop_count+1) -1;
+                       }
+
+                       // setup fake source
+                       g_object_set (G_OBJECT (gst_element->input),
+                                               "sizetype", 2, 
"can-activate-pull", FALSE, "signal-handoffs", TRUE,
+                                               "sizemax", BUFFER_SIZE, 
"num-buffers", numBuf, NULL);
+                       // Setup the callback
+                       g_signal_connect (gst_element->input, "handoff", 
G_CALLBACK (callback_handoff), gst_element);
+
+                       // link data, decoder, audio* and adder
+                       gst_element_link_many (gst_element->input,
+                                                       gst_element->capsfilter,
+                                                       gst_element->decoder,
+                                                       
gst_element->audioconvert,
+                                                       
gst_element->audioresample, 
+                                                       gst_element->volume, 
NULL);
+
+               } else if (m_sound_data[sound_handle]->format == 
FORMAT_NATIVE16) {
+
+                       // Set the info about the stream so that gstreamer 
knows what it is.
+                       GstCaps *caps = gst_caps_new_simple ("audio/x-raw-int",
+                               "rate", G_TYPE_INT, 
m_sound_data[sound_handle]->sample_rate,
+                               "channels", G_TYPE_INT, 
m_sound_data[sound_handle]->stereo ? 2 : 1,
+                               "endianness", G_TYPE_INT, G_BIG_ENDIAN,
+                               "width", G_TYPE_INT, 16,
+                               /*"signed", G_TYPE_INT, 1,*/ NULL);
+                       g_object_set (G_OBJECT (gst_element->capsfilter), 
"caps", caps, NULL);
+                       gst_caps_unref (caps);
+
+                       // number of buffers to send
+                       int numBuf = 
(int)ceil((float)m_sound_data[sound_handle]->data_size / (float)BUFFER_SIZE);
+                       if (loop_count == -1) {
+                               numBuf = -1;
+                       } else if (loop_count > 0) {
+                               numBuf = numBuf * (loop_count+1) -1;
+                       }
+                       // setup fake source
+                       g_object_set (G_OBJECT (gst_element->input),
+                                               "sizetype", 2, 
"can-activate-pull", FALSE, "signal-handoffs", TRUE,
+                                               "sizemax", BUFFER_SIZE, 
"num-buffers", numBuf, NULL);
+                       // Setup the callback
+                       g_signal_connect (gst_element->input, "handoff", 
G_CALLBACK (callback_handoff), gst_element);
+
+/*     caps info:
+      audio/x-raw-int
+                   rate: [ 1, 2147483647 ]
+               channels: [ 1, 8 ]
+             endianness: { 1234, 4321 }
+                  width: 16
+                  depth: [ 1, 16 ]
+                 signed: { true, false }*/
+                       // Raw native sound-data, output directly
+                       gst_element_link_many (gst_element->input, 
+                                               gst_element->capsfilter, 
+                                               gst_element->audioconvert,
+                                               gst_element->audioresample,
+                                               gst_element->volume, NULL);
+               }
+               // Add ghostpad
+               GstPad *pad = gst_element_get_pad (gst_element->volume, "src");
+               gst_element_add_pad (gst_element->bin, gst_ghost_pad_new 
("src", pad));
+               gst_object_unref (GST_OBJECT (pad));
+               
+               // Add the bin to the main pipeline
+               gst_bin_add(GST_BIN (pipeline), gst_element->bin);
+               gst_element_link(gst_element->bin,adder);
+               
+               // Set the volume
+               g_object_set (G_OBJECT (gst_element->volume), "volume", 
(double)m_sound_data[sound_handle]->volume / 100.0, NULL);
+
+               //gst_pad_add_event_probe(pad, G_CALLBACK(event_callback), 
m_sound_data[sound_handle]);
+
+               // Put the gst_element on the vector
+               
m_sound_data[sound_handle]->m_gst_elements.push_back(gst_element);
+
+               // If not already playing, start doing it
+               gst_element_set_state (GST_ELEMENT (pipeline), 
GST_STATE_PLAYING);
+
+               ++soundsPlaying;
+       }
+
+
+       virtual void    stop_sound(int sound_handle)
+       {
+               
+               // Check if the sound exists.
+               if (sound_handle < 0 || sound_handle >= m_sound_data.size())
+               {
+                       // Invalid handle.
+                       return;
+               }
+
+               // This variable is used to asure that we don't try to pause
+               // if nothing is playing, which would mess things up
+               bool stopped = false;
+
+               // Stop all the instances of this sound.
+               for (int i = 
m_sound_data[sound_handle]->m_gst_elements.size()-1; i >= 0 ; i--) {
+                       // Check if we can succesfully stop the elements 
playback - if not we skip cleaning this for now
+                       // FIXME: what if it ain't possible to stop an element 
when this is called from ~GST_sound_handler
+
+                       // Unlink the elements
+                       gst_element_unlink_many 
(m_sound_data[sound_handle]->m_gst_elements[i]->bin, adder, NULL);
+
+                       // FIXME: This stops ALL sounds, not just the current.
+                       if (gst_element_set_state (GST_ELEMENT 
(m_sound_data[sound_handle]->m_gst_elements[i]->bin), GST_STATE_NULL) != 1) 
continue;
+
+
+                       // Unref/delete the elements
+                       gst_object_unref (GST_OBJECT 
(m_sound_data[sound_handle]->m_gst_elements[i]->bin));
+
+
+                       // Delete the gst_element struct
+                       
m_sound_data[sound_handle]->m_gst_elements.erase(m_sound_data[sound_handle]->m_gst_elements.begin()
 + i);
+                       --soundsPlaying;
+                       stopped = true;
+               }
+               
+                       
+               // If no sounds, set pipeline to paused. Else the pipeline 
thinks it's still playing,
+               // and will fastforward through new sounds until it reach the 
"correct posistion".
+               if (soundsPlaying == 0 && stopped) {
+                       gst_element_set_state (GST_ELEMENT (pipeline), 
GST_STATE_PAUSED);
+               }
+               
+       }
+
+
+       virtual void    delete_sound(int sound_handle)
+       // this gets called when it's done with a sample.
+       {
+               
+               if (sound_handle >= 0 && sound_handle < m_sound_data.size())
+               {
+                       free (m_sound_data[sound_handle]->data);
+                       m_sound_data[sound_handle]->data = 0;
+               }
+
+       }
+
+       // This will stop all sounds playing. Will cause problems if the 
soundhandler is made static
+       // and supplys sound_handling for many SWF's, since it will stop all 
sounds with no regard
+       // for what sounds is associated with what SWF.
+       virtual void    stop_all_sounds()
+       {
+               for (int i = 0; i < m_sound_data.size(); i++)
+                       stop_sound(i);
+
+
+       }
+
+
+       //      returns the sound volume level as an integer from 0 to 100,
+       //      where 0 is off and 100 is full volume. The default setting is 
100.
+       virtual int     get_volume(int sound_handle) {
+       
+               // Check if the sound exists.
+               if (sound_handle >= 0 && sound_handle < m_sound_data.size())
+               {
+                       return m_sound_data[sound_handle]->volume;
+               } else {
+                       return 0; // Invalid handle
+               }
+       }
+       
+
+       //      A number from 0 to 100 representing a volume level. 
+       //      100 is full volume and 0 is no volume. The default setting is 
100.
+       virtual void    set_volume(int sound_handle, int volume) {
+
+               // Check if the sound exists.
+               if (sound_handle < 0 || sound_handle >= m_sound_data.size())
+               {
+                       // Invalid handle.
+                       return;
+               }
+
+               // Set volume for this sound. Should this only apply to the 
active sounds?
+               m_sound_data[sound_handle]->volume = volume;
+               
+               for (int i = 0; i < 
m_sound_data[sound_handle]->m_gst_elements.size(); i++) {
+                       g_object_set (G_OBJECT 
(m_sound_data[sound_handle]->m_gst_elements[i]->volume),
+                                               "volume", volume/100, NULL);
+               }
+
+       }
+
+
+};
+
+
+gnash::sound_handler*  gnash::create_sound_handler_gst()
+// Factory.
+{
+       return new GST_sound_handler;
+}
+
+
+#endif
+
+// Local Variables:
+// mode: C++
+// End:
+




reply via email to

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