[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp l...
From: |
Tomas Groth |
Subject: |
[Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp l... |
Date: |
Wed, 14 Feb 2007 20:41:48 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Tomas Groth <tgc> 07/02/14 20:41:48
Modified files:
. : ChangeLog
backend : sound_handler_sdl.cpp
libbase : gstgnashsrc.h
server : gnash.h
server/asobj : Makefile.am NetConnection.cpp NetConnection.h
NetStreamFfmpeg.cpp NetStreamFfmpeg.h
NetStreamGst.cpp Sound.cpp Sound.h
Added files:
server/asobj : SoundFfmpeg.cpp SoundFfmpeg.h SoundGst.cpp
SoundGst.h SoundMad.cpp SoundMad.h
Log message:
* backend/sound_handler_sdl.cpp, server/asobj/NetStreamFfmpeg.{h,cpp},
server/gnash.h: Changed the aux_streamer_ptr callback to return bool.
* libbase/gstgnashsrc.h, server/asobj/NetStreamGst.cpp: Moved definition
of gnash_plugin_desc to registering file to avoid multiple
definitions.
* server/asobj/SoundGst.{cpp,h}, server/asobj/SoundFfmpeg.{cpp,h},
server/asobj/SoundMad.{cpp,h} Added FFMPEG, Gstreamer and libmad
backends for the Sound class.
* server/asobj/Sound.{cpp,h}: Added support for the new backends.
* server/asobj/Makefile.am: Added SoundGst.{h,cpp}, SoundFfmpeg.{h,cpp},
and SoundMad.{h,cpp},
* server/asobj/NetConnection.{cpp,h}: Made accept as_object as argument
instead of NetStream, to allow Sound to use NetConnection.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2360&r2=1.2361
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/sound_handler_sdl.cpp?cvsroot=gnash&r1=1.45&r2=1.46
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/gstgnashsrc.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/gnash.h?cvsroot=gnash&r1=1.83&r2=1.84
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Makefile.am?cvsroot=gnash&r1=1.31&r2=1.32
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.cpp?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetConnection.h?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.h?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.cpp?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Sound.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Sound.h?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/SoundFfmpeg.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/SoundFfmpeg.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/SoundGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/SoundGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/SoundMad.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/SoundMad.h?cvsroot=gnash&rev=1.1
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2360
retrieving revision 1.2361
diff -u -b -r1.2360 -r1.2361
--- ChangeLog 14 Feb 2007 13:50:30 -0000 1.2360
+++ ChangeLog 14 Feb 2007 20:41:47 -0000 1.2361
@@ -1,3 +1,18 @@
+2007-02-14 Tomas Groth Christensen <address@hidden>
+
+ * backend/sound_handler_sdl.cpp, server/asobj/NetStreamFfmpeg.{h,cpp},
+ server/gnash.h: Changed the aux_streamer_ptr callback to return bool.
+ * libbase/gstgnashsrc.h, server/asobj/NetStreamGst.cpp: Moved definition
+ of gnash_plugin_desc to registering file to avoid multiple
definitions.
+ * server/asobj/SoundGst.{cpp,h}, server/asobj/SoundFfmpeg.{cpp,h},
+ server/asobj/SoundMad.{cpp,h} Added FFMPEG, Gstreamer and libmad
+ backends for the Sound class.
+ * server/asobj/Sound.{cpp,h}: Added support for the new backends.
+ * server/asobj/Makefile.am: Added SoundGst.{h,cpp}, SoundFfmpeg.{h,cpp},
+ and SoundMad.{h,cpp},
+ * server/asobj/NetConnection.{cpp,h}: Made accept as_object as argument
+ instead of NetStream, to allow Sound to use NetConnection.
+
2007-02-14 Sandro Santilli <address@hidden>
* server/shape.h: add more public functions for
Index: backend/sound_handler_sdl.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/sound_handler_sdl.cpp,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -b -r1.45 -r1.46
--- backend/sound_handler_sdl.cpp 2 Feb 2007 15:01:17 -0000 1.45
+++ backend/sound_handler_sdl.cpp 14 Feb 2007 20:41:48 -0000 1.46
@@ -18,7 +18,7 @@
// Based on sound_handler_sdl.cpp by Thatcher Ulrich http://tulrich.com 2003
// which has been donated to the Public Domain.
-// $Id: sound_handler_sdl.cpp,v 1.45 2007/02/02 15:01:17 bjacques Exp $
+// $Id: sound_handler_sdl.cpp,v 1.46 2007/02/14 20:41:48 tgc Exp $
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -759,8 +759,8 @@
SDL_sound_handler::aux_streamer_ptr aux_streamer =
it->second; //handler->m_aux_streamer[i]->ptr;
void* owner = it->first;
- (aux_streamer)(owner, buf, buffer_length);
-
+ bool ret = (aux_streamer)(owner, buf, buffer_length);
+ if (!ret) handler->m_aux_streamer.erase(it);
SDL_MixAudio(stream, buf, buffer_length,
SDL_MIX_MAXVOLUME);
}
Index: libbase/gstgnashsrc.h
===================================================================
RCS file: /sources/gnash/gnash/libbase/gstgnashsrc.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libbase/gstgnashsrc.h 18 Jan 2007 11:53:37 -0000 1.4
+++ libbase/gstgnashsrc.h 14 Feb 2007 20:41:48 -0000 1.5
@@ -17,7 +17,7 @@
// Based on the filesrc and fdsrc element in Gstreamer-core
//
-/* $Id: gstgnashsrc.h,v 1.4 2007/01/18 11:53:37 tgc Exp $ */
+/* $Id: gstgnashsrc.h,v 1.5 2007/02/14 20:41:48 tgc Exp $ */
#ifndef __GST_GNASH_SRC_H__
#define __GST_GNASH_SRC_H__
@@ -77,24 +77,4 @@
G_END_DECLS
-static gboolean
-register_elements (GstPlugin *plugin)
-{
- return gst_element_register (plugin, "gnashsrc", GST_RANK_NONE,
GST_TYPE_GNASH_SRC);
-}
-
-GstPluginDesc gnash_plugin_desc = {
- 0, // GST_VERSION_MAJOR
- 10, // GST_VERSION_MINOR
- "gnashsrc",
- "Use gnash as source via callbacks",
- register_elements,
- "0.0.1",
- "LGPL",
- "gnash",
- "gnash",
- "http://www.gnu.org/software/gnash/",
- GST_PADDING_INIT
-};
-
#endif /* __GST_GNASH_SRC_H__ */
Index: server/gnash.h
===================================================================
RCS file: /sources/gnash/gnash/server/gnash.h,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -b -r1.83 -r1.84
--- server/gnash.h 18 Jan 2007 22:53:21 -0000 1.83
+++ server/gnash.h 14 Feb 2007 20:41:48 -0000 1.84
@@ -17,7 +17,7 @@
//
//
-/* $Id: gnash.h,v 1.83 2007/01/18 22:53:21 strk Exp $ */
+/* $Id: gnash.h,v 1.84 2007/02/14 20:41:48 tgc Exp $ */
/// \mainpage
///
@@ -411,7 +411,7 @@
{
public:
- typedef void (*aux_streamer_ptr)(void *udata, uint8 *stream, int len);
+ typedef bool (*aux_streamer_ptr)(void *udata, uint8 *stream, int len);
struct sound_envelope
{
Index: server/asobj/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Makefile.am,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -b -r1.31 -r1.32
--- server/asobj/Makefile.am 14 Feb 2007 09:41:38 -0000 1.31
+++ server/asobj/Makefile.am 14 Feb 2007 20:41:48 -0000 1.32
@@ -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: Makefile.am,v 1.31 2007/02/14 09:41:38 tgc Exp $
+# $Id: Makefile.am,v 1.32 2007/02/14 20:41:48 tgc Exp $
AUTOMAKE_OPTIONS =
@@ -42,7 +42,6 @@
libgnashasobjs_la_SOURCES = \
- Sound.cpp \
Boolean.cpp \
Camera.cpp \
Color.cpp \
@@ -63,6 +62,7 @@
Object.cpp \
Selection.cpp \
SharedObject.cpp\
+ Sound.cpp \
Stage.cpp \
System.cpp \
TextSnapshot.cpp\
@@ -76,7 +76,6 @@
$(NULL)
noinst_HEADERS = \
- Sound.h \
Boolean.h \
Camera.h \
Color.h \
@@ -100,6 +99,10 @@
Object.h \
Selection.h \
SharedObject.h \
+ Sound.h \
+ SoundFfmpeg.h \
+ SoundGst.h \
+ SoundMad.h \
Stage.h \
System.h \
TextSnapshot.h \
@@ -116,17 +119,23 @@
$(top_builddir)/libbase/libgnashbase.la
if USE_FFMPEG_ENGINE
-libgnashasobjs_la_SOURCES += NetStreamFfmpeg.cpp
+libgnashasobjs_la_SOURCES += NetStreamFfmpeg.cpp SoundFfmpeg.cpp
AM_CPPFLAGS += $(FFMPEG_CFLAGS)
libgnashasobjs_la_LIBADD += $(FFMPEG_LIBS)
endif
if USE_SOUND_GST
-libgnashasobjs_la_SOURCES += NetStreamGst.cpp
+libgnashasobjs_la_SOURCES += NetStreamGst.cpp SoundGst.cpp
AM_CPPFLAGS += $(GSTREAMER_CFLAGS)
libgnashasobjs_la_LIBADD += $(GSTREAMER_LIBS)
endif
+if USE_MAD_ENGINE
+libgnashasobjs_la_SOURCES += SoundMad.cpp
+AM_CPPFLAGS += $(MAD_CFLAGS)
+libgnashasobjs_la_LIBADD += $(MAD_LIBS)
+endif
+
libgnashasobjs_la_LDFLAGS = -avoid-version
# Rebuild with GCC 4.x Mudflap support
Index: server/asobj/NetConnection.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.cpp,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/asobj/NetConnection.cpp 5 Feb 2007 22:22:32 -0000 1.21
+++ server/asobj/NetConnection.cpp 14 Feb 2007 20:41:48 -0000 1.22
@@ -14,7 +14,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: NetConnection.cpp,v 1.21 2007/02/05 22:22:32 tgc Exp $ */
+/* $Id: NetConnection.cpp,v 1.22 2007/02/14 20:41:48 tgc Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -188,7 +188,7 @@
/// RTMP. Newer Flash movies have a parameter to connect which is a
/// URL string like rtmp://foobar.com/videos/bar.flv
/*public*/
-bool NetConnection::openConnection(const char* char_url, NetStream* ns)
+bool NetConnection::openConnection(const char* char_url, as_object* ns)
{
// if already running there is no need to setup things again
Index: server/asobj/NetConnection.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetConnection.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- server/asobj/NetConnection.h 30 Jan 2007 12:49:03 -0000 1.15
+++ server/asobj/NetConnection.h 14 Feb 2007 20:41:48 -0000 1.16
@@ -14,7 +14,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: NetConnection.h,v 1.15 2007/01/30 12:49:03 strk Exp $ */
+/* $Id: NetConnection.h,v 1.16 2007/02/14 20:41:48 tgc Exp $ */
#ifndef __NETCONNECTION_H__
#define __NETCONNECTION_H__
@@ -53,7 +53,7 @@
~NetConnection();
/// Opens the connection to char_url
- bool openConnection(const char* char_url, NetStream* ns);
+ bool openConnection(const char* char_url, as_object* ns);
/// Put read pointer at given position
bool seek(size_t pos);
@@ -113,7 +113,7 @@
// The NetStream object which handles the video playback
// Watch out for circular dependencies, see NetStream.h
- NetStream* netStreamObj;
+ as_object* netStreamObj;
// Total filesize
double totalSize;
Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- server/asobj/NetStreamFfmpeg.cpp 8 Feb 2007 14:40:20 -0000 1.15
+++ server/asobj/NetStreamFfmpeg.cpp 14 Feb 2007 20:41:48 -0000 1.16
@@ -14,7 +14,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: NetStreamFfmpeg.cpp,v 1.15 2007/02/08 14:40:20 tgc Exp $ */
+/* $Id: NetStreamFfmpeg.cpp,v 1.16 2007/02/14 20:41:48 tgc Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -478,7 +478,7 @@
}
// audio callback is running in sound handler thread
-void NetStreamFfmpeg::audio_streamer(void *owner, uint8 *stream, int len)
+bool NetStreamFfmpeg::audio_streamer(void *owner, uint8 *stream, int len)
{
NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(owner);
@@ -501,6 +501,7 @@
delete samples;
}
}
+ return true;
}
bool NetStreamFfmpeg::read_frame()
Index: server/asobj/NetStreamFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- server/asobj/NetStreamFfmpeg.h 8 Feb 2007 13:25:41 -0000 1.11
+++ server/asobj/NetStreamFfmpeg.h 14 Feb 2007 20:41:48 -0000 1.12
@@ -14,7 +14,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: NetStreamFfmpeg.h,v 1.11 2007/02/08 13:25:41 tgc Exp $ */
+/* $Id: NetStreamFfmpeg.h,v 1.12 2007/02/14 20:41:48 tgc Exp $ */
#ifndef __NETSTREAMFFMPEG_H__
#define __NETSTREAMFFMPEG_H__
@@ -163,7 +163,7 @@
static void startPlayback(NetStreamFfmpeg* ns);
static void av_streamer(NetStreamFfmpeg* ns);
- static void audio_streamer(void *udata, uint8 *stream, int len);
+ static bool audio_streamer(void *udata, uint8 *stream, int len);
private:
Index: server/asobj/NetStreamGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- server/asobj/NetStreamGst.cpp 8 Feb 2007 14:40:20 -0000 1.11
+++ server/asobj/NetStreamGst.cpp 14 Feb 2007 20:41:48 -0000 1.12
@@ -37,6 +37,25 @@
namespace gnash {
+static gboolean
+register_elements (GstPlugin *plugin)
+{
+ return gst_element_register (plugin, "gnashsrc", GST_RANK_NONE,
GST_TYPE_GNASH_SRC);
+}
+
+static GstPluginDesc gnash_plugin_desc = {
+ 0, // GST_VERSION_MAJOR
+ 10, // GST_VERSION_MINOR
+ "gnashsrc",
+ "Use gnash as source via callbacks",
+ register_elements,
+ "0.0.1",
+ "LGPL",
+ "gnash",
+ "gnash",
+ "http://www.gnu.org/software/gnash/",
+ GST_PADDING_INIT
+};
NetStreamGst::NetStreamGst():
Index: server/asobj/Sound.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Sound.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/asobj/Sound.cpp 14 Feb 2007 09:41:38 -0000 1.1
+++ server/asobj/Sound.cpp 14 Feb 2007 20:41:48 -0000 1.2
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2007 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
@@ -29,6 +29,14 @@
#include "GnashException.h"
#include "builtin_function.h"
+#ifdef SOUND_GST
+#include "SoundGst.h"
+#elif defined(USE_FFMPEG)
+#include "SoundFfmpeg.h"
+#elif defined(USE_MAD)
+#include "SoundMad.h"
+#endif
+
#include <string>
namespace gnash {
@@ -50,12 +58,15 @@
Sound::Sound() :
as_object(getSoundInterface()),
- soundName(""),
- soundId(-1)
+ connection(NULL),
+ soundId(-1),
+ externalSound(false),
+ isStreaming(false)
{
}
Sound::~Sound() {
+ if (connection) delete connection;
}
@@ -103,11 +114,18 @@
}
void
-Sound::loadSound(std::string /*file*/, bool /*streaming*/)
+Sound::loadSound(std::string file, bool /*streaming*/)
{
log_msg("%s is still testing!! \n", __FUNCTION__);
+ if (connection) {
+ log_warning("This sound already has a connection?? (We try to
handle this by deleting the old one...)\n");
+ delete connection;
+ }
+ externalURL = file;
+ connection = new NetConnection();
+ connection->openConnection(externalURL.c_str(), this);
}
void
@@ -159,11 +177,35 @@
}
}
+unsigned int
+Sound::getDuration()
+{
+ log_error("%s: only works when ffmpeg, gstreamer or libmad is
enabled\n", __FUNCTION__);
+ return 0;
+}
+
+unsigned int
+Sound::getPosition()
+{
+ log_error("%s: only works when ffmpeg, gstreamer or libmad is
enabled\n", __FUNCTION__);
+ return 0;
+}
+
+
void
sound_new(const fn_call& fn)
{
- Sound *sound_obj = new Sound;
+ Sound* sound_obj;
+#ifdef SOUND_GST
+ sound_obj = new SoundGst();
+#elif defined(USE_FFMPEG)
+ sound_obj = new SoundFfmpeg();
+#elif defined(USE_MAD)
+ sound_obj = new SoundMad();
+#else
+ sound_obj = new Sound();
+#endif
fn.result->set_as_object(sound_obj);
}
@@ -325,9 +367,16 @@
}
void
-sound_loadsound(const fn_call& /*fn*/)
+sound_loadsound(const fn_call& fn)
{
- log_msg("%s:unimplemented \n", __FUNCTION__);
+ if (fn.nargs != 2) {
+ log_error("loadSound needs 2 arguments!\n");
+ return;
+ }
+
+ Sound* so = ensure_sound(fn.this_ptr);
+ so->loadSound(fn.arg(0).to_std_string(), fn.arg(1).to_bool());
+
}
void
@@ -358,9 +407,16 @@
}
void
-sound_duration(const fn_call& /*fn*/)
+sound_duration(const fn_call& fn)
{
- log_msg("%s:unimplemented \n", __FUNCTION__);
+ Sound* so = ensure_sound(fn.this_ptr);
+ if ( fn.nargs == 0 ) {
+ fn.result->set_int(so->getDuration());
+ } else {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror("Tried to set read-only property
Sound.duration");
+ );
+ }
}
void
@@ -370,9 +426,16 @@
}
void
-sound_position(const fn_call& /*fn*/)
+sound_position(const fn_call& fn)
{
- log_msg("%s:unimplemented \n", __FUNCTION__);
+ Sound* so = ensure_sound(fn.this_ptr);
+ if ( fn.nargs == 0 ) {
+ fn.result->set_int(so->getPosition());
+ } else {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror("Tried to set read-only property
Sound.position");
+ );
+ }
}
void
Index: server/asobj/Sound.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Sound.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/asobj/Sound.h 14 Feb 2007 09:41:38 -0000 1.1
+++ server/asobj/Sound.h 14 Feb 2007 20:41:48 -0000 1.2
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2007 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
@@ -16,8 +16,8 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-#ifndef __ASSOUND_H__
-#define __ASSOUND_H__
+#ifndef __SOUND_H__
+#define __SOUND_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -36,21 +36,24 @@
public:
Sound();
~Sound();
- void attachSound(int si, const char* name);
- void getBytesLoaded();
- void getBytesTotal();
- void getPan();
- void getTransform();
- int getVolume();
- void loadSound(std::string file, bool streaming);
- void setPan();
- void setTransform();
- void setVolume(int volume);
- void start(int offset, int loops);
- void stop(int si);
+ virtual void attachSound(int si, const char* name);
+ virtual void getBytesLoaded();
+ virtual void getBytesTotal();
+ virtual void getPan();
+ virtual void getTransform();
+ virtual int getVolume();
+ virtual void loadSound(std::string file, bool streaming);
+ virtual void setPan();
+ virtual void setTransform();
+ virtual void setVolume(int volume);
+ virtual void start(int offset, int loops);
+ virtual void stop(int si);
+ virtual unsigned int getDuration();
+ virtual unsigned int getPosition();
std::string soundName;
-private:
+
+protected:
bool _duration;
bool _id3;
bool _onID3;
@@ -61,12 +64,14 @@
int soundId;
bool externalSound;
+ std::string externalURL;
+ bool isStreaming;
};
void sound_class_init(as_object& global);
} // end of gnash namespace
-// __ASSOUND_H__
+// __SOUND_H__
#endif
Index: server/asobj/SoundFfmpeg.cpp
===================================================================
RCS file: server/asobj/SoundFfmpeg.cpp
diff -N server/asobj/SoundFfmpeg.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/SoundFfmpeg.cpp 14 Feb 2007 20:41:48 -0000 1.1
@@ -0,0 +1,457 @@
+//
+// Copyright (C) 2005, 2006, 2007 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
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "SoundFfmpeg.h"
+#include "sound.h" // for sound_sample_impl
+#include "movie_definition.h"
+#include "sprite_instance.h"
+#include "fn_call.h"
+#include "GnashException.h"
+#include "builtin_function.h"
+
+#include <string>
+
+namespace gnash {
+
+// ffmpeg callback function
+int
+SoundFfmpeg::readPacket(void* opaque, uint8_t* buf, int buf_size)
+{
+
+ SoundFfmpeg* so = static_cast<SoundFfmpeg*>(opaque);
+ NetConnection* nc = so->connection;
+
+ size_t ret = nc->read(static_cast<void*>(buf), buf_size);
+ so->inputPos += ret;
+ return ret;
+
+}
+
+// ffmpeg callback function
+offset_t
+SoundFfmpeg::seekMedia(void *opaque, offset_t offset, int whence){
+
+ SoundFfmpeg* so = static_cast<SoundFfmpeg*>(opaque);
+ NetConnection* nc = so->connection;
+
+
+ // Offset is absolute new position in the file
+ if (whence == SEEK_SET) {
+ nc->seek(offset);
+ so->inputPos = offset;
+
+ // New position is offset + old position
+ } else if (whence == SEEK_CUR) {
+ nc->seek(so->inputPos + offset);
+ so->inputPos = so->inputPos + offset;
+
+ // // New position is offset + end of file
+ } else if (whence == SEEK_END) {
+ // This is (most likely) a streamed file, so we can't seek to
the end!
+ // Instead we seek to 50.000 bytes... seems to work fine...
+ nc->seek(50000);
+ so->inputPos = 50000;
+
+ }
+
+ return so->inputPos;
+}
+
+
+void
+SoundFfmpeg::setupDecoder(SoundFfmpeg* so)
+{
+
+ NetConnection* nc = so->connection;
+ assert(nc);
+
+ // Pass stuff from/to the NetConnection object.
+ assert(so);
+ if ( !nc->openConnection(so->externalURL.c_str(), so) ) {
+ log_warning("Gnash could not open audio url: %s",
so->externalURL.c_str());
+ delete so->lock;
+ return;
+ }
+
+ so->inputPos = 0;
+
+ // This registers all available file formats and codecs
+ // with the library so they will be used automatically when
+ // a file with the corresponding format/codec is opened
+
+ av_register_all();
+
+ // Open video file
+
+ // Probe the file to detect the format
+ AVProbeData probe_data, *pd = &probe_data;
+ pd->filename = "";
+ pd->buf = new uint8_t[2048];
+ pd->buf_size = 2048;
+
+ if (readPacket(so, pd->buf, pd->buf_size) < 1){
+ log_warning("Gnash could not read from audio url: %s",
so->externalURL.c_str());
+ delete[] pd->buf;
+ delete so->lock;
+ return;
+ }
+
+ AVInputFormat* inputFmt = av_probe_input_format(pd, 1);
+
+ // After the format probe, reset to the beginning of the file.
+ nc->seek(0);
+
+ // Setup the filereader/seeker mechanism. 7th argument (NULL) is the
writer function,
+ // which isn't needed.
+ init_put_byte(&so->ByteIOCxt, new uint8_t[500000], 500000, 0, so,
SoundFfmpeg::readPacket, NULL, SoundFfmpeg::seekMedia);
+ so->ByteIOCxt.is_streamed = 1;
+
+ so->formatCtx = av_alloc_format_context();
+
+ // Open the stream. the 4th argument is the filename, which we ignore.
+ if(av_open_input_stream(&so->formatCtx, &so->ByteIOCxt, "", inputFmt,
NULL) < 0){
+ log_error("Couldn't open file '%s' for decoding",
so->externalURL.c_str());
+ delete so->lock;
+ return;
+ }
+
+ // Next, we need to retrieve information about the streams contained in
the file
+ // This fills the streams field of the AVFormatContext with valid
information
+ int ret = av_find_stream_info(so->formatCtx);
+ if (ret < 0)
+ {
+ log_error("Couldn't find stream information from '%s', error
code: %d", so->externalURL.c_str(), ret);
+ delete so->lock;
+ return;
+ }
+
+ // Find the first audio stream
+ so->audioIndex = -1;
+
+ for (unsigned int i = 0; i < so->formatCtx->nb_streams; i++)
+ {
+ AVCodecContext* enc = so->formatCtx->streams[i]->codec;
+
+ switch (enc->codec_type)
+ {
+ case CODEC_TYPE_AUDIO:
+ if (so->audioIndex < 0)
+ {
+ so->audioIndex = i;
+ so->audioStream =
so->formatCtx->streams[i];
+ }
+ break;
+
+ case CODEC_TYPE_VIDEO:
+ case CODEC_TYPE_DATA:
+ case CODEC_TYPE_SUBTITLE:
+ case CODEC_TYPE_UNKNOWN:
+ log_warning("Non-audio data found in file
%s\n", so->externalURL.c_str());
+ break;
+ }
+ }
+
+ if (so->audioIndex < 0)
+ {
+ log_error("Didn't find a audio stream from '%s'",
so->externalURL.c_str());
+ return;
+ }
+
+ // Get a pointer to the audio codec context for the video stream
+ so->audioCodecCtx = so->formatCtx->streams[so->audioIndex]->codec;
+
+ // Find the decoder for the audio stream
+ AVCodec* pACodec = avcodec_find_decoder(so->audioCodecCtx->codec_id);
+ if(pACodec == NULL)
+ {
+ log_error("No available AUDIO decoder to process file: '%s'",
so->externalURL.c_str());
+ delete so->lock;
+ return;
+ }
+
+ // Open codec
+ if (avcodec_open(so->audioCodecCtx, pACodec) < 0)
+ {
+ log_error("Could not open AUDIO codec");
+ delete so->lock;
+ return;
+ }
+
+ // By deleting this lock we allow start() to start playback
+ delete so->lock;
+ return;
+}
+
+// audio callback is running in sound handler thread
+bool SoundFfmpeg::getAudio(void* owner, uint8_t* stream, int len)
+{
+ SoundFfmpeg* so = static_cast<SoundFfmpeg*>(owner);
+
+ int pos = 0;
+
+ // First use the data left over from last time
+ if (so->leftOverSize > 0) {
+
+ // If we have enough "leftover" data to fill the buffer,
+ // we don't bother to decode some new.
+ if (so->leftOverSize >= len) {
+ memcpy(stream, so->leftOverData, len);
+ int rest = so->leftOverSize - len;
+ if (rest < 1) {
+ delete[] so->leftOverData;
+ so->leftOverSize = 0;
+ } else {
+ uint8_t* buf = new uint8_t[rest];
+ memcpy(stream, so->leftOverData+len, rest);
+ delete[] so->leftOverData;
+ so->leftOverData = buf;
+ so->leftOverSize -= len;
+ }
+ return true;
+ } else {
+ memcpy(stream, so->leftOverData, so->leftOverSize);
+ pos += so->leftOverSize;
+ so->leftOverSize = 0;
+ delete[] so->leftOverData;
+ }
+ }
+
+ AVPacket packet;
+ int rc;
+ bool loop = true;
+ int outputsamples = 0;
+ uint8_t* ptr = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+ bool ret = true;
+ while (loop) {
+ // Parse file
+ rc = av_read_frame(so->formatCtx, &packet);
+ if (rc >= 0)
+ {
+ if (packet.stream_index == so->audioIndex)
+ {
+ sound_handler* s = get_sound_handler();
+ if (s)
+ {
+ // Decode audio
+ int frame_size;
+ if
(avcodec_decode_audio(so->audioCodecCtx, (int16_t*) ptr, &frame_size,
packet.data, packet.size) >= 0)
+ {
+
+ bool stereo =
so->audioCodecCtx->channels > 1 ? true : false;
+ int samples = stereo ?
frame_size >> 2 : frame_size >> 1;
+ int newDataSize = 0;
+ int16_t* output_data = NULL;
+
+ // Resample if needed
+ if (so->audioCodecCtx->channels
!= 2 || so->audioCodecCtx->sample_rate != 44100) {
+ // Resampeling using
ffmpegs (libavcodecs) resampler
+ if (!so->resampleCtx) {
+ // arguments:
(output channels, input channels, output rate, input rate)
+ so->resampleCtx
= audio_resample_init (2, so->audioCodecCtx->channels, 44100,
so->audioCodecCtx->sample_rate);
+ }
+ // The size of this is
a guess, we don't know yet... Lets hope it's big enough
+ output_data = new
int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+ samples =
audio_resample (so->resampleCtx, output_data, (int16_t*)ptr, samples);
+ newDataSize = samples
* 2 * 2; // 2 for stereo and 2 for samplesize = 2 bytes
+ } else {
+ output_data =
(int16_t*)ptr;
+ newDataSize = samples *
2 * 2;
+ }
+
+ // Copy the data to buffer
+ // If the decoded data isn't
enough to fill the buffer, we put the decoded
+ // data into the buffer, and
continues decoding.
+ if (newDataSize <= len-pos) {
+ memcpy(stream+pos,
(uint8_t*)output_data, newDataSize);
+ pos += newDataSize;
+ } else {
+ // If we can fill the buffer,
and still have "leftovers", we save them
+ // and use them later.
+ int rest = len-pos;
+ so->leftOverSize =
newDataSize - rest;
+ memcpy(stream+pos,
(uint8_t*)output_data, rest);
+ so->leftOverData = new
uint8_t[so->leftOverSize];
+
memcpy(so->leftOverData, ((uint8_t*)output_data)+rest, so->leftOverSize);
+ loop = false;
+ pos += rest;
+ }
+ delete[] output_data;
+ }
+ }
+ }
+ } else {
+ // If we should loop we make sure we do.
+ if (so->remainingLoops != 0) {
+ so->remainingLoops--;
+
+ // Seek to begining of file
+ if (av_seek_frame(so->formatCtx,
so->audioIndex, 0, 0) < 0) {
+ log_warning("seeking to start of file
(for looping) failed\n");
+ so->remainingLoops = 0;
+ }
+ } else {
+ // Stops playback by returning false which makes the
soundhandler
+ // detach this sound.
+ ret = false;
+ so->isAttached = false;
+ break;
+ }
+ }
+ } // while
+ delete[] ptr;
+ return ret;
+}
+
+SoundFfmpeg::~SoundFfmpeg() {
+ if (leftOverData && leftOverSize) delete[] leftOverData;
+
+ if (audioCodecCtx) avcodec_close(audioCodecCtx);
+ audioCodecCtx = NULL;
+
+ if (formatCtx) {
+ formatCtx->iformat->flags = AVFMT_NOFILE;
+ av_close_input_file(formatCtx);
+ formatCtx = NULL;
+ }
+
+ if (resampleCtx) {
+ audio_resample_close (resampleCtx);
+ }
+
+/* if (isAttached) {
+ sound_handler* s = get_sound_handler();
+ if (s) {
+ s->detach_aux_streamer(this);
+ }
+ }*/
+
+}
+
+void
+SoundFfmpeg::loadSound(std::string file, bool streaming)
+{
+ leftOverData = NULL;
+ leftOverSize = 0;
+ audioIndex = -1;
+ resampleCtx = NULL;
+ remainingLoops = 0;
+
+ if (connection) {
+ log_warning("This sound already has a connection?? (We try to
handle this by deleting the old one...)\n");
+ delete connection;
+ }
+ externalURL = file;
+
+ connection = new NetConnection();
+
+ externalSound = true;
+ isStreaming = streaming;
+
+ lock = new boost::mutex::scoped_lock(setupMutex);
+
+ // To avoid blocking while connecting, we use a thread.
+ setupThread = new boost::thread(boost::bind(SoundFfmpeg::setupDecoder,
this));
+
+}
+
+void
+SoundFfmpeg::start(int offset, int loops)
+{
+ boost::mutex::scoped_lock lock(setupMutex);
+
+ if (externalSound) {
+ if (offset > 0) {
+ // Seek to offset position
+ double timebase =
(double)formatCtx->streams[audioIndex]->time_base.num /
(double)formatCtx->streams[audioIndex]->time_base.den;
+
+ long newpos = (long)(offset / timebase);
+
+ if (av_seek_frame(formatCtx, audioIndex, newpos, 0) <
0) {
+ log_warning("seeking to offset failed\n");
+ }
+ }
+ // Save how many loops to do
+ if (loops > 0) {
+ remainingLoops = loops;
+ }
+ }
+
+ // Start sound
+ sound_handler* s = get_sound_handler();
+ if (s) {
+ if (externalSound) {
+ if (audioIndex >= 0)
+ {
+ s->attach_aux_streamer(getAudio, (void*) this);
+ isAttached = true;
+ }
+ } else {
+ s->play_sound(soundId, loops, offset, 0, NULL);
+ }
+ }
+}
+
+void
+SoundFfmpeg::stop(int si)
+{
+ // stop the sound
+ sound_handler* s = get_sound_handler();
+ if (s != NULL)
+ {
+ if (si > -1) {
+ if (externalSound) {
+ s->detach_aux_streamer(this);
+ } else {
+ s->stop_sound(soundId);
+ }
+ } else {
+ s->stop_sound(si);
+ }
+ }
+}
+
+unsigned int
+SoundFfmpeg::getDuration()
+{
+ // Return the duration of the file in milliseconds
+ if (formatCtx && audioIndex) {
+ return static_cast<unsigned int>(formatCtx->duration * 1000);
+ } else {
+ return 0;
+ }
+}
+
+unsigned int
+SoundFfmpeg::getPosition()
+{
+ // Return the position in the file in milliseconds
+ if (formatCtx && audioIndex) {
+ double time =
(double)formatCtx->streams[audioIndex]->time_base.num /
formatCtx->streams[audioIndex]->time_base.den *
(double)formatCtx->streams[audioIndex]->cur_dts;
+ return static_cast<unsigned int>(time * 1000);
+ } else {
+ return 0;
+ }
+}
+
+} // end of gnash namespace
+
Index: server/asobj/SoundFfmpeg.h
===================================================================
RCS file: server/asobj/SoundFfmpeg.h
diff -N server/asobj/SoundFfmpeg.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/SoundFfmpeg.h 14 Feb 2007 20:41:48 -0000 1.1
@@ -0,0 +1,96 @@
+//
+// Copyright (C) 2005, 2006, 2007 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
+//
+
+#ifndef __SOUNDFFMPEG_H__
+#define __SOUNDFFMPEG_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "impl.h"
+#include "as_object.h"
+#include "NetConnection.h"
+#include "Sound.h" // for inheritance
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <ffmpeg/avformat.h>
+
+namespace gnash {
+
+// Forward declarations
+class fn_call;
+
+class SoundFfmpeg : public Sound {
+public:
+
+ ~SoundFfmpeg();
+
+ void loadSound(std::string file, bool streaming);
+ void start(int offset, int loops);
+ void stop(int si);
+ unsigned int getDuration();
+ unsigned int getPosition();
+
+ // Used for ffmpeg data read and seek callbacks
+ static int readPacket(void* opaque, uint8_t* buf, int buf_size);
+ static offset_t seekMedia(void *opaque, offset_t offset, int whence);
+
+ static void setupDecoder(SoundFfmpeg* so);
+ static bool getAudio(void *owner, uint8 *stream, int len);
+private:
+
+ // audio
+ AVCodecContext *audioCodecCtx;
+ AVStream* audioStream;
+
+ AVFormatContext *formatCtx;
+
+ AVFrame* audioFrame;
+
+ ReSampleContext *resampleCtx;
+
+ boost::thread *setupThread;
+ boost::mutex setupMutex;
+ boost::mutex::scoped_lock *lock;
+
+ long inputPos;
+
+ ByteIOContext ByteIOCxt;
+
+ // The stream in the file that we use
+ int audioIndex;
+
+ // If the decoded data doesn't fit the buffer we put the leftovers here
+ uint8_t* leftOverData;
+ int leftOverSize;
+
+ // Are this sound attached to the soundhandler?
+ bool isAttached;
+
+ int remainingLoops;
+};
+
+
+} // end of gnash namespace
+
+// __ASSOUND_H__
+#endif
+
Index: server/asobj/SoundGst.cpp
===================================================================
RCS file: server/asobj/SoundGst.cpp
diff -N server/asobj/SoundGst.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/SoundGst.cpp 14 Feb 2007 20:41:48 -0000 1.1
@@ -0,0 +1,331 @@
+//
+// Copyright (C) 2005, 2006, 2007 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
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "SoundGst.h"
+#include "sound.h" // for sound_sample_impl
+#include "movie_definition.h"
+#include "sprite_instance.h"
+#include "fn_call.h"
+#include "GnashException.h"
+#include "builtin_function.h"
+
+#include "gstgnashsrc.h"
+
+#include <string>
+
+namespace gnash {
+
+static gboolean
+register_elements (GstPlugin *plugin)
+{
+ return gst_element_register (plugin, "gnashsrc", GST_RANK_NONE,
GST_TYPE_GNASH_SRC);
+}
+
+static GstPluginDesc gnash_plugin_desc = {
+ 0, // GST_VERSION_MAJOR
+ 10, // GST_VERSION_MINOR
+ "gnashsrc",
+ "Use gnash as source via callbacks",
+ register_elements,
+ "0.0.1",
+ "LGPL",
+ "gnash",
+ "gnash",
+ "http://www.gnu.org/software/gnash/",
+ GST_PADDING_INIT
+};
+
+// Gstreamer callback function
+int
+SoundGst::readPacket(void* opaque, char* buf, int buf_size)
+{
+
+ SoundGst* so = static_cast<SoundGst*>(opaque);
+ NetConnection* nc = so->connection;
+
+ size_t ret = nc->read(static_cast<void*>(buf), buf_size);
+ so->inputPos += ret;
+ return ret;
+
+}
+
+// Gstreamer callback function
+int
+SoundGst::seekMedia(void *opaque, int offset, int whence){
+
+ SoundGst* so = static_cast<SoundGst*>(opaque);
+ NetConnection* nc = so->connection;
+
+
+ // Offset is absolute new position in the file
+ if (whence == SEEK_SET) {
+ nc->seek(offset);
+ so->inputPos = offset;
+
+ // New position is offset + old position
+ } else if (whence == SEEK_CUR) {
+ nc->seek(so->inputPos + offset);
+ so->inputPos = so->inputPos + offset;
+
+ // // New position is offset + end of file
+ } else if (whence == SEEK_END) {
+ // This is (most likely) a streamed file, so we can't seek to
the end!
+ // Instead we seek to 50.000 bytes... seems to work fine...
+ nc->seek(50000);
+ so->inputPos = 50000;
+
+ }
+
+ return so->inputPos;
+}
+
+// Callback function used by Gstreamer to to attached audio and video streams
+// detected by decoderbin to either the video out or audio out elements.
+void
+SoundGst::callback_newpad (GstElement* /*decodebin*/, GstPad *pad, gboolean
/*last*/, gpointer data)
+{
+printf("new pad found\n");
+ SoundGst* so = static_cast<SoundGst*>(data);
+ GstCaps *caps;
+ GstStructure *str;
+ GstPad *audiopad;
+
+ audiopad = gst_element_get_pad (so->audioconv, "sink");
+
+ // check media type
+ caps = gst_pad_get_caps (pad);
+ str = gst_caps_get_structure (caps, 0);
+ if (g_strrstr (gst_structure_get_name (str), "audio")) {
+ // link'n'play
+ gst_pad_link (pad, audiopad);
+printf("new pad connected\n");
+ } else {
+ gst_object_unref (audiopad);
+ log_warning("Non-audio data found in file %s\n",
so->externalURL.c_str());
+ }
+ gst_caps_unref (caps);
+ return;
+
+}
+
+void
+SoundGst::setupDecoder(SoundGst* so)
+{
+
+ NetConnection* nc = so->connection;
+ assert(nc);
+
+ // Pass stuff from/to the NetConnection object.
+ assert(so);
+ if ( !nc->openConnection(so->externalURL.c_str(), so) ) {
+ log_warning("Gnash could not open audio url: %s",
so->externalURL.c_str());
+ delete so->lock;
+ return;
+ }
+
+ so->inputPos = 0;
+
+ // init GStreamer
+ gst_init (NULL, NULL);
+
+ // setup the GnashNC plugin
+ _gst_plugin_register_static (&gnash_plugin_desc);
+
+ // setup the pipeline
+ so->pipeline = gst_pipeline_new (NULL);
+
+ // create an audio sink - use oss, alsa or...? make a commandline
option?
+ // we first try atudetect, then alsa, then oss, then esd, then...?
+ // If the gstreamer adder ever gets fixed this should be connected to
the
+ // adder in the soundhandler.
+#if !defined(__NetBSD__)
+ so->audiosink = gst_element_factory_make ("autoaudiosink", NULL);
+ if (!so->audiosink) so->audiosink = gst_element_factory_make
("alsasink", NULL);
+ if (!so->audiosink) so->audiosink = gst_element_factory_make
("osssink", NULL);
+#endif
+ if (!so->audiosink) so->audiosink = gst_element_factory_make
("esdsink", NULL);
+
+ // Check if the creation of the gstreamer pipeline and audiosink was a
succes
+ if (!so->pipeline) {
+ gnash::log_error("The gstreamer pipeline element could not be
created\n");
+ return;
+ }
+ if (!so->audiosink) {
+ gnash::log_error("The gstreamer audiosink element could not be
created\n");
+ return;
+ }
+
+ // setup gnashnc source (our homegrown source element)
+ so->source = gst_element_factory_make ("gnashsrc", NULL);
+ gnashsrc_callback* gc = new gnashsrc_callback;
+ gc->read = SoundGst::readPacket;
+ gc->seek = SoundGst::seekMedia;
+ g_object_set (G_OBJECT (so->source), "data", so, "callbacks", gc, NULL);
+
+ // setup the audio converter
+ so->audioconv = gst_element_factory_make ("audioconvert", NULL);
+
+ // setup the volume controller
+ so->volume = gst_element_factory_make ("volume", NULL);
+
+ // setup the decoder with callback
+ so->decoder = gst_element_factory_make ("decodebin", NULL);
+ g_signal_connect (so->decoder, "new-decoded-pad", G_CALLBACK
(SoundGst::callback_newpad), so);
+
+
+ if (!so->source || !so->audioconv || !so->volume || !so->decoder) {
+ gnash::log_error("Gstreamer element(s) for movie handling could
not be created\n");
+ return;
+ }
+
+ // put it all in the pipeline
+ gst_bin_add_many (GST_BIN (so->pipeline), so->source, so->decoder,
so->audiosink, so->audioconv, so->volume, NULL);
+
+ // link the elements
+ gst_element_link(so->source, so->decoder);
+ gst_element_link_many(so->audioconv, so->volume, so->audiosink, NULL);
+
+ // By deleting this lock we allow start() to start playback
+ delete so->lock;
+ return;
+}
+
+SoundGst::~SoundGst() {
+
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (pipeline));
+}
+
+void
+SoundGst::loadSound(std::string file, bool streaming)
+{
+ remainingLoops = 0;
+
+ if (connection) {
+ log_warning("This sound already has a connection?? (We try to
handle this by deleting the old one...)\n");
+ delete connection;
+ }
+ externalURL = file;
+
+ connection = new NetConnection();
+
+ externalSound = true;
+ isStreaming = streaming;
+
+ lock = new boost::mutex::scoped_lock(setupMutex);
+
+ // To avoid blocking while connecting, we use a thread.
+ setupThread = new boost::thread(boost::bind(SoundGst::setupDecoder,
this));
+
+}
+
+void
+SoundGst::start(int offset, int loops)
+{
+ boost::mutex::scoped_lock lock(setupMutex);
+
+ if (externalSound) {
+ if (offset > 0) {
+ // Seek to offset position
+ if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME,
GST_SEEK_FLAG_FLUSH,
+ GST_SEEK_TYPE_SET, GST_SECOND *
static_cast<long>(offset),
+ GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
+ log_warning("seeking to offset failed\n");
+ }
+
+ }
+ // Save how many loops to do
+ if (loops > 0) {
+ remainingLoops = loops;
+ }
+ // start playing
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+printf("playback started\n");
+
+ }
+
+
+ // Start sound
+ sound_handler* s = get_sound_handler();
+ if (s) {
+ if (!externalSound) {
+ s->play_sound(soundId, loops, offset, 0, NULL);
+ }
+ }
+}
+
+void
+SoundGst::stop(int si)
+{
+ // stop the sound
+ sound_handler* s = get_sound_handler();
+ if (s != NULL)
+ {
+ if (si > -1) {
+ if (externalSound) {
+ gst_element_set_state (GST_ELEMENT (pipeline),
GST_STATE_NULL);
+ } else {
+ s->stop_sound(soundId);
+ }
+ } else {
+ s->stop_sound(si);
+ }
+ }
+}
+
+unsigned int
+SoundGst::getDuration()
+{
+ // Return the duration of the file in milliseconds
+ GstFormat fmt = GST_FORMAT_TIME;
+ int64_t len;
+
+ if (pipeline && gst_element_query_duration (pipeline, &fmt, &len)) {
+ return static_cast<unsigned int>(len*1000);
+ } else {
+ return 0;
+ }
+}
+
+unsigned int
+SoundGst::getPosition()
+{
+ // Return the position in the file in milliseconds
+ if (!pipeline) return 0;
+
+ GstFormat fmt = GST_FORMAT_TIME;
+ int64_t pos;
+ GstStateChangeReturn ret;
+ GstState current, pending;
+
+ ret = gst_element_get_state (GST_ELEMENT (pipeline), ¤t,
&pending, 0);
+
+ if (current != GST_STATE_NULL && gst_element_query_position (pipeline,
&fmt, &pos)) {
+ return static_cast<unsigned int>(pos * 1000);
+ } else {
+ return 0;
+ }
+}
+
+} // end of gnash namespace
+
Index: server/asobj/SoundGst.h
===================================================================
RCS file: server/asobj/SoundGst.h
diff -N server/asobj/SoundGst.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/SoundGst.h 14 Feb 2007 20:41:48 -0000 1.1
@@ -0,0 +1,87 @@
+//
+// Copyright (C) 2005, 2006, 2007 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
+//
+
+#ifndef __SOUNDGST_H__
+#define __SOUNDGST_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "impl.h"
+#include "as_object.h"
+#include "NetConnection.h"
+#include "Sound.h" // for inheritance
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <gst/gst.h>
+
+namespace gnash {
+
+// Forward declarations
+class fn_call;
+
+class SoundGst : public Sound {
+public:
+
+ ~SoundGst();
+
+ void loadSound(std::string file, bool streaming);
+ void start(int offset, int loops);
+ void stop(int si);
+ unsigned int getDuration();
+ unsigned int getPosition();
+
+ // Used for ffmpeg data read and seek callbacks
+ static int readPacket(void* opaque, char* buf, int buf_size);
+ static int seekMedia(void *opaque, int offset, int whence);
+
+ static void setupDecoder(SoundGst* so);
+ static bool getAudio(void *owner, uint8 *stream, int len);
+
+ static void callback_newpad (GstElement *decodebin, GstPad *pad,
gboolean last, gpointer data);
+private:
+
+ // gstreamer pipeline objects
+ GstElement *pipeline;
+ GstElement *audiosink;
+ GstElement *source;
+ GstElement *decoder;
+ GstElement *volume;
+ GstElement *audioconv;
+
+ boost::thread *setupThread;
+ boost::mutex setupMutex;
+ boost::mutex::scoped_lock *lock;
+
+ long inputPos;
+
+ // Are this sound attached to the soundhandler?
+ bool isAttached;
+
+ int remainingLoops;
+};
+
+
+} // end of gnash namespace
+
+// __SOUNDGST_H__
+#endif
+
Index: server/asobj/SoundMad.cpp
===================================================================
RCS file: server/asobj/SoundMad.cpp
diff -N server/asobj/SoundMad.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/SoundMad.cpp 14 Feb 2007 20:41:48 -0000 1.1
@@ -0,0 +1,439 @@
+//
+// Copyright (C) 2005, 2006, 2007 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
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "SoundMad.h"
+#include "sound.h" // for sound_sample_impl
+#include "movie_definition.h"
+#include "sprite_instance.h"
+#include "fn_call.h"
+#include "GnashException.h"
+#include "builtin_function.h"
+
+#include <string>
+
+namespace gnash {
+
+int
+SoundMad::readPacket(uint8_t* buf, int buf_size)
+{
+
+ size_t ret = connection->read(static_cast<void*>(buf), buf_size);
+ inputPos += ret;
+ return ret;
+
+}
+
+int
+SoundMad::seekMedia(int offset, int whence){
+
+ // Offset is absolute new position in the file
+ if (whence == SEEK_SET) {
+ connection->seek(offset);
+ inputPos = offset;
+
+ // New position is offset + old position
+ } else if (whence == SEEK_CUR) {
+ connection->seek(inputPos + offset);
+ inputPos = inputPos + offset;
+
+ // // New position is offset + end of file
+ } else if (whence == SEEK_END) {
+ // This is (most likely) a streamed file, so we can't seek to
the end!
+ // Instead we seek to 50.000 bytes... seems to work fine...
+ connection->seek(50000);
+ inputPos = 50000;
+
+ }
+
+ return inputPos;
+}
+
+
+void
+SoundMad::setupDecoder(SoundMad* so)
+{
+
+ NetConnection* nc = so->connection;
+ assert(nc);
+
+ // Pass stuff from/to the NetConnection object.
+ assert(so);
+ if ( !nc->openConnection(so->externalURL.c_str(), so) ) {
+ log_warning("Gnash could not open audio url: %s",
so->externalURL.c_str());
+ delete so->lock;
+ return;
+ }
+
+ so->inputPos = 0;
+
+ // Init the mad decoder
+ mad_stream_init(&so->stream);
+ mad_frame_init(&so->frame);
+ mad_synth_init(&so->synth);
+
+ // Decode a single frame to decode the header
+
+ // Fetch data from the file
+ so->seekMedia(0, SEEK_SET);
+ uint8_t* buf = new uint8_t[1024];
+ int bufSize = so->readPacket(buf, 1024);
+
+ // Setup the mad decoder
+ mad_stream_buffer(&so->stream, buf, bufSize);
+
+ int ret;
+
+ int loops = 0;
+ while(true) {
+
+ ret = mad_frame_decode(&so->frame, &so->stream);
+ loops++;
+
+ // There is always some junk in front of the data,
+ // so we continue until we get past it.
+ if (ret && so->stream.error == MAD_ERROR_LOSTSYNC) continue;
+
+ // Error handling is done by relooping (max. 8 times) and just
hooping that it will work...
+ if (loops > 8) break;
+ if (ret == -1 && so->stream.error != MAD_ERROR_BUFLEN &&
MAD_RECOVERABLE(so->stream.error)) {
+ log_warning("Recoverable error while decoding MP3, MAD
error: %s", mad_stream_errorstr (&so->stream));
+ continue;
+ }
+ break;
+ }
+ so->bitrate = so->frame.header.bitrate;
+
+ so->seekMedia(0, SEEK_SET);
+ delete [] buf;
+
+ // By deleting this lock we allow start() to start playback
+ delete so->lock;
+ return;
+}
+
+// audio callback is running in sound handler thread
+bool SoundMad::getAudio(void* owner, uint8_t* stream, int len)
+{
+ SoundMad* so = static_cast<SoundMad*>(owner);
+
+ int pos = 0;
+
+ // First use the data left over from last time
+ if (so->leftOverSize > 0) {
+
+ // If we have enough "leftover" data to fill the buffer,
+ // we don't bother to decode some new.
+ if (so->leftOverSize >= len) {
+ memcpy(stream, so->leftOverData, len);
+ int rest = so->leftOverSize - len;
+ if (rest < 1) {
+ delete[] so->leftOverData;
+ so->leftOverSize = 0;
+ } else {
+ uint8_t* buf = new uint8_t[rest];
+ memcpy(stream, so->leftOverData+len, rest);
+ delete[] so->leftOverData;
+ so->leftOverData = buf;
+ so->leftOverSize -= len;
+ }
+ return true;
+ } else {
+ memcpy(stream, so->leftOverData, so->leftOverSize);
+ pos += so->leftOverSize;
+ so->leftOverSize = 0;
+ delete[] so->leftOverData;
+ }
+ }
+
+ uint8_t* buf = new uint8_t[8192];
+ int bufSize = so->readPacket(buf, 8192);
+ int orgBufSize = bufSize;
+
+ bool loop = true;
+ int outputsamples = 0;
+
+ uint8_t* ptr = new uint8_t[8192];
+
+ bool ret = true;
+ sound_handler* s = get_sound_handler();
+ if (bufSize > 0) {
+ if (s) {
+ // temp raw buffer
+ uint8_t* tmp_raw_buffer;
+ unsigned int tmp_raw_buffer_size;
+ int outsize = 0;
+ while (loop) {
+ // Decode audio
+
+ // Setup the mad decoder
+ mad_stream_buffer(&so->stream,
buf+(orgBufSize-bufSize), bufSize);
+
+ int ret;
+ const unsigned char* old_next_frame =
so->stream.next_frame;
+ int loops = 0;
+ while(true) {
+
+ ret = mad_frame_decode(&so->frame,
&so->stream);
+ loops++;
+
+ // There is always some junk in front
of the data,
+ // so we continue until we get past it.
+ if (ret && so->stream.error ==
MAD_ERROR_LOSTSYNC) continue;
+
+ // Error handling is done by relooping
(max. 8 times) and just hooping that it will work...
+ if (loops > 8) break;
+ if (ret == -1 && so->stream.error !=
MAD_ERROR_BUFLEN && MAD_RECOVERABLE(so->stream.error)) {
+ log_warning("Recoverable error
while decoding MP3, MAD error: %s", mad_stream_errorstr (&so->stream));
+ continue;
+ }
+
+ break;
+ }
+
+ if (ret == -1 && so->stream.error !=
MAD_ERROR_BUFLEN) {
+ log_error("Unrecoverable error while
decoding MP3, MAD error: %s", mad_stream_errorstr (&so->stream));
+ bufSize = 0;
+ loop = false;
+ } else if (ret == -1 && so->stream.error ==
MAD_ERROR_BUFLEN) {
+ // the buffer is empty, no more to
decode!
+ bufSize = 0;
+ loop = false;
+ } else {
+ bufSize -= so->stream.next_frame -
old_next_frame;
+ }
+
+ mad_synth_frame (&so->synth, &so->frame);
+
+ outsize = so->synth.pcm.length *
((so->frame.header.mode) ? 4 : 2);
+
+ tmp_raw_buffer = new uint8_t[outsize];
+ int sample;
+
+ int16_t* dst =
reinterpret_cast<int16_t*>(tmp_raw_buffer);
+
+ // transfer the decoded samples into the
sound-struct, and do some
+ // scaling while we're at it.
+ for(int f = 0; f < so->synth.pcm.length; f++)
+ {
+ for (int e = 0; e <
((so->frame.header.mode) ? 2 : 1); e++){ // channels (stereo/mono)
+
+ mad_fixed_t mad_sample =
so->synth.pcm.samples[e][f];
+
+ // round
+ mad_sample += (1L <<
(MAD_F_FRACBITS - 16));
+
+ // clip
+ if (mad_sample >= MAD_F_ONE)
mad_sample = MAD_F_ONE - 1;
+ else if (mad_sample <
-MAD_F_ONE) mad_sample = -MAD_F_ONE;
+
+ // quantize
+ sample = mad_sample >>
(MAD_F_FRACBITS + 1 - 16);
+
+ if ( sample !=
static_cast<int16_t>(sample) ) sample = sample < 0 ? -32768 : 32767;
+
+ *dst++ = sample;
+ }
+ }
+
+ // If we need to convert samplerate or/and from
mono to stereo...
+ if (outsize > 0 && (so->frame.header.samplerate
!= 44100 || !so->frame.header.mode)) {
+
+ int16_t* adjusted_data = 0;
+ int adjusted_size = 0;
+ int sample_count = outsize /
((so->frame.header.mode) ? 4 : 2);
+
+ // Convert to needed samplerate
+ s->convert_raw_data(&adjusted_data,
&adjusted_size, tmp_raw_buffer, sample_count, 0,
+
so->frame.header.samplerate, so->frame.header.mode);
+
+ // Hopefully this wont happen
+ if (!adjusted_data) {
+ log_warning("Error in sound
sample convertion");
+ continue;
+ }
+
+ // Move the new data to the sound-struct
+ delete[] tmp_raw_buffer;
+ tmp_raw_buffer =
reinterpret_cast<uint8_t*>(adjusted_data);
+ tmp_raw_buffer_size = adjusted_size;
+
+ } else {
+ tmp_raw_buffer_size = outsize;
+ }
+
+
+
+
+ // Copy the data to buffer
+ // If the decoded data isn't enough to fill the
buffer, we put the decoded
+ // data into the buffer, and continues decoding.
+ if (tmp_raw_buffer_size <= len-pos) {
+ memcpy(stream+pos, tmp_raw_buffer,
tmp_raw_buffer_size);
+ pos += tmp_raw_buffer_size;
+ } else {
+ // If we can fill the buffer, and still have
"leftovers", we save them
+ // and use them later.
+ int rest = len-pos;
+ so->leftOverSize = tmp_raw_buffer_size
- rest;
+ memcpy(stream+pos, tmp_raw_buffer,
rest);
+ so->leftOverData = new
uint8_t[so->leftOverSize];
+ memcpy(so->leftOverData,
(tmp_raw_buffer)+rest, so->leftOverSize);
+ loop = false;
+ pos += rest;
+ }
+ delete[] tmp_raw_buffer;
+ } // while
+ } // (s)
+ } else { // bufSize > 0
+ // If we should loop we make sure we do.
+ if (so->remainingLoops != 0) {
+ so->remainingLoops--;
+
+ // Seek to begining of file
+ so->seekMedia(0, SEEK_SET);
+ } else {
+ // Stops playback by returning false which makes the
soundhandler
+ // detach this sound.
+ ret = false;
+ so->isAttached = false;
+ }
+ }
+ so->seekMedia(-bufSize, SEEK_CUR);
+ delete[] ptr;
+ return ret;
+}
+
+SoundMad::~SoundMad() {
+ if (leftOverData && leftOverSize) delete[] leftOverData;
+
+ mad_synth_finish(&synth);
+ mad_frame_finish(&frame);
+ mad_stream_finish(&stream);
+
+/* if (isAttached) {
+ sound_handler* s = get_sound_handler();
+ if (s) {
+ s->detach_aux_streamer(this);
+ }
+ }*/
+
+}
+
+void
+SoundMad::loadSound(std::string file, bool streaming)
+{
+ leftOverData = NULL;
+ leftOverSize = 0;
+ remainingLoops = 0;
+
+ if (connection) {
+ log_warning("This sound already has a connection?? (We try to
handle this by deleting the old one...)\n");
+ delete connection;
+ }
+ externalURL = file;
+
+ connection = new NetConnection();
+
+ externalSound = true;
+ isStreaming = streaming;
+
+ lock = new boost::mutex::scoped_lock(setupMutex);
+
+ // To avoid blocking while connecting, we use a thread.
+ setupThread = new boost::thread(boost::bind(SoundMad::setupDecoder,
this));
+
+}
+
+void
+SoundMad::start(int offset, int loops)
+{
+ boost::mutex::scoped_lock lock(setupMutex);
+
+ if (externalSound) {
+ seekMedia((bitrate*offset)/8, SEEK_SET);
+
+ // Save how many loops to do
+ if (loops > 0) {
+ remainingLoops = loops;
+ }
+ }
+
+ // Start sound
+ sound_handler* s = get_sound_handler();
+ if (s) {
+ if (externalSound) {
+ if (1)
+ {
+ s->attach_aux_streamer(getAudio, (void*) this);
+ isAttached = true;
+ }
+ } else {
+ s->play_sound(soundId, loops, offset, 0, NULL);
+ }
+ }
+}
+
+void
+SoundMad::stop(int si)
+{
+ // stop the sound
+ sound_handler* s = get_sound_handler();
+ if (s != NULL)
+ {
+ if (si > -1) {
+ if (externalSound) {
+ s->detach_aux_streamer(this);
+ } else {
+ s->stop_sound(soundId);
+ }
+ } else {
+ s->stop_sound(si);
+ }
+ }
+}
+
+unsigned int
+SoundMad::getDuration()
+{
+ // Return the duration of the file in milliseconds
+/* if (formatCtx && audioIndex) {
+ return static_cast<unsigned int>(formatCtx->duration * 1000);
+ } else {
+ return 0;
+ }*/
+ return 0;
+}
+
+unsigned int
+SoundMad::getPosition()
+{
+ // Return the position in the file in milliseconds
+ if (1) {
+ return inputPos/bitrate/8*1000;
+ } else {
+ return 0;
+ }
+}
+
+} // end of gnash namespace
+
Index: server/asobj/SoundMad.h
===================================================================
RCS file: server/asobj/SoundMad.h
diff -N server/asobj/SoundMad.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/asobj/SoundMad.h 14 Feb 2007 20:41:48 -0000 1.1
@@ -0,0 +1,88 @@
+//
+// Copyright (C) 2005, 2006, 2007 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
+//
+
+#ifndef __SOUNDMAD_H__
+#define __SOUNDMAD_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "impl.h"
+#include "as_object.h"
+#include "NetConnection.h"
+#include "Sound.h" // for inheritance
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <mad.h>
+
+namespace gnash {
+
+// Forward declarations
+class fn_call;
+
+class SoundMad : public Sound {
+public:
+
+ ~SoundMad();
+
+ void loadSound(std::string file, bool streaming);
+ void start(int offset, int loops);
+ void stop(int si);
+ unsigned int getDuration();
+ unsigned int getPosition();
+
+ static void setupDecoder(SoundMad* so);
+ static bool getAudio(void *owner, uint8 *stream, int len);
+private:
+
+ long inputPos;
+
+ boost::thread *setupThread;
+ boost::mutex setupMutex;
+ boost::mutex::scoped_lock *lock;
+
+ // bitrate in bps
+ unsigned long bitrate;
+
+ int readPacket(uint8_t* buf, int buf_size);
+ int seekMedia(int offset, int whence);
+
+ /// mad stuff
+ mad_stream stream;
+ mad_frame frame;
+ mad_synth synth;
+
+ // If the decoded data doesn't fit the buffer we put the leftovers here
+ uint8_t* leftOverData;
+ int leftOverSize;
+
+ // Are this sound attached to the soundhandler?
+ bool isAttached;
+
+ int remainingLoops;
+};
+
+
+} // end of gnash namespace
+
+// __ASSOUND_H__
+#endif
+
- [Gnash-commit] gnash ChangeLog backend/sound_handler_sdl.cpp l...,
Tomas Groth <=