[Top][All Lists]
[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:
+
- [Gnash-commit] gnash ChangeLog backend/Makefile.am backend/gna...,
Tomas Groth <=