gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11053: Migrated Sound actionscript


From: Ben Limmer
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11053: Migrated Sound actionscript class to new hierarchy
Date: Tue, 09 Jun 2009 13:00:20 -0600
User-agent: Bazaar (1.13.1)

------------------------------------------------------------
revno: 11053
committer: Ben Limmer <address@hidden>
branch nick: trunk
timestamp: Tue 2009-06-09 13:00:20 -0600
message:
  Migrated Sound actionscript class to new hierarchy
removed:
  libcore/asobj/Sound_as.cpp
  libcore/asobj/Sound_as.h
modified:
  libcore/ClassHierarchy.cpp
  libcore/asobj/Global.cpp
  libcore/asobj/Makefile.am
  libcore/asobj/flash.am
  libcore/asobj/flash/media/Sound_as.cpp
  libcore/asobj/flash/media/Sound_as.h
  libcore/asobj/flash/media/media.am
    ------------------------------------------------------------
    revno: 11049.1.1
    committer: Ben Limmer <address@hidden>
    branch nick: branch_6
    timestamp: Tue 2009-06-09 11:32:44 -0600
    message:
      Migrated Sound actionscript class to new hierarchy
    removed:
      libcore/asobj/Sound_as.cpp
      libcore/asobj/Sound_as.h
    modified:
      libcore/ClassHierarchy.cpp
      libcore/asobj/Global.cpp
      libcore/asobj/Makefile.am
      libcore/asobj/flash.am
      libcore/asobj/flash/media/Sound_as.cpp
      libcore/asobj/flash/media/Sound_as.h
      libcore/asobj/flash/media/media.am
=== modified file 'libcore/ClassHierarchy.cpp'
--- a/libcore/ClassHierarchy.cpp        2009-06-09 18:42:51 +0000
+++ b/libcore/ClassHierarchy.cpp        2009-06-09 19:00:20 +0000
@@ -48,8 +48,8 @@
 #include "NetStream_as.h"
 #include "Selection_as.h"
 #include "flash/net/SharedObject_as.h"
-#include "Sound_as.h"
 #include "flash/display/Stage_as.h"
+#include "flash/media/Sound_as.h"
 #include "System_as.h"
 #include "flash/text/TextSnapshot_as.h"
 #include "TextFormat_as.h"

=== modified file 'libcore/asobj/Global.cpp'
--- a/libcore/asobj/Global.cpp  2009-06-09 18:42:51 +0000
+++ b/libcore/asobj/Global.cpp  2009-06-09 19:00:20 +0000
@@ -40,6 +40,7 @@
 #include "flash/ui/Keyboard_as.h"
 #include "Selection_as.h"
 #include "Microphone.h"
+#include "flash/media/Sound_as.h"
 #include "Number_as.h"
 #include "Object.h"
 #include "Math_as.h"

=== modified file 'libcore/asobj/Makefile.am'
--- a/libcore/asobj/Makefile.am 2009-06-09 18:42:51 +0000
+++ b/libcore/asobj/Makefile.am 2009-06-09 19:00:20 +0000
@@ -72,7 +72,6 @@
        PlayHead.cpp \
        Selection_as.cpp \
        Namespace_as.cpp \
-       Sound_as.cpp \
        Stage_as.cpp \
        TextFormat_as.cpp \
        TextSnapshot_as.cpp \
@@ -102,7 +101,6 @@
        Number_as.h \
        PlayHead.h \
        Selection_as.h \
-       Sound_as.h \
        Stage_as.h      \
        TextFormat_as.h \
        TextSnapshot_as.h \

=== removed file 'libcore/asobj/Sound_as.cpp'
--- a/libcore/asobj/Sound_as.cpp        2009-06-09 14:04:51 +0000
+++ b/libcore/asobj/Sound_as.cpp        1970-01-01 00:00:00 +0000
@@ -1,1121 +0,0 @@
-// Sound_as.cpp:  ActionScript Sound output stub class, for Gnash.
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-#ifdef HAVE_CONFIG_H
-#include "gnashconfig.h"
-#endif
-
-#include "Sound_as.h"
-#include "log.h"
-#include "sound_handler.h"
-#include "AudioDecoder.h"
-#include "MediaParser.h"
-#include "MediaHandler.h"
-#include "sound_definition.h" // for sound_sample
-#include "movie_root.h"
-#include "movie_definition.h"
-#include "fn_call.h"
-#include "GnashException.h"
-#include "builtin_function.h"
-#include "Object.h" // for getObjectInterface
-#include "VM.h"
-#include "namedStrings.h"
-#include "ExportableResource.h"
-#include "StreamProvider.h"
-
-#include <string>
-
-// Define the macro below to get some more DEBUG
-// lines while Sound is at work
-//#define GNASH_DEBUG_SOUND_AS
-
-namespace gnash {
-
-static as_value sound_new(const fn_call& fn);
-static as_value sound_attachsound(const fn_call& fn);
-static as_value sound_getbytesloaded(const fn_call& fn);
-static as_value sound_getbytestotal(const fn_call& fn);
-static as_value sound_getpan(const fn_call& fn);
-static as_value sound_setpan(const fn_call& fn);
-static as_value sound_getDuration(const fn_call& fn);
-static as_value sound_setDuration(const fn_call& fn);
-static as_value sound_gettransform(const fn_call& fn);
-static as_value sound_getPosition(const fn_call& fn);
-static as_value sound_getvolume(const fn_call& fn);
-static as_value sound_loadsound(const fn_call& fn);
-static as_value sound_settransform(const fn_call& fn);
-static as_value sound_setvolume(const fn_call& fn);
-static as_value sound_start(const fn_call& fn);
-static as_value sound_stop(const fn_call& fn);
-static as_value checkPolicyFile_getset(const fn_call& fn);
-static as_object* getSoundInterface();
-
-Sound_as::Sound_as() 
-    :
-    as_object(getSoundInterface()),
-    _attachedCharacter(0),
-    soundId(-1),
-    externalSound(false),
-    isStreaming(false),
-    _soundHandler(_vm.getRoot().runInfo().soundHandler()),
-    _mediaHandler(media::MediaHandler::get()),
-    _startTime(0),
-    _leftOverData(),
-    _leftOverPtr(0),
-    _leftOverSize(0),
-    _inputStream(0),
-    remainingLoops(0),
-    _probeTimer(0),
-    _soundCompleted(false)
-{
-}
-
-Sound_as::~Sound_as()
-{
-    //GNASH_REPORT_FUNCTION;
-
-    if (_inputStream && _soundHandler)
-    {
-        _soundHandler->unplugInputStream(_inputStream);
-        _inputStream=0;
-    }
-
-}
-
-void
-Sound_as::attachCharacter(DisplayObject* attachTo) 
-{
-    _attachedCharacter.reset(new CharacterProxy(attachTo));
-}
-
-void
-Sound_as::attachSound(int si, const std::string& name)
-{
-    soundId = si;
-    soundName = name;
-}
-
-long
-Sound_as::getBytesLoaded()
-{
-    if ( _mediaParser ) return _mediaParser->getBytesLoaded();
-    return -1;
-}
-
-long
-Sound_as::getBytesTotal()
-{
-    if ( _mediaParser ) return _mediaParser->getBytesTotal();
-    return -1;
-}
-
-void
-Sound_as::getPan()
-{
-    LOG_ONCE(log_unimpl(__FUNCTION__));
-}
-
-void
-Sound_as::getTransform()
-{
-    LOG_ONCE(log_unimpl(__FUNCTION__));
-}
-
-bool
-Sound_as::getVolume(int& volume)
-{
-    // TODO: check what takes precedence in case we
-    //       have both an attached DisplayObject *and*
-    //       some other sound...
-    //
-    if ( _attachedCharacter )
-    {
-        //log_debug("Sound has an attached DisplayObject");
-        DisplayObject* ch = _attachedCharacter->get();
-        if ( ! ch )
-        {
-            log_debug("Character attached to Sound was unloaded and "
-                    "couldn't rebind");
-            return false;
-        }
-        volume = ch->getVolume();
-        return true;
-    }
-    //else log_debug("Sound has NO attached DisplayObject, _soundHandler is 
%p, soundId is %d", _soundHandler, soundId);
-
-    // If we're not attached to a DisplayObject we'll need to query
-    // sound_handler for volume. If we have no sound handler, we
-    // can't do much, so we'll return false
-    if (!_soundHandler)
-    {
-        log_debug("We have no sound handler here...");
-        return false;
-    }
-
-    // Now, we may be controlling a specific sound or
-    // the final output as a whole.
-    // If soundId is -1 we're controlling as a whole
-    //
-    if ( soundId == -1 )
-    {
-        volume = _soundHandler->getFinalVolume();
-    }
-    else
-    {
-        volume = _soundHandler->get_volume(soundId);
-    }
-
-    return true;
-}
-
-void
-Sound_as::loadSound(const std::string& file, bool streaming)
-{
-    if ( ! _mediaHandler || ! _soundHandler ) 
-    {
-        log_debug("No media or sound handlers, won't load any sound");
-        return;
-    }
-
-    /// If we are already streaming stop doing so as we'll replace
-    /// the media parser
-    if ( _inputStream )
-    {
-        _soundHandler->unplugInputStream(_inputStream);
-        _inputStream = 0;
-    }
-
-    /// Delete any media parser being used (make sure we have detached!)
-    _mediaParser.reset();
-
-    /// Start at offset 0, in case a previous ::start() call
-    /// changed that.
-    _startTime=0;
-
-    const movie_root& mr = _vm.getRoot();
-    URL url(file, mr.runInfo().baseURL());
-
-    const RcInitFile& rcfile = RcInitFile::getDefaultInstance();
-
-    const StreamProvider& streamProvider = mr.runInfo().streamProvider();
-    std::auto_ptr<IOChannel> inputStream(streamProvider.getStream(url,
-                rcfile.saveStreamingMedia()));
-    if ( ! inputStream.get() )
-    {
-        log_error( _("Gnash could not open this url: %s"), url );
-        return;
-    }
-
-    externalSound = true;
-    isStreaming = streaming;
-
-    
_mediaParser.reset(_mediaHandler->createMediaParser(inputStream).release());
-    if ( ! _mediaParser )
-    {
-        log_error(_("Unable to create parser for Sound at %s"), url);
-        // not necessarely correct, the stream might have been found...
-        return;
-    }
-
-    // TODO: use global _soundbuftime
-    _mediaParser->setBufferTime(60000); // one minute buffer... should be fine
-
-    if ( isStreaming )
-    {
-        startProbeTimer();
-    }
-    else
-    {
-        LOG_ONCE(log_unimpl("Non-streaming Sound.loadSound: will behave "
-                    "as a streaming one"));
-        // if not streaming, we'll probe on .start()
-    }
-}
-
-sound::InputStream*
-Sound_as::attachAuxStreamerIfNeeded()
-{
-    media::AudioInfo* audioInfo =  _mediaParser->getAudioInfo();
-    if (!audioInfo) return 0;
-
-    // the following may throw an exception
-    
_audioDecoder.reset(_mediaHandler->createAudioDecoder(*audioInfo).release());
-
-    // start playing ASAP, a call to ::start will just change _startTime
-#ifdef GNASH_DEBUG_SOUND_AS
-    log_debug("Attaching the aux streamer");
-#endif
-    return _soundHandler->attach_aux_streamer(getAudioWrapper, (void*) this);
-}
-
-void
-Sound_as::setPan()
-{
-    LOG_ONCE(log_unimpl(__FUNCTION__));
-}
-
-void
-Sound_as::setTransform()
-{
-    LOG_ONCE(log_unimpl(__FUNCTION__));
-}
-
-void
-Sound_as::setVolume(int volume)
-{
-    // TODO: check what takes precedence in case we
-    //       have both an attached DisplayObject *and*
-    //       some other sound...
-    //
-    if ( _attachedCharacter )
-    {
-        DisplayObject* ch = _attachedCharacter->get();
-        if ( ! ch )
-        {
-            log_debug("Character attached to Sound was unloaded and "
-                    "couldn't rebind");
-            return;
-        }
-        ch->setVolume(volume);
-        return;
-    }
-
-    // If we're not attached to a DisplayObject we'll need to use
-    // sound_handler for volume. If we have no sound handler, we
-    // can't do much, so we'll just return
-    if (!_soundHandler)
-    {
-        return;
-    }
-
-    // Now, we may be controlling a specific sound or
-    // the final output as a whole.
-    // If soundId is -1 we're controlling as a whole
-    //
-    if ( soundId == -1 )
-    {
-        _soundHandler->setFinalVolume(volume);
-    }
-    else
-    {
-        _soundHandler->set_volume(soundId, volume);
-    }
-}
-
-void
-Sound_as::start(int offset, int loops)
-{
-    if ( ! _soundHandler )
-    {
-        log_error("No sound handler, nothing to start...");
-        return;
-    }
-
-    if (externalSound)
-    {
-        if ( ! _mediaParser )
-        {
-            log_error("No MediaParser initialized, can't start an external 
sound");
-            return;
-        }
-
-        if (offset > 0)
-        {
-            _startTime=offset*1000;
-            boost::uint32_t seekms = boost::uint32_t(offset*1000);
-            // TODO: boost::mutex::scoped_lock parserLock(_parserMutex);
-            _mediaParser->seek(seekms); // well, we try...
-        }
-
-        if (isStreaming)
-        {
-            IF_VERBOSE_ASCODING_ERRORS(
-            log_aserror(_("Sound.start() has no effect on a streaming Sound"));
-            );
-            return;
-        }
-
-        // Save how many loops to do (not when streaming)
-        if (loops > 0)
-        {
-            remainingLoops = loops;
-        }
-
-        // TODO: we should really be waiting for the sound to be fully
-        //       loaded before starting to play it (!isStreaming case)
-        startProbeTimer();
-
-        //if ( ! _inputStream ) {
-        //  _inputStream=_soundHandler->attach_aux_streamer(getAudioWrapper, 
(void*) this);
-        //}
-    }
-    else
-    {
-        _soundHandler->startSound(
-                    soundId,
-                    loops,
-                    offset, // in seconds
-                    0, // envelopes
-                    true // allow multiple instances (checked)
-                    );
-    }
-}
-
-void
-Sound_as::stop(int si)
-{
-    if ( ! _soundHandler )
-    {
-        log_error("No sound handler, nothing to stop...");
-        return;
-    }
-
-    // stop the sound
-    if (si < 0)
-    {
-        if (externalSound)
-        {
-            if ( _inputStream )
-            {
-                _soundHandler->unplugInputStream(_inputStream);
-                _inputStream=0;
-            }
-        }
-        else
-        {
-            _soundHandler->stop_sound(soundId);
-        }
-    }
-    else
-    {
-        _soundHandler->stop_sound(si);
-    }
-}
-
-unsigned int
-Sound_as::getDuration()
-{
-    if ( ! _soundHandler )
-    {
-        log_error("No sound handler, can't check duration...");
-        return 0;
-    }
-
-    // If this is a event sound get the info from the soundhandler
-    if (!externalSound)
-    {
-        return _soundHandler->get_duration(soundId);
-    }
-
-    // If we have a media parser (we'd do for an externalSound)
-    // try fetching duration from it
-    if ( _mediaParser )
-    {
-        media::AudioInfo* info = _mediaParser->getAudioInfo();
-        if ( info )
-        {
-            return info->duration;
-        }
-    }
-
-    return 0;
-}
-
-unsigned int
-Sound_as::getPosition()
-{
-    if ( ! _soundHandler )
-    {
-        log_error("No sound handler, can't check position (we're likely not 
playing anyway)...");
-        return 0;
-    }
-
-    // If this is a event sound get the info from the soundhandler
-    if (!externalSound)
-    {
-        return _soundHandler->tell(soundId);
-    }
-
-    if ( _mediaParser )
-    {
-        boost::uint64_t ts;
-        if ( _mediaParser->nextAudioFrameTimestamp(ts) )
-        {
-            return ts;
-        }
-    }
-
-    return 0;
-
-}
-
-
-unsigned int
-Sound_as::getAudio(boost::int16_t* samples, unsigned int nSamples, bool& atEOF)
-{
-    boost::uint8_t* stream = reinterpret_cast<boost::uint8_t*>(samples);
-    int len = nSamples*2;
-
-    //GNASH_REPORT_FUNCTION;
-
-    while (len)
-    {
-        if ( ! _leftOverData )
-        {
-            bool parsingComplete = _mediaParser->parsingCompleted(); // check 
*before* calling nextAudioFrame
-            std::auto_ptr<media::EncodedAudioFrame> frame = 
_mediaParser->nextAudioFrame();
-            if ( ! frame.get() )
-            {
-                // just wait some more if parsing isn't complete yet
-                if ( ! parsingComplete )
-                {
-                    //log_debug("Parsing not complete and no more audio frames 
in input, try again later");
-                    break;
-                }
-
-                // or detach and stop here...
-                // (should really honour loopings if any,
-                // but that should be only done for non-streaming sound!)
-                //log_debug("Parsing complete and no more audio frames in 
input, detaching");
-
-                markSoundCompleted(true);
-
-                // Setting atEOF to true will detach us.
-                // We should change _inputStream, but need thread safety!
-                // So on probeAudio, if _soundCompleted is set
-                // we'll consider ourselves detached already and set
-                // _inputStream to zero
-                atEOF=true;
-                return nSamples-(len/2);
-            }
-
-            // if we've been asked to start at a specific time, skip
-            // any frame with earlier timestamp
-            if ( frame->timestamp < _startTime )
-            {
-                //log_debug("This audio frame timestamp (%d) < requested start 
time (%d)", frame->timestamp, _startTime);
-                continue;
-            }
-
-            _leftOverData.reset( _audioDecoder->decode(*frame, _leftOverSize) 
);
-            _leftOverPtr = _leftOverData.get();
-            if ( ! _leftOverData )
-            {
-                log_error("No samples decoded from input of %d bytes", 
frame->dataSize);
-                continue;
-            }
-
-            //log_debug(" decoded %d bytes of audio", _leftOverSize);
-        }
-
-        assert( !(_leftOverSize%2) );
-
-        int n = std::min<int>(_leftOverSize, len);
-        //log_debug(" consuming %d bytes of decoded audio", n);
-
-        std::copy(_leftOverPtr, _leftOverPtr+n, stream);
-
-        stream += n;
-        _leftOverPtr += n;
-        _leftOverSize -= n;
-        len -= n;
-
-        if (_leftOverSize == 0)
-        {
-            _leftOverData.reset();
-            _leftOverPtr = 0;
-        }
-
-    }
-
-    // drop any queued video frame
-    while (_mediaParser->nextVideoFrame().get()) {};
-
-    atEOF=false;
-    return nSamples-(len/2);
-}
-
-// audio callback is running in sound handler thread
-unsigned int
-Sound_as::getAudioWrapper(void* owner, boost::int16_t* samples,
-        unsigned int nSamples, bool& atEOF)
-{
-    Sound_as* so = static_cast<Sound_as*>(owner);
-    return so->getAudio(samples, nSamples, atEOF);
-}
-
-
-
-
-
-
-
-
-as_value
-sound_new(const fn_call& fn)
-{
-    Sound_as* sound_obj = new Sound_as();
-
-    if ( fn.nargs )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        if ( fn.nargs > 1 )
-        {
-            std::stringstream ss; fn.dump_args(ss);
-            log_aserror("new Sound(%d) : args after first one ignored", 
ss.str());
-        }
-        );
-
-        const as_value& arg0 = fn.arg(0);
-        if ( ! arg0.is_null() && ! arg0.is_undefined() )
-        {
-            as_object* obj = arg0.to_object().get();
-            DisplayObject* ch = obj ? obj->toDisplayObject() : 0;
-            IF_VERBOSE_ASCODING_ERRORS(
-            if ( ! ch )
-            {
-                std::stringstream ss; fn.dump_args(ss);
-                log_aserror("new Sound(%s) : first argument isn't null "
-                    "nor undefined, and doesn't cast to a DisplayObject. "
-                    "We'll take as an invalid DisplayObject ref.",
-                    ss.str());
-            }
-            );
-            sound_obj->attachCharacter(ch);
-        }
-    }
-       
-    return as_value(sound_obj);
-}
-
-as_value
-sound_start(const fn_call& fn)
-{
-    IF_VERBOSE_ACTION (
-    log_action(_("-- start sound"));
-    )
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-    int loop = 0;
-    int secondOffset = 0;
-
-    if (fn.nargs > 0) {
-        secondOffset = (int) fn.arg(0).to_number();
-
-        if (fn.nargs > 1) {
-            loop = (int) fn.arg(1).to_number() - 1;
-
-            // -1 means infinite playing of sound
-            // sanity check
-            loop = loop < 0 ? -1 : loop;
-        }
-    }
-    so->start(secondOffset, loop);
-    return as_value();
-}
-
-as_value
-sound_stop(const fn_call& fn)
-{
-    IF_VERBOSE_ACTION (
-    log_action(_("-- stop sound "));
-    )
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-
-    int si = -1;
-
-    if (fn.nargs > 0) {
-        const std::string& name = fn.arg(0).to_string();
-
-        // check the import.
-        const movie_definition* def = fn.callerDef;
-        assert(def);
-        boost::intrusive_ptr<ExportableResource> res = 
-            def->get_exported_resource(name);
-
-        if (!res)
-        {
-            IF_VERBOSE_MALFORMED_SWF(
-                log_swferror(_("import error: resource '%s' is not exported"),
-                    name);
-                );
-            return as_value();
-        }
-
-        sound_sample* ss = dynamic_cast<sound_sample*>(res.get());
-
-        if (ss != NULL)
-        {
-            si = ss->m_sound_handler_id;
-        }
-        else
-        {
-            log_error(_("sound sample is NULL (doesn't cast to 
sound_sample)"));
-            return as_value();
-        }
-
-    }
-    so->stop(si);
-    return as_value();
-}
-
-as_value
-sound_attachsound(const fn_call& fn)
-{
-    IF_VERBOSE_ACTION (
-    log_action(_("-- attach sound"));
-    )
-    if (fn.nargs < 1)
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("attach sound needs one argument"));
-            );
-        return as_value();
-    }
-
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-
-    const std::string& name = fn.arg(0).to_string();
-    if (name.empty()) {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("attachSound needs a non-empty string"));
-        );
-        return as_value();
-    }
-
-    // check the import.
-    // NOTE: we should be checking in the SWF containing the calling code
-    // (see 'winter bell' from orisinal morning sunshine for a testcase)
-    const movie_definition* def = fn.callerDef;
-    assert(def);
-    boost::intrusive_ptr<ExportableResource> res = 
-        def->get_exported_resource(name);
-    if (!res)
-    {
-        IF_VERBOSE_MALFORMED_SWF(
-            log_swferror(_("import error: resource '%s' is not exported"),
-                name);
-        );
-        return as_value();
-    }
-
-    int si = 0;
-    sound_sample* ss = dynamic_cast<sound_sample*>(res.get());
-
-    if (ss)
-    {
-        si = ss->m_sound_handler_id;
-    }
-    else
-    {
-        log_error(_("sound sample is NULL (doesn't cast to sound_sample)"));
-        return as_value();
-    }
-
-    // sanity check
-    assert(si >= 0);
-    so->attachSound(si, name);
-    return as_value();
-}
-
-as_value
-sound_getbytesloaded(const fn_call& fn)
-{
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-    long loaded = so->getBytesLoaded();
-    if (loaded < 0) return as_value();
-    return as_value(loaded);
-}
-
-as_value
-sound_getbytestotal(const fn_call& fn)
-{
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-    long total = so->getBytesTotal();
-    if (total < 0) return as_value();
-    return as_value(total);
-}
-
-as_value
-sound_getpan(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.getPan()") );
-    return as_value();
-}
-
-as_value
-sound_getDuration(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.getDuration()") );
-    return as_value();
-}
-
-as_value
-sound_setDuration(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.setDuration()") );
-    return as_value();
-}
-
-as_value
-sound_getPosition(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.getPosition()") );
-    return as_value();
-}
-
-as_value
-sound_setPosition(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.setPosition()") );
-    return as_value();
-}
-
-as_value
-sound_gettransform(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.getTransform()") );
-    return as_value();
-}
-
-as_value
-sound_getvolume(const fn_call& fn)
-{
-
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-
-    if ( fn.nargs )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        std::stringstream ss; fn.dump_args(ss);
-        log_aserror("Sound.getVolume(%s) : arguments ignored");
-        );
-    }
-
-    int volume;
-    if ( so->getVolume(volume) ) return as_value(volume);
-    return as_value();
-}
-
-as_value
-sound_loadsound(const fn_call& fn)
-{
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-
-    if (!fn.nargs)
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("Sound.loadSound() needs at least 1 argument"));
-            );
-        return as_value();      
-    }
-
-    std::string url = fn.arg(0).to_string();
-
-    bool streaming = false;
-    if ( fn.nargs > 1 )
-    {
-        streaming = fn.arg(1).to_bool();
-
-        IF_VERBOSE_ASCODING_ERRORS(
-        if ( fn.nargs > 2 )
-        {
-            std::stringstream ss; fn.dump_args(ss);
-            log_aserror(_("Sound.loadSound(%s): arguments after first 2 "
-                    "discarded"), ss.str());
-        }
-        );
-    }
-
-    so->loadSound(url, streaming);
-
-    return as_value();
-}
-
-as_value
-sound_setpan(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.setPan()") );
-    return as_value();
-}
-
-as_value
-sound_settransform(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.setTransform()") );
-    return as_value();
-}
-
-as_value
-sound_setvolume(const fn_call& fn)
-{
-    if (fn.nargs < 1)
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("set volume of sound needs one argument"));
-        );
-        return as_value();
-    }
-
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);    
-    int volume = (int) fn.arg(0).to_number();
-
-    so->setVolume(volume);
-    return as_value();
-}
-
-as_value
-sound_duration(const fn_call& fn)
-{
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-    return as_value(so->getDuration());
-}
-
-as_value
-checkPolicyFile_getset(const fn_call& /*fn*/)
-{
-    LOG_ONCE( log_unimpl ("Sound.checkPolicyFile") );
-    return as_value();
-}
-
-as_value
-sound_areSoundsInaccessible(const fn_call& /*fn*/)
-{
-    // TODO: I guess this would have to do with permissions (crossdomain stuff)
-    // more then capability.
-    // See http://www.actionscript.org/forums/showthread.php3?t=160028
-    // 
-    // naive test shows this always being undefined..
-    //
-    LOG_ONCE( log_unimpl ("Sound.areSoundsInaccessible()") );
-    return as_value();
-}
-
-as_value
-sound_position(const fn_call& fn)
-{
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
-
-    return as_value(so->getPosition());
-}
-
-void
-attachSoundInterface(as_object& o)
-{
-
-    int flags = as_prop_flags::dontEnum | 
-                as_prop_flags::dontDelete | 
-                as_prop_flags::readOnly;
-
-    o.init_member("attachSound", new builtin_function(sound_attachsound),
-            flags);
-    o.init_member("getPan", new builtin_function(sound_getpan), flags);
-    o.init_member("setPan", new builtin_function(sound_setpan), flags);
-    o.init_member("start", new builtin_function(sound_start), flags);
-    o.init_member("stop", new builtin_function(sound_stop), flags);
-    o.init_member("getTransform", new builtin_function(sound_gettransform),
-            flags);
-    o.init_member("setTransform", new builtin_function(sound_settransform),
-            flags);
-    o.init_member("getVolume", new builtin_function(sound_getvolume), flags);
-    o.init_member("setVolume", new builtin_function(sound_setvolume), flags);
-
-    int flagsn6 = flags | as_prop_flags::onlySWF6Up;
-
-    o.init_member("getDuration", 
-            new builtin_function(sound_getDuration), flagsn6);
-    o.init_member("setDuration", 
-            new builtin_function(sound_setDuration), flagsn6);
-    o.init_member("loadSound", new builtin_function(sound_loadsound), flagsn6);
-    o.init_member("getPosition", 
-            new builtin_function(sound_getPosition), flagsn6);
-    o.init_member("setPosition", 
-            new builtin_function(sound_setPosition), flagsn6);
-    o.init_member("getBytesLoaded", 
-            new builtin_function(sound_getbytesloaded), flagsn6);
-    o.init_member("getBytesTotal", 
-            new builtin_function(sound_getbytestotal), flagsn6);
-
-    int flagsn9 = as_prop_flags::dontEnum | 
-                  as_prop_flags::dontDelete | 
-                  as_prop_flags::readOnly | 
-                  as_prop_flags::onlySWF9Up;
-
-    o.init_member("areSoundsInaccessible", 
-            new builtin_function(sound_areSoundsInaccessible), flagsn9);
-
-    // Properties
-    //there's no such thing as an ID3 member (swfdec shows)
-    o.init_readonly_property("duration", &sound_duration);
-    o.init_readonly_property("position", &sound_position);
-
-    int fl_hp = as_prop_flags::dontEnum | as_prop_flags::dontDelete;
-
-    o.init_property("checkPolicyFile", &checkPolicyFile_getset, 
-            &checkPolicyFile_getset, fl_hp);
-
-}
-
-static as_object*
-getSoundInterface()
-{
-
-    static boost::intrusive_ptr<as_object> o;
-    if ( o == NULL )
-    {
-        o = new as_object(getObjectInterface());
-        attachSoundInterface(*o);
-
-        // TODO: make this an additional second arg to as_object(__proto__) 
ctor !
-        o->set_member_flags(NSV::PROP_uuPROTOuu, as_prop_flags::readOnly, 0);
-    }
-
-    return o.get();
-}
-
-// extern (used by Global.cpp)
-void
-Sound_as::init(as_object& global)
-{
-
-    // This is going to be the global Sound "class"/"function"
-    static boost::intrusive_ptr<builtin_function> cl;
-
-    if ( cl == NULL )
-    {
-        as_object* iface = getSoundInterface();
-        cl=new builtin_function(&sound_new, iface);
-        iface->set_member_flags(NSV::PROP_CONSTRUCTOR, 
as_prop_flags::readOnly);
-    }
-
-    // Register _global.String
-    global.init_member("Sound", cl.get());
-
-}
-
-/*private*/
-void
-Sound_as::startProbeTimer()
-{
-    _probeTimer = 1;
-    getVM().getRoot().addAdvanceCallback(this);
-}
-
-/*private*/
-void
-Sound_as::stopProbeTimer()
-{
-#ifdef GNASH_DEBUG_SOUND_AS
-    log_debug("stopProbeTimer called");
-#endif
-
-    if ( _probeTimer )
-    {
-        VM& vm = getVM();
-        vm.getRoot().removeAdvanceCallback(this);
-        log_debug(" sound callback removed");
-        _probeTimer = 0;
-    }
-}
-
-void
-Sound_as::advanceState()
-{
-    probeAudio();
-}
-
-/*private*/
-void
-Sound_as::probeAudio()
-{
-    if ( isAttached() )
-    {
-#ifdef GNASH_DEBUG_SOUND_AS
-        log_debug("Probing audio for end");
-#endif
-
-        boost::mutex::scoped_lock lock(_soundCompletedMutex);
-        if (_soundCompleted)
-        {
-            // when _soundCompleted is true we're
-            // NOT attached !
-            _mediaParser.reset(); // no use for this anymore...
-            _inputStream=0;
-            _soundCompleted=false;
-            stopProbeTimer();
-
-            // dispatch onSoundComplete 
-            callMethod(NSV::PROP_ON_SOUND_COMPLETE);
-        }
-    }
-    else
-    {
-#ifdef GNASH_DEBUG_SOUND_AS
-        log_debug("Probing audio for start");
-#endif
-
-        bool parsingCompleted = _mediaParser->parsingCompleted();
-        try {
-            _inputStream = attachAuxStreamerIfNeeded();
-        } catch (MediaException& e) {
-            assert(!_inputStream);
-            assert(!_audioDecoder.get());
-            log_error(_("Could not create audio decoder: %s"), e.what());
-            _mediaParser.reset(); // no use for this anymore...
-            stopProbeTimer();
-            return;
-        }
-
-        if ( ! _inputStream )
-        {
-            if ( parsingCompleted )
-            {
-                log_debug("No audio in Sound input.");
-                stopProbeTimer();
-                _mediaParser.reset(); // no use for this anymore...
-            }
-            else
-            {
-                // keep probing
-            }
-        }
-        else
-        {
-            // An audio decoder was constructed, good!
-            assert(_audioDecoder.get());
-        }
-    }
-}
-
-#ifdef GNASH_USE_GC
-void
-Sound_as::markReachableResources() const
-{
-    if ( _attachedCharacter ) _attachedCharacter->setReachable();
-    markAsObjectReachable();
-}
-#endif // GNASH_USE_GC
-
-void
-Sound_as::markSoundCompleted(bool completed)
-{
-    boost::mutex::scoped_lock lock(_soundCompletedMutex);
-    _soundCompleted=completed;
-}
-
-} // end of gnash namespace

=== removed file 'libcore/asobj/Sound_as.h'
--- a/libcore/asobj/Sound_as.h  2009-04-03 09:18:40 +0000
+++ b/libcore/asobj/Sound_as.h  1970-01-01 00:00:00 +0000
@@ -1,197 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-#ifndef GNASH_ASOBJ_SOUND_H
-#define GNASH_ASOBJ_SOUND_H
-
-#ifdef HAVE_CONFIG_H
-#include "gnashconfig.h"
-#endif
-
-#include "smart_ptr.h" // GNASH_USE_GC
-#include "impl.h"
-#include "as_object.h" // for inheritance
-
-#include <boost/scoped_ptr.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/thread/mutex.hpp>
-
-// Forward declarations
-namespace gnash {
-    class CharacterProxy;
-    namespace sound {
-        class sound_handler;
-        class InputStream;
-    }
-    namespace media {
-        class MediaHandler;
-        class MediaParser;
-        class AudioDecoder;
-    }
-}
-
-namespace gnash {
-
-// Forward declarations
-class fn_call;
-  
-class Sound_as : public as_object
-{
-
-public:
-
-    Sound_as();
-
-    ~Sound_as();
-
-    static void init(as_object& global);
-
-    /// Make this sound control the given DisplayObject
-    //
-    /// NOTE: 0 is accepted, to implement an "invalid"
-    ///       controller type.
-    ///
-    void attachCharacter(DisplayObject* attachedChar);
-
-    void attachSound(int si, const std::string& name);
-
-    /// Get number of bytes loaded from the external sound (if any)
-    long getBytesLoaded();
-
-    /// Get total number of bytes in the external sound being loaded
-    //
-    /// @return -1 if unknown
-    ///
-    long getBytesTotal();
-
-    void getPan();
-    void getTransform();
-
-    /// Get volume from associated resource
-    //
-    /// @return true of volume was obtained, false
-    ///         otherwise (for example if the associated
-    ///         DisplayObject was unloaded).
-    ///
-    bool getVolume(int& volume);
-    void setVolume(int volume);
-
-    void loadSound(const std::string& file, bool streaming);
-    void setPan();
-    void setTransform();
-    void start(int offset, int loops);
-    void stop(int si);
-    unsigned int getDuration();
-    unsigned int getPosition();
-
-    std::string soundName;  
-
-private:
-
-#ifdef GNASH_USE_GC
-    /// Mark all reachable resources of a Sound, for the GC
-    //
-    /// Reachable resources are:
-    /// - attached DisplayObject object (attachedCharacter)
-    ///
-    void markReachableResources() const;
-#endif // GNASH_USE_GC
-
-    bool _duration;
-    bool _id3;
-    bool _onID3;
-    bool _onLoad;
-    bool _onComplete;
-    bool _position;
-
-    boost::scoped_ptr<CharacterProxy> _attachedCharacter;
-    int soundId;
-    bool externalSound;
-    std::string externalURL;
-    bool isStreaming;
-
-    sound::sound_handler* _soundHandler;
-
-    media::MediaHandler* _mediaHandler;
-
-    boost::scoped_ptr<media::MediaParser> _mediaParser;
-
-    boost::scoped_ptr<media::AudioDecoder> _audioDecoder;
-
-    /// Number of milliseconds into the sound to start it
-    //
-    /// This is set by start()
-    boost::uint64_t _startTime;
-
-    boost::scoped_array<boost::uint8_t> _leftOverData;
-    boost::uint8_t* _leftOverPtr;
-    boost::uint32_t _leftOverSize;
-
-    /// This is a sound_handler::aux_streamer_ptr type.
-    static unsigned int getAudioWrapper(void *owner, boost::int16_t* samples,
-            unsigned int nSamples, bool& etEOF);
-
-    unsigned int getAudio(boost::int16_t* samples, unsigned int nSamples,
-            bool& atEOF);
-
-    /// The aux streamer for sound handler
-    sound::InputStream* _inputStream;
-
-    int remainingLoops;
-
-    /// Query media parser for audio info, create decoder and attach aux 
streamer
-    /// if found.
-    ///
-    /// @return  an InputStream* if audio found and aux streamer attached,
-    ///          0 if no audio found.
-    ///
-    /// May throw a MediaException if audio was found but
-    /// audio decoder could not be created
-    /// 
-    sound::InputStream* attachAuxStreamerIfNeeded();
-
-    /// Register a timer for audio info probing
-    void startProbeTimer();
-
-    /// Unregister the probe timer
-    void stopProbeTimer();
-
-    virtual void advanceState();
-
-    /// Probe audio
-    void probeAudio();
-
-    int _probeTimer;
-
-    bool _soundCompleted;
-
-    boost::mutex _soundCompletedMutex;
-
-    /// Thread-safe setter for _soundCompleted
-    void markSoundCompleted(bool completed);
-
-    /// Is this sound attached to the soundhandler?
-    bool isAttached() const {
-        return _inputStream!=0;
-    }
-};
-
-} // end of gnash namespace
-
-#endif
-

=== modified file 'libcore/asobj/flash.am'
--- a/libcore/asobj/flash.am    2009-06-09 18:42:51 +0000
+++ b/libcore/asobj/flash.am    2009-06-09 19:00:20 +0000
@@ -47,7 +47,6 @@
        asobj/PlayHead.cpp \
        asobj/Selection_as.cpp \
        asobj/Namespace_as.cpp \
-       asobj/Sound_as.cpp \
        asobj/System_as.cpp \
        asobj/TextFormat_as.cpp \
        asobj/MovieClipLoader.cpp\
@@ -77,7 +76,6 @@
        asobj/Number_as.h \
        asobj/PlayHead.h \
        asobj/Selection_as.h \
-       asobj/Sound_as.h \
        asobj/System_as.h \
        asobj/TextFormat_as.h \
        asobj/String_as.h \

=== modified file 'libcore/asobj/flash/media/Sound_as.cpp'
--- a/libcore/asobj/flash/media/Sound_as.cpp    2009-05-28 17:12:07 +0000
+++ b/libcore/asobj/flash/media/Sound_as.cpp    2009-06-09 17:32:44 +0000
@@ -23,16 +23,52 @@
 
 #include "media/Sound_as.h"
 #include "log.h"
+#include "sound_handler.h"
+#include "AudioDecoder.h"
+#include "MediaHandler.h"
+#include "sound_definition.h"
+#include "movie_root.h"
+#include "movie_definition.h"
 #include "fn_call.h"
+#include "GnashException.h" // for ActionException
+#include "builtin_function.h" // need builtin_function
 #include "smart_ptr.h" // for boost intrusive_ptr
-#include "builtin_function.h" // need builtin_function
-#include "GnashException.h" // for ActionException
+#include "Object.h"
+#include "VM.h"
+#include "namedStrings.h"
+#include "ExportableResource.h"
+#include "StreamProvider.h"
+
+#include <string>
+
+
 
 namespace gnash {
 
 // Forward declarations
 namespace {
-    as_value sound_load(const fn_call& fn);
+       as_value sound_new(const fn_call& fn);
+       as_value sound_attachsound(const fn_call& fn);
+       as_value sound_getbytesloaded(const fn_call& fn);
+       as_value sound_setPosition(const fn_call& fn);
+       as_value sound_areSoundsInaccessible(const fn_call& fn);
+       as_value sound_duration(const fn_call& fn);
+       as_value sound_position(const fn_call& fn);
+       as_value sound_getbytestotal(const fn_call& fn);
+       as_value sound_getpan(const fn_call& fn);
+       as_value sound_setpan(const fn_call& fn);
+       as_value sound_getDuration(const fn_call& fn);
+       as_value sound_setDuration(const fn_call& fn);
+       as_value sound_gettransform(const fn_call& fn);
+       as_value sound_getPosition(const fn_call& fn);
+       as_value sound_getvolume(const fn_call& fn);
+       as_value sound_loadsound(const fn_call& fn);
+       as_value sound_settransform(const fn_call& fn);
+       as_value sound_setvolume(const fn_call& fn);
+       as_value sound_start(const fn_call& fn);
+       as_value sound_stop(const fn_call& fn);
+       as_value checkPolicyFile_getset(const fn_call& fn);
+       as_value sound_load(const fn_call& fn);
     as_value sound_play(const fn_call& fn);
     as_value sound_complete(const fn_call& fn);
     as_value sound_id3(const fn_call& fn);
@@ -41,68 +77,1058 @@
     as_value sound_progress(const fn_call& fn);
     as_value sound_ctor(const fn_call& fn);
     void attachSoundInterface(as_object& o);
-    void attachSoundStaticInterface(as_object& o);
     as_object* getSoundInterface();
-
-}
-
-class Sound_as : public as_object
-{
-
-public:
-
-    Sound_as()
-        :
-        as_object(getSoundInterface())
-    {}
-};
+}
+
+Sound_as::Sound_as() 
+    :
+    as_object(getSoundInterface()),
+    _attachedCharacter(0),
+    soundId(-1),
+    externalSound(false),
+    isStreaming(false),
+    _soundHandler(_vm.getRoot().runInfo().soundHandler()),
+    _mediaHandler(media::MediaHandler::get()),
+    _startTime(0),
+    _leftOverData(),
+    _leftOverPtr(0),
+    _leftOverSize(0),
+    _inputStream(0),
+    remainingLoops(0),
+    _probeTimer(0),
+    _soundCompleted(false)
+{
+}
+
+Sound_as::~Sound_as()
+{
+    //GNASH_REPORT_FUNCTION;
+
+    if (_inputStream && _soundHandler)
+    {
+        _soundHandler->unplugInputStream(_inputStream);
+        _inputStream=0;
+    }
+
+}
 
 // extern (used by Global.cpp)
-void sound_class_init(as_object& global)
+void
+Sound_as::init(as_object& global)
 {
+
+    // This is going to be the global Sound "class"/"function"
     static boost::intrusive_ptr<builtin_function> cl;
 
-    if (!cl) {
-        cl = new builtin_function(&sound_ctor, getSoundInterface());
-        attachSoundStaticInterface(*cl);
+    if ( cl == NULL )
+    {
+        as_object* iface = getSoundInterface();
+        cl=new builtin_function(&sound_new, iface);
+        iface->set_member_flags(NSV::PROP_CONSTRUCTOR, 
as_prop_flags::readOnly);
     }
 
-    // Register _global.Sound
+    // Register _global.String
     global.init_member("Sound", cl.get());
-}
+
+}
+
+/*private*/
+void
+Sound_as::startProbeTimer()
+{
+    _probeTimer = 1;
+    getVM().getRoot().addAdvanceCallback(this);
+}
+
+/*private*/
+void
+Sound_as::stopProbeTimer()
+{
+#ifdef GNASH_DEBUG_SOUND_AS
+    log_debug("stopProbeTimer called");
+#endif
+
+    if ( _probeTimer )
+    {
+        VM& vm = getVM();
+        vm.getRoot().removeAdvanceCallback(this);
+        log_debug(" sound callback removed");
+        _probeTimer = 0;
+    }
+}
+
+void
+Sound_as::advanceState()
+{
+    probeAudio();
+}
+
+/*private*/
+void
+Sound_as::probeAudio()
+{
+    if ( isAttached() )
+    {
+#ifdef GNASH_DEBUG_SOUND_AS
+        log_debug("Probing audio for end");
+#endif
+
+        boost::mutex::scoped_lock lock(_soundCompletedMutex);
+        if (_soundCompleted)
+        {
+            // when _soundCompleted is true we're
+            // NOT attached !
+            _mediaParser.reset(); // no use for this anymore...
+            _inputStream=0;
+            _soundCompleted=false;
+            stopProbeTimer();
+
+            // dispatch onSoundComplete 
+            callMethod(NSV::PROP_ON_SOUND_COMPLETE);
+        }
+    }
+    else
+    {
+#ifdef GNASH_DEBUG_SOUND_AS
+        log_debug("Probing audio for start");
+#endif
+
+        bool parsingCompleted = _mediaParser->parsingCompleted();
+        try {
+            _inputStream = attachAuxStreamerIfNeeded();
+        } catch (MediaException& e) {
+            assert(!_inputStream);
+            assert(!_audioDecoder.get());
+            log_error(_("Could not create audio decoder: %s"), e.what());
+            _mediaParser.reset(); // no use for this anymore...
+            stopProbeTimer();
+            return;
+        }
+
+        if ( ! _inputStream )
+        {
+            if ( parsingCompleted )
+            {
+                log_debug("No audio in Sound input.");
+                stopProbeTimer();
+                _mediaParser.reset(); // no use for this anymore...
+            }
+            else
+            {
+                // keep probing
+            }
+        }
+        else
+        {
+            // An audio decoder was constructed, good!
+            assert(_audioDecoder.get());
+        }
+    }
+}
+
+#ifdef GNASH_USE_GC
+void
+Sound_as::markReachableResources() const
+{
+    if ( _attachedCharacter ) _attachedCharacter->setReachable();
+    markAsObjectReachable();
+}
+#endif // GNASH_USE_GC
+
+void
+Sound_as::markSoundCompleted(bool completed)
+{
+    boost::mutex::scoped_lock lock(_soundCompletedMutex);
+    _soundCompleted=completed;
+}
+
+void
+Sound_as::attachCharacter(DisplayObject* attachTo) 
+{
+    _attachedCharacter.reset(new CharacterProxy(attachTo));
+}
+
+void
+Sound_as::attachSound(int si, const std::string& name)
+{
+    soundId = si;
+    soundName = name;
+}
+
+long
+Sound_as::getBytesLoaded()
+{
+    if ( _mediaParser ) return _mediaParser->getBytesLoaded();
+    return -1;
+}
+
+long
+Sound_as::getBytesTotal()
+{
+    if ( _mediaParser ) return _mediaParser->getBytesTotal();
+    return -1;
+}
+
+void
+Sound_as::getPan()
+{
+    LOG_ONCE(log_unimpl(__FUNCTION__));
+}
+
+void
+Sound_as::getTransform()
+{
+    LOG_ONCE(log_unimpl(__FUNCTION__));
+}
+
+bool
+Sound_as::getVolume(int& volume)
+{
+    // TODO: check what takes precedence in case we
+    //       have both an attached DisplayObject *and*
+    //       some other sound...
+    //
+    if ( _attachedCharacter )
+    {
+        //log_debug("Sound has an attached DisplayObject");
+        DisplayObject* ch = _attachedCharacter->get();
+        if ( ! ch )
+        {
+            log_debug("Character attached to Sound was unloaded and "
+                    "couldn't rebind");
+            return false;
+        }
+        volume = ch->getVolume();
+        return true;
+    }
+    //else log_debug("Sound has NO attached DisplayObject, _soundHandler is 
%p, soundId is %d", _soundHandler, soundId);
+
+    // If we're not attached to a DisplayObject we'll need to query
+    // sound_handler for volume. If we have no sound handler, we
+    // can't do much, so we'll return false
+    if (!_soundHandler)
+    {
+        log_debug("We have no sound handler here...");
+        return false;
+    }
+
+    // Now, we may be controlling a specific sound or
+    // the final output as a whole.
+    // If soundId is -1 we're controlling as a whole
+    //
+    if ( soundId == -1 )
+    {
+        volume = _soundHandler->getFinalVolume();
+    }
+    else
+    {
+        volume = _soundHandler->get_volume(soundId);
+    }
+
+    return true;
+}
+
+void
+Sound_as::loadSound(const std::string& file, bool streaming)
+{
+    if ( ! _mediaHandler || ! _soundHandler ) 
+    {
+        log_debug("No media or sound handlers, won't load any sound");
+        return;
+    }
+
+    /// If we are already streaming stop doing so as we'll replace
+    /// the media parser
+    if ( _inputStream )
+    {
+        _soundHandler->unplugInputStream(_inputStream);
+        _inputStream = 0;
+    }
+
+    /// Delete any media parser being used (make sure we have detached!)
+    _mediaParser.reset();
+
+    /// Start at offset 0, in case a previous ::start() call
+    /// changed that.
+    _startTime=0;
+
+    const movie_root& mr = _vm.getRoot();
+    URL url(file, mr.runInfo().baseURL());
+
+    const RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+
+    const StreamProvider& streamProvider = mr.runInfo().streamProvider();
+    std::auto_ptr<IOChannel> inputStream(streamProvider.getStream(url,
+                rcfile.saveStreamingMedia()));
+    if ( ! inputStream.get() )
+    {
+        log_error( _("Gnash could not open this url: %s"), url );
+        return;
+    }
+
+    externalSound = true;
+    isStreaming = streaming;
+
+    
_mediaParser.reset(_mediaHandler->createMediaParser(inputStream).release());
+    if ( ! _mediaParser )
+    {
+        log_error(_("Unable to create parser for Sound at %s"), url);
+        // not necessarely correct, the stream might have been found...
+        return;
+    }
+
+    // TODO: use global _soundbuftime
+    _mediaParser->setBufferTime(60000); // one minute buffer... should be fine
+
+    if ( isStreaming )
+    {
+        startProbeTimer();
+    }
+    else
+    {
+        LOG_ONCE(log_unimpl("Non-streaming Sound.loadSound: will behave "
+                    "as a streaming one"));
+        // if not streaming, we'll probe on .start()
+    }
+}
+
+sound::InputStream*
+Sound_as::attachAuxStreamerIfNeeded()
+{
+    media::AudioInfo* audioInfo =  _mediaParser->getAudioInfo();
+    if (!audioInfo) return 0;
+
+    // the following may throw an exception
+    
_audioDecoder.reset(_mediaHandler->createAudioDecoder(*audioInfo).release());
+
+    // start playing ASAP, a call to ::start will just change _startTime
+#ifdef GNASH_DEBUG_SOUND_AS
+    log_debug("Attaching the aux streamer");
+#endif
+    return _soundHandler->attach_aux_streamer(getAudioWrapper, (void*) this);
+}
+
+void
+Sound_as::setPan()
+{
+    LOG_ONCE(log_unimpl(__FUNCTION__));
+}
+
+void
+Sound_as::setTransform()
+{
+    LOG_ONCE(log_unimpl(__FUNCTION__));
+}
+
+void
+Sound_as::setVolume(int volume)
+{
+    // TODO: check what takes precedence in case we
+    //       have both an attached DisplayObject *and*
+    //       some other sound...
+    //
+    if ( _attachedCharacter )
+    {
+        DisplayObject* ch = _attachedCharacter->get();
+        if ( ! ch )
+        {
+            log_debug("Character attached to Sound was unloaded and "
+                    "couldn't rebind");
+            return;
+        }
+        ch->setVolume(volume);
+        return;
+    }
+
+    // If we're not attached to a DisplayObject we'll need to use
+    // sound_handler for volume. If we have no sound handler, we
+    // can't do much, so we'll just return
+    if (!_soundHandler)
+    {
+        return;
+    }
+
+    // Now, we may be controlling a specific sound or
+    // the final output as a whole.
+    // If soundId is -1 we're controlling as a whole
+    //
+    if ( soundId == -1 )
+    {
+        _soundHandler->setFinalVolume(volume);
+    }
+    else
+    {
+        _soundHandler->set_volume(soundId, volume);
+    }
+}
+
+void
+Sound_as::start(int offset, int loops)
+{
+    if ( ! _soundHandler )
+    {
+        log_error("No sound handler, nothing to start...");
+        return;
+    }
+
+    if (externalSound)
+    {
+        if ( ! _mediaParser )
+        {
+            log_error("No MediaParser initialized, can't start an external 
sound");
+            return;
+        }
+
+        if (offset > 0)
+        {
+            _startTime=offset*1000;
+            boost::uint32_t seekms = boost::uint32_t(offset*1000);
+            // TODO: boost::mutex::scoped_lock parserLock(_parserMutex);
+            _mediaParser->seek(seekms); // well, we try...
+        }
+
+        if (isStreaming)
+        {
+            IF_VERBOSE_ASCODING_ERRORS(
+            log_aserror(_("Sound.start() has no effect on a streaming Sound"));
+            );
+            return;
+        }
+
+        // Save how many loops to do (not when streaming)
+        if (loops > 0)
+        {
+            remainingLoops = loops;
+        }
+
+        // TODO: we should really be waiting for the sound to be fully
+        //       loaded before starting to play it (!isStreaming case)
+        startProbeTimer();
+
+        //if ( ! _inputStream ) {
+        //  _inputStream=_soundHandler->attach_aux_streamer(getAudioWrapper, 
(void*) this);
+        //}
+    }
+    else
+    {
+        _soundHandler->startSound(
+                    soundId,
+                    loops,
+                    offset, // in seconds
+                    0, // envelopes
+                    true // allow multiple instances (checked)
+                    );
+    }
+}
+
+void
+Sound_as::stop(int si)
+{
+    if ( ! _soundHandler )
+    {
+        log_error("No sound handler, nothing to stop...");
+        return;
+    }
+
+    // stop the sound
+    if (si < 0)
+    {
+        if (externalSound)
+        {
+            if ( _inputStream )
+            {
+                _soundHandler->unplugInputStream(_inputStream);
+                _inputStream=0;
+            }
+        }
+        else
+        {
+            _soundHandler->stop_sound(soundId);
+        }
+    }
+    else
+    {
+        _soundHandler->stop_sound(si);
+    }
+}
+
+unsigned int
+Sound_as::getDuration()
+{
+    if ( ! _soundHandler )
+    {
+        log_error("No sound handler, can't check duration...");
+        return 0;
+    }
+
+    // If this is a event sound get the info from the soundhandler
+    if (!externalSound)
+    {
+        return _soundHandler->get_duration(soundId);
+    }
+
+    // If we have a media parser (we'd do for an externalSound)
+    // try fetching duration from it
+    if ( _mediaParser )
+    {
+        media::AudioInfo* info = _mediaParser->getAudioInfo();
+        if ( info )
+        {
+            return info->duration;
+        }
+    }
+
+    return 0;
+}
+
+unsigned int
+Sound_as::getPosition()
+{
+    if ( ! _soundHandler )
+    {
+        log_error("No sound handler, can't check position (we're likely not 
playing anyway)...");
+        return 0;
+    }
+
+    // If this is a event sound get the info from the soundhandler
+    if (!externalSound)
+    {
+        return _soundHandler->tell(soundId);
+    }
+
+    if ( _mediaParser )
+    {
+        boost::uint64_t ts;
+        if ( _mediaParser->nextAudioFrameTimestamp(ts) )
+        {
+            return ts;
+        }
+    }
+
+    return 0;
+
+}
+
+
+unsigned int
+Sound_as::getAudio(boost::int16_t* samples, unsigned int nSamples, bool& atEOF)
+{
+    boost::uint8_t* stream = reinterpret_cast<boost::uint8_t*>(samples);
+    int len = nSamples*2;
+
+    //GNASH_REPORT_FUNCTION;
+
+    while (len)
+    {
+        if ( ! _leftOverData )
+        {
+            bool parsingComplete = _mediaParser->parsingCompleted(); // check 
*before* calling nextAudioFrame
+            std::auto_ptr<media::EncodedAudioFrame> frame = 
_mediaParser->nextAudioFrame();
+            if ( ! frame.get() )
+            {
+                // just wait some more if parsing isn't complete yet
+                if ( ! parsingComplete )
+                {
+                    //log_debug("Parsing not complete and no more audio frames 
in input, try again later");
+                    break;
+                }
+
+                // or detach and stop here...
+                // (should really honour loopings if any,
+                // but that should be only done for non-streaming sound!)
+                //log_debug("Parsing complete and no more audio frames in 
input, detaching");
+
+                markSoundCompleted(true);
+
+                // Setting atEOF to true will detach us.
+                // We should change _inputStream, but need thread safety!
+                // So on probeAudio, if _soundCompleted is set
+                // we'll consider ourselves detached already and set
+                // _inputStream to zero
+                atEOF=true;
+                return nSamples-(len/2);
+            }
+
+            // if we've been asked to start at a specific time, skip
+            // any frame with earlier timestamp
+            if ( frame->timestamp < _startTime )
+            {
+                //log_debug("This audio frame timestamp (%d) < requested start 
time (%d)", frame->timestamp, _startTime);
+                continue;
+            }
+
+            _leftOverData.reset( _audioDecoder->decode(*frame, _leftOverSize) 
);
+            _leftOverPtr = _leftOverData.get();
+            if ( ! _leftOverData )
+            {
+                log_error("No samples decoded from input of %d bytes", 
frame->dataSize);
+                continue;
+            }
+
+            //log_debug(" decoded %d bytes of audio", _leftOverSize);
+        }
+
+        assert( !(_leftOverSize%2) );
+
+        int n = std::min<int>(_leftOverSize, len);
+        //log_debug(" consuming %d bytes of decoded audio", n);
+
+        std::copy(_leftOverPtr, _leftOverPtr+n, stream);
+
+        stream += n;
+        _leftOverPtr += n;
+        _leftOverSize -= n;
+        len -= n;
+
+        if (_leftOverSize == 0)
+        {
+            _leftOverData.reset();
+            _leftOverPtr = 0;
+        }
+
+    }
+
+    // drop any queued video frame
+    while (_mediaParser->nextVideoFrame().get()) {};
+
+    atEOF=false;
+    return nSamples-(len/2);
+}
+
+// audio callback is running in sound handler thread
+unsigned int
+Sound_as::getAudioWrapper(void* owner, boost::int16_t* samples,
+        unsigned int nSamples, bool& atEOF)
+{
+    Sound_as* so = static_cast<Sound_as*>(owner);
+    return so->getAudio(samples, nSamples, atEOF);
+}
+
 
 namespace {
 
 void
 attachSoundInterface(as_object& o)
 {
-    o.init_member("load", new builtin_function(sound_load));
-    o.init_member("play", new builtin_function(sound_play));
-    o.init_member("complete", new builtin_function(sound_complete));
-    o.init_member("id3", new builtin_function(sound_id3));
-    o.init_member("ioError", new builtin_function(sound_ioError));
-    o.init_member("open", new builtin_function(sound_open));
-    o.init_member("progress", new builtin_function(sound_progress));
-}
-
-void
-attachSoundStaticInterface(as_object& o)
-{
-
-}
+
+    int flags = as_prop_flags::dontEnum | 
+                as_prop_flags::dontDelete | 
+                as_prop_flags::readOnly;
+
+    o.init_member("attachSound", new builtin_function(sound_attachsound),
+            flags);
+    o.init_member("getPan", new builtin_function(sound_getpan), flags);
+    o.init_member("setPan", new builtin_function(sound_setpan), flags);
+    o.init_member("start", new builtin_function(sound_start), flags);
+    o.init_member("stop", new builtin_function(sound_stop), flags);
+    o.init_member("getTransform", new builtin_function(sound_gettransform),
+            flags);
+    o.init_member("setTransform", new builtin_function(sound_settransform),
+            flags);
+    o.init_member("getVolume", new builtin_function(sound_getvolume), flags);
+    o.init_member("setVolume", new builtin_function(sound_setvolume), flags);
+
+    int flagsn6 = flags | as_prop_flags::onlySWF6Up;
+
+    o.init_member("getDuration", 
+            new builtin_function(sound_getDuration), flagsn6);
+    o.init_member("setDuration", 
+            new builtin_function(sound_setDuration), flagsn6);
+    o.init_member("loadSound", new builtin_function(sound_loadsound), flagsn6);
+    o.init_member("getPosition", 
+            new builtin_function(sound_getPosition), flagsn6);
+    o.init_member("setPosition", 
+            new builtin_function(sound_setPosition), flagsn6);
+    o.init_member("getBytesLoaded", 
+            new builtin_function(sound_getbytesloaded), flagsn6);
+    o.init_member("getBytesTotal", 
+            new builtin_function(sound_getbytestotal), flagsn6);
+
+    int flagsn9 = as_prop_flags::dontEnum | 
+                  as_prop_flags::dontDelete | 
+                  as_prop_flags::readOnly | 
+                  as_prop_flags::onlySWF9Up;
+
+    o.init_member("areSoundsInaccessible", 
+            new builtin_function(sound_areSoundsInaccessible), flagsn9);
+
+    // Properties
+    //there's no such thing as an ID3 member (swfdec shows)
+    o.init_readonly_property("duration", &sound_duration);
+    o.init_readonly_property("position", &sound_position);
+
+    int fl_hp = as_prop_flags::dontEnum | as_prop_flags::dontDelete;
+
+    o.init_property("checkPolicyFile", &checkPolicyFile_getset, 
+            &checkPolicyFile_getset, fl_hp);
+}
+
 
 as_object*
 getSoundInterface()
 {
     static boost::intrusive_ptr<as_object> o;
-    if ( ! o ) {
-        o = new as_object();
+    if ( o == NULL )
+    {
+        o = new as_object(getObjectInterface());
         attachSoundInterface(*o);
+
+        // TODO: make this an additional second arg to as_object(__proto__) 
ctor !
+        o->set_member_flags(NSV::PROP_uuPROTOuu, as_prop_flags::readOnly, 0);
     }
+
     return o.get();
 }
 
 as_value
+sound_new(const fn_call& fn)
+{
+    Sound_as* sound_obj = new Sound_as();
+
+    if ( fn.nargs )
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        if ( fn.nargs > 1 )
+        {
+            std::stringstream ss; fn.dump_args(ss);
+            log_aserror("new Sound(%d) : args after first one ignored", 
ss.str());
+        }
+        );
+
+        const as_value& arg0 = fn.arg(0);
+        if ( ! arg0.is_null() && ! arg0.is_undefined() )
+        {
+            as_object* obj = arg0.to_object().get();
+            DisplayObject* ch = obj ? obj->toDisplayObject() : 0;
+            IF_VERBOSE_ASCODING_ERRORS(
+            if ( ! ch )
+            {
+                std::stringstream ss; fn.dump_args(ss);
+                log_aserror("new Sound(%s) : first argument isn't null "
+                    "nor undefined, and doesn't cast to a DisplayObject. "
+                    "We'll take as an invalid DisplayObject ref.",
+                    ss.str());
+            }
+            );
+            sound_obj->attachCharacter(ch);
+        }
+    }
+       
+    return as_value(sound_obj);
+}
+
+as_value
+sound_start(const fn_call& fn)
+{
+    IF_VERBOSE_ACTION (
+    log_action(_("-- start sound"));
+    )
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    int loop = 0;
+    int secondOffset = 0;
+
+    if (fn.nargs > 0) {
+        secondOffset = (int) fn.arg(0).to_number();
+
+        if (fn.nargs > 1) {
+            loop = (int) fn.arg(1).to_number() - 1;
+
+            // -1 means infinite playing of sound
+            // sanity check
+            loop = loop < 0 ? -1 : loop;
+        }
+    }
+    so->start(secondOffset, loop);
+    return as_value();
+}
+
+as_value
+sound_stop(const fn_call& fn)
+{
+    IF_VERBOSE_ACTION (
+    log_action(_("-- stop sound "));
+    )
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+
+    int si = -1;
+
+    if (fn.nargs > 0) {
+        const std::string& name = fn.arg(0).to_string();
+
+        // check the import.
+        const movie_definition* def = fn.callerDef;
+        assert(def);
+        boost::intrusive_ptr<ExportableResource> res = 
+            def->get_exported_resource(name);
+
+        if (!res)
+        {
+            IF_VERBOSE_MALFORMED_SWF(
+                log_swferror(_("import error: resource '%s' is not exported"),
+                    name);
+                );
+            return as_value();
+        }
+
+        sound_sample* ss = dynamic_cast<sound_sample*>(res.get());
+
+        if (ss != NULL)
+        {
+            si = ss->m_sound_handler_id;
+        }
+        else
+        {
+            log_error(_("sound sample is NULL (doesn't cast to 
sound_sample)"));
+            return as_value();
+        }
+
+    }
+    so->stop(si);
+    return as_value();
+}
+
+as_value
+sound_attachsound(const fn_call& fn)
+{
+    IF_VERBOSE_ACTION (
+    log_action(_("-- attach sound"));
+    )
+    if (fn.nargs < 1)
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("attach sound needs one argument"));
+            );
+        return as_value();
+    }
+
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+
+    const std::string& name = fn.arg(0).to_string();
+    if (name.empty()) {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("attachSound needs a non-empty string"));
+        );
+        return as_value();
+    }
+
+    // check the import.
+    // NOTE: we should be checking in the SWF containing the calling code
+    // (see 'winter bell' from orisinal morning sunshine for a testcase)
+    const movie_definition* def = fn.callerDef;
+    assert(def);
+    boost::intrusive_ptr<ExportableResource> res = 
+        def->get_exported_resource(name);
+    if (!res)
+    {
+        IF_VERBOSE_MALFORMED_SWF(
+            log_swferror(_("import error: resource '%s' is not exported"),
+                name);
+        );
+        return as_value();
+    }
+
+    int si = 0;
+    sound_sample* ss = dynamic_cast<sound_sample*>(res.get());
+
+    if (ss)
+    {
+        si = ss->m_sound_handler_id;
+    }
+    else
+    {
+        log_error(_("sound sample is NULL (doesn't cast to sound_sample)"));
+        return as_value();
+    }
+
+    // sanity check
+    assert(si >= 0);
+    so->attachSound(si, name);
+    return as_value();
+}
+
+as_value
+sound_getbytesloaded(const fn_call& fn)
+{
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    long loaded = so->getBytesLoaded();
+    if (loaded < 0) return as_value();
+    return as_value(loaded);
+}
+
+as_value
+sound_getbytestotal(const fn_call& fn)
+{
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    long total = so->getBytesTotal();
+    if (total < 0) return as_value();
+    return as_value(total);
+}
+
+as_value
+sound_getpan(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.getPan()") );
+    return as_value();
+}
+
+as_value
+sound_getDuration(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.getDuration()") );
+    return as_value();
+}
+
+as_value
+sound_setDuration(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.setDuration()") );
+    return as_value();
+}
+
+as_value
+sound_getPosition(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.getPosition()") );
+    return as_value();
+}
+
+as_value
+sound_setPosition(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.setPosition()") );
+    return as_value();
+}
+
+as_value
+sound_gettransform(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.getTransform()") );
+    return as_value();
+}
+
+as_value
+sound_getvolume(const fn_call& fn)
+{
+
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+
+    if ( fn.nargs )
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        std::stringstream ss; fn.dump_args(ss);
+        log_aserror("Sound.getVolume(%s) : arguments ignored");
+        );
+    }
+
+    int volume;
+    if ( so->getVolume(volume) ) return as_value(volume);
+    return as_value();
+}
+
+as_value
+sound_loadsound(const fn_call& fn)
+{
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+
+    if (!fn.nargs)
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("Sound.loadSound() needs at least 1 argument"));
+            );
+        return as_value();      
+    }
+
+    std::string url = fn.arg(0).to_string();
+
+    bool streaming = false;
+    if ( fn.nargs > 1 )
+    {
+        streaming = fn.arg(1).to_bool();
+
+        IF_VERBOSE_ASCODING_ERRORS(
+        if ( fn.nargs > 2 )
+        {
+            std::stringstream ss; fn.dump_args(ss);
+            log_aserror(_("Sound.loadSound(%s): arguments after first 2 "
+                    "discarded"), ss.str());
+        }
+        );
+    }
+
+    so->loadSound(url, streaming);
+
+    return as_value();
+}
+
+as_value
+sound_setpan(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.setPan()") );
+    return as_value();
+}
+
+as_value
+sound_settransform(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.setTransform()") );
+    return as_value();
+}
+
+as_value
+sound_setvolume(const fn_call& fn)
+{
+    if (fn.nargs < 1)
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("set volume of sound needs one argument"));
+        );
+        return as_value();
+    }
+
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);    
+    int volume = (int) fn.arg(0).to_number();
+
+    so->setVolume(volume);
+    return as_value();
+}
+
+as_value
+sound_duration(const fn_call& fn)
+{
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    return as_value(so->getDuration());
+}
+
+as_value
+checkPolicyFile_getset(const fn_call& /*fn*/)
+{
+    LOG_ONCE( log_unimpl ("Sound.checkPolicyFile") );
+    return as_value();
+}
+
+as_value
+sound_areSoundsInaccessible(const fn_call& /*fn*/)
+{
+    // TODO: I guess this would have to do with permissions (crossdomain stuff)
+    // more then capability.
+    // See http://www.actionscript.org/forums/showthread.php3?t=160028
+    // 
+    // naive test shows this always being undefined..
+    //
+    LOG_ONCE( log_unimpl ("Sound.areSoundsInaccessible()") );
+    return as_value();
+}
+
+as_value
+sound_position(const fn_call& fn)
+{
+    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+
+    return as_value(so->getPosition());
+}
+
+
+as_value
 sound_load(const fn_call& fn)
 {
     boost::intrusive_ptr<Sound_as> ptr =

=== modified file 'libcore/asobj/flash/media/Sound_as.h'
--- a/libcore/asobj/flash/media/Sound_as.h      2009-05-28 17:29:17 +0000
+++ b/libcore/asobj/flash/media/Sound_as.h      2009-06-09 17:32:44 +0000
@@ -24,14 +24,169 @@
 #include "gnashconfig.h"
 #endif
 
+#include "smart_ptr.h" //GNASH_USE_GC
+#include "impl.h"
+#include "as_object.h"
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/thread/mutex.hpp>
 
 namespace gnash {
 
 // Forward declarations
-class as_object;
-
-/// Initialize the global Sound class
-void sound_class_init(as_object& global);
+class CharacterProxy;
+       namespace sound {
+               class sound_handler;
+               class InputStream;
+       }
+       namespace media {
+               class MediaHandler;
+               class MediaParser;
+               class AudioDecoder;
+       }
+       
+       class fn_call;
+       class as_object;
+       class Sound_as : public as_object
+       {
+
+       public:
+               Sound_as();
+               
+               ~Sound_as();
+               
+               static void init(as_object& global);
+               
+       /// Make this sound control the given DisplayObject
+    //
+    /// NOTE: 0 is accepted, to implement an "invalid"
+    ///       controller type.
+    ///
+    void attachCharacter(DisplayObject* attachedChar);
+
+    void attachSound(int si, const std::string& name);
+
+    /// Get number of bytes loaded from the external sound (if any)
+    long getBytesLoaded();
+
+    /// Get total number of bytes in the external sound being loaded
+    //
+    /// @return -1 if unknown
+    ///
+    long getBytesTotal();
+
+    void getPan();
+    void getTransform();
+
+    /// Get volume from associated resource
+    //
+    /// @return true of volume was obtained, false
+    ///         otherwise (for example if the associated
+    ///         DisplayObject was unloaded).
+    ///
+    bool getVolume(int& volume);
+    void setVolume(int volume);
+
+    void loadSound(const std::string& file, bool streaming);
+    void setPan();
+    void setTransform();
+    void start(int offset, int loops);
+    void stop(int si);
+    unsigned int getDuration();
+    unsigned int getPosition();
+
+    std::string soundName;  
+
+private:
+
+#ifdef GNASH_USE_GC
+    /// Mark all reachable resources of a Sound, for the GC
+    //
+    /// Reachable resources are:
+    /// - attached DisplayObject object (attachedCharacter)
+    ///
+    void markReachableResources() const;
+#endif // GNASH_USE_GC
+
+    bool _duration;
+    bool _id3;
+    bool _onID3;
+    bool _onLoad;
+    bool _onComplete;
+    bool _position;
+
+    boost::scoped_ptr<CharacterProxy> _attachedCharacter;
+    int soundId;
+    bool externalSound;
+    std::string externalURL;
+    bool isStreaming;
+
+    sound::sound_handler* _soundHandler;
+
+    media::MediaHandler* _mediaHandler;
+
+    boost::scoped_ptr<media::MediaParser> _mediaParser;
+
+    boost::scoped_ptr<media::AudioDecoder> _audioDecoder;
+
+    /// Number of milliseconds into the sound to start it
+    //
+    /// This is set by start()
+    boost::uint64_t _startTime;
+
+    boost::scoped_array<boost::uint8_t> _leftOverData;
+    boost::uint8_t* _leftOverPtr;
+    boost::uint32_t _leftOverSize;
+
+    /// This is a sound_handler::aux_streamer_ptr type.
+    static unsigned int getAudioWrapper(void *owner, boost::int16_t* samples,
+            unsigned int nSamples, bool& etEOF);
+
+    unsigned int getAudio(boost::int16_t* samples, unsigned int nSamples,
+            bool& atEOF);
+
+    /// The aux streamer for sound handler
+    sound::InputStream* _inputStream;
+
+    int remainingLoops;
+
+    /// Query media parser for audio info, create decoder and attach aux 
streamer
+    /// if found.
+    ///
+    /// @return  an InputStream* if audio found and aux streamer attached,
+    ///          0 if no audio found.
+    ///
+    /// May throw a MediaException if audio was found but
+    /// audio decoder could not be created
+    /// 
+    sound::InputStream* attachAuxStreamerIfNeeded();
+
+    /// Register a timer for audio info probing
+    void startProbeTimer();
+
+    /// Unregister the probe timer
+    void stopProbeTimer();
+
+    virtual void advanceState();
+
+    /// Probe audio
+    void probeAudio();
+
+    int _probeTimer;
+
+    bool _soundCompleted;
+
+    boost::mutex _soundCompletedMutex;
+
+    /// Thread-safe setter for _soundCompleted
+    void markSoundCompleted(bool completed);
+
+    /// Is this sound attached to the soundhandler?
+    bool isAttached() const {
+        return _inputStream!=0;
+    }
+       };
 
 } // gnash namespace
 

=== modified file 'libcore/asobj/flash/media/media.am'
--- a/libcore/asobj/flash/media/media.am        2009-06-07 18:12:15 +0000
+++ b/libcore/asobj/flash/media/media.am        2009-06-09 17:32:44 +0000
@@ -58,7 +58,7 @@
 endif
 
 if BUILD_SOUND_AS3
-# MEDIA_SOURCES += asobj/flash/media/Sound_as.cpp
+MEDIA_SOURCES += asobj/flash/media/Sound_as.cpp
 MEDIA_HEADERS += asobj/flash/media/Sound_as.h
 endif
 


reply via email to

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