resource loading bugs and new sound class
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 17 Jun 2010 21:40:46 +0000 (15:40 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 17 Jun 2010 21:40:46 +0000 (15:40 -0600)
src/GameLayer.cc
src/GameLayer.hh
src/Main.cc
src/moof/hash.hh
src/moof/resource.cc
src/moof/resource.hh
src/moof/sound.cc
src/moof/sound.hh
src/moof/timer.cc

index fcb77ed65cfa086be3e30f07e85cefde40c8af81..8299d638211f57db283bd2e74ae7413af070fff1 100644 (file)
@@ -80,15 +80,10 @@ void GameLayer::advanceScene(moof::settings& settings)
 GameLayer::GameLayer()
 {
        moof::log_info("about to load sound resource...");
-       music_ = moof::resource::load("NightFusionIntro.ogg");
-       if (music_)
-       {
-               music_->loop(true);
-               music_->enqueue("NightFusionLoop");
-       }
-       else moof::log_error("music not loaded");
-
-       //music_->position(moof::vector3(10.0, 5.0, 0.0));
+       music_.sample("NightFusionIntro.ogg");
+       music_.loop(true);
+       music_.enqueue("NightFusionLoop.ogg");
+       music_.position(moof::vector3(10.0, 5.0, 0.0));
 
        mThinkTimer.init(boost::bind(&GameLayer::thinkTimer, this),
                        0.1, moof::timer::repeat);
@@ -104,7 +99,7 @@ void GameLayer::did_add_to_view()
 {
        bool isMute = false;
        settings().get("nomusic", isMute);
-       if (!isMute) music_->play();
+       if (!isMute) music_.stream();
 
        loadSceneLoader();
        advanceScene(settings());               // load the first scene
@@ -218,12 +213,12 @@ bool GameLayer::handle_event(const moof::event& event)
                        {
                                state_.heroine->animation.startSequence("Flattened");
                                moof::log_info("thump!");
-                               //mPunchSound.play();
+                               punch_sound_.play();
                                return true;
                        }
                        else if (event.key.keysym.sym == SDLK_m)
                        {
-                               music_->toggle();
+                               music_.toggle();
                                return true;
                        }
                        else if (event.key.keysym.sym == SDLK_PAGEUP)
index 37eb8e07874dda42593d09e0efe7a1de2c305bd4..f2a70f97f43e0bbe1ca28f9ec395f769cc368013 100644 (file)
@@ -72,9 +72,9 @@ private:
        HudP                    mHud;
 
        //moof::sound_stream    mMusic;
-       //moof::sound           mPunchSound;
+       moof::sound     punch_sound_;
        
-       moof::sound_stream_handle       music_;
+       moof::sound             music_;
 
        moof::ray2              mRay;
        moof::line2             mLine;
index 6914c97df3525ed8ce7b7d206f8ee0b5c3598720..adda533e40fcc595e8cf5784d3be4de6361a9bad 100644 (file)
@@ -274,6 +274,7 @@ void goodbye()
 
 int main(int argc, char* argv[])
 {
+       // FIXME: This is temporary.
        moof::timer reloadTimer(boost::bind(&moof::resource::reload_as_needed),
                                                        SCALAR(2.0),
                                                        moof::timer::repeat);
index 09639124da09d110b55cde03e73c8869d07e94f1..ea63db152ad53f05bc7b3643b45437a5b13a2efc 100644 (file)
@@ -39,9 +39,10 @@ struct hash_function
                return (*this)(val.data(), val.length());
        }
 
-       unsigned operator () (int val) const
+       template <class T>
+       unsigned operator () (T val) const
        {
-               return val;
+               return static_cast<unsigned>(val);
        }
 };
 
index 359d1b4dcdfc35fcb3b2bb8d8a3394ecbee60925..314f80b5db81707e73b4cb3d91300f6d5b5a8ea0 100644 (file)
 
 namespace moof {
        
+void resource::print_types()
+{
+}
+
+void resource::manage_loader(const std::string& extension, loader_ptr& loader, bool set)
+{
+       static type_lookup lookup;
+
+       if (loader || set)
+       {
+               lookup[extension] = loader;
+       }
+       else
+       {
+               std::map<std::string,loader_ptr>::iterator it;
+               it = lookup.find(extension);
+               if (it != lookup.end()) loader = (*it).second;
+       }
+}
 
 static std::string search_paths_;
 
@@ -40,7 +59,8 @@ typedef boost::weak_ptr<resource> resource_weakptr;
 static hash<std::string,resource_weakptr,hash_function> resource_table_;
 
 // static member
-resource::type_lookup_ptr resource::type_lookup_;
+//resource::type_lookup_ptr resource::type_lookup_;
+//resource::type_lookup resource::type_lookup_;
 
 
 #ifdef USE_HOTLOADING
@@ -107,14 +127,15 @@ resource_ptr resource::load(const std::string& path)
 {
        std::string extension = stlplus::extension_part(path);
 
-       if (!find(path))
+       std::string path1 = find_file(path);
+       if (!find(path1))
        {
-               log_error("trying to load missing resource:", path);
+               log_error("trying to load missing resource:", path1);
                return resource_ptr();
        }
 
        hash<std::string,resource_weakptr,hash_function>::iterator it;
-       it = resource_table_.find(path);
+       it = resource_table_.find(path1);
        if (it != resource_table_.end())
        {
                resource_weakptr rsrc = (*it).second;
@@ -122,18 +143,18 @@ resource_ptr resource::load(const std::string& path)
                if (locked) return locked;
        }
 
-       std::map<std::string,loader_ptr>::iterator jt;
-       jt = type_lookup_->find(extension);
-       if (jt != type_lookup_->end())
+       loader_ptr loader;
+       manage_loader(extension, loader);
+       if (loader)
        {
-               resource_ptr rsrc((*jt).second->load(path));
-               rsrc->set_loader(path, (*jt).second);
-               resource_table_[path] = rsrc;
+               resource_ptr rsrc(loader->load(path1));
+               rsrc->set_loader(path1, loader);
+               resource_table_[path1] = rsrc;
 
 #ifdef USE_HOTLOADING
-               int wd = inotify_add_watch(monitor_fd_, path.c_str(), IN_MODIFY);
+               int wd = inotify_add_watch(monitor_fd_, path1.c_str(), IN_MODIFY);
                rsrc->set_watch_descriptor(wd);
-               monitor_lookup_[wd] = path;
+               monitor_lookup_[wd] = path1;
 #endif
 
                log_info("loaded", rsrc.get());
index 29ae114f9d4daa4cc1b5e0cd14d900d7611963fa..f8fd4f6327ee9b18ad47b6e0360e0c25115a5d1d 100644 (file)
@@ -88,9 +88,11 @@ public:
        template <class T>
        static void register_type(const std::string& extension)
        {
-               if (!type_lookup_) type_lookup_ = type_lookup_ptr(new type_lookup);
+               //if (!type_lookup_) type_lookup_ = type_lookup_ptr(new type_lookup);
                loader_ptr loader(new specific_loader<T>);
-               (*type_lookup_)[extension] = loader;
+               //(*type_lookup_)[extension] = loader;
+               //type_lookup_[extension] = loader;
+               manage_loader(extension, loader, true);
        }
 
        /**
@@ -101,7 +103,10 @@ public:
         */
        static void unregister_type(const std::string& extension)
        {
-               type_lookup_->erase(extension);
+               //type_lookup_.erase(extension);
+               //type_lookup_->erase(extension);
+               loader_ptr loader;
+               manage_loader(extension, loader, true);
        }
 
 
@@ -164,6 +169,8 @@ public:
         */
        static int reload_as_needed();
 
+       static void print_types();
+
 
 private:
 
@@ -188,6 +195,7 @@ private:
 
                virtual resource* load(const std::string& path)
                {
+                       log_info("loading resource of type ", typeid(T).name());
                        return new resource(new T(path));
                }
        };
@@ -212,7 +220,7 @@ private:
 
                virtual ~specific_unloader()
                {
-                       log_warning("unloading resource of type ", typeid(T).name());
+                       log_info("unloading resource of type ", typeid(T).name());
                        delete object_;
                }
 
@@ -238,8 +246,11 @@ private:
        loader_ptr              loader_;
 
        typedef std::map<std::string,loader_ptr> type_lookup;
-       typedef boost::shared_ptr<type_lookup> type_lookup_ptr;
-       static type_lookup_ptr type_lookup_;
+       //typedef boost::shared_ptr<type_lookup> type_lookup_ptr;
+       //static type_lookup_ptr type_lookup_;
+       //static type_lookup type_lookup_;
+
+       static void manage_loader(const std::string& extension, loader_ptr& loader, bool set = false);
 
 #ifdef USE_HOTLOADING
        int wd_;
index a1da62b8be10c9d1c2567f2931e90a1eb9841071..853c21a3d806f92bbb48fb91cb188b6d70e5c678 100644 (file)
 #include <string>
 
 #include <boost/algorithm/string.hpp>
+#include <boost/cstdint.hpp>
 #include <AL/al.h>
 #include <AL/alc.h>
 #include <vorbis/codec.h>
 #include <vorbis/vorbisfile.h>
 
+#include "hash.hh"
 #include "log.hh"
 #include "manager.hh"
 #include "sound.hh"
+#include "resource.hh"
 #include "timer.hh"
 
-#define BUF_SIZE (64 * 1024)
-//#define BUF_SIZE (5*2048)
+
+#ifndef BUF_SIZE
+#define BUF_SIZE       (4096)
+#endif
+
+#define NUM_BUFFERS (16)
+
 
 namespace moof {
 
 
-class impl
+class sound_backend
+{
+public:
+
+       sound_backend()
+       {
+               if (retain_count++ == 0)
+               {
+                       al_device  = alcOpenDevice(0);
+                       al_context = alcCreateContext(al_device, 0);
+                       if (!al_device || !al_context)
+                       {
+                               const char* error = alcGetString(al_device,
+                                                                                                alcGetError(al_device));
+                               log_error("audio subsystem initialization failure", error);
+                       }
+                       else
+                       {
+                               alcMakeContextCurrent(al_context);
+                               log_info << "opened sound device `"
+                                                << alcGetString(al_device,
+                                                                                ALC_DEFAULT_DEVICE_SPECIFIER)
+                                                << "'" << std::endl;
+                       }
+               }
+       }
+
+
+       sound_backend(const sound_backend& backend)
+       {
+               ++retain_count;
+       }
+
+       sound_backend& operator=(const sound_backend& backend)
+       {
+               ++retain_count;
+               return *this;
+       }
+
+       ~sound_backend()
+       {
+               if (--retain_count == 0)
+               {
+                       alcMakeContextCurrent(0);
+                       alcDestroyContext(al_context);
+                       alcCloseDevice(al_device);
+                       log_info("unloaded sound device ALSA");
+               }
+       }
+
+
+       static int                      retain_count;
+       static ALCdevice*       al_device;
+       static ALCcontext*      al_context;
+};
+
+int                    sound_backend::retain_count = 0;
+ALCdevice*     sound_backend::al_device;
+ALCcontext*    sound_backend::al_context;
+
+
+class sound_resource;
+typedef resource_handle<sound_resource> sound_handle;
+
+
+class sound_resource_loader
 {
 public:
        
-       impl()
+       sound_resource_loader()
        {
-               resource::register_type<sound_stream>("ogg");
+               resource::register_type<sound_resource>("ogg");
        }
 
-       ~impl()
+       ~sound_resource_loader()
        {
                resource::unregister_type("ogg");
        }
 };
-static impl impl;
 
+static sound_resource_loader loader;
 
-class sound::impl
+
+
+// SOUND BUFFER
+
+class buffer
 {
 public:
 
-       static ALenum get_audio_format(const vorbis_info* audioInfo)
+       typedef hash<ALuint,int,hash_function> retcount_lookup;
+
+
+       buffer() :
+               buffer_((ALuint)-1) {}
+
+       buffer(const void* data,
+                  ALsizei size,
+                  ALenum format,
+                  ALsizei freq)
        {
-               if (audioInfo->channels == 1) return AL_FORMAT_MONO16;
-               else                                              return AL_FORMAT_STEREO16;
+               alGenBuffers(1, &buffer_);
+               alBufferData(buffer_, format, data, size, freq);
+
+               retain_counts_[buffer_] = 1;
+               log_warning("ctor buffer:", buffer_);
        }
-       
 
-       class buffer;
-       typedef boost::shared_ptr<buffer> buffer_ptr;
-       
-       class buffer : public manager<buffer>
+       buffer(const buffer& buf)
        {
-       public:
+               buffer_ = buf.buffer_;
+               retain();
+       }
 
-               buffer() :
-                       buffer_(-1)
+       buffer& operator = (const buffer& buf)
+       {
+               buffer_ = buf.buffer_;
+               retain();
+               return *this;
+       }
+
+       ~buffer()
+       {
+               release();
+       }
+
+
+       void queue(ALuint source) const
+       {
+               if (*this)
                {
-                       mOggStream.datasource = 0;
+                       alSourceQueueBuffers(source, 1, &buffer_);
+                       retain();
+                       log_warning("queued buffer:", buffer_);
                }
+       }
+
+       static buffer unqueue(ALuint source)
+       {
+               ALuint buf = (ALuint)-1;
+               alSourceUnqueueBuffers(source, 1, &buf);
+               log_warning("unqueued buffer:", buf);
+               return buffer(buf);
+       }
+
+       void set(ALuint source) const
+       {
+               log_warning("set buffer:", buffer_);
+               if (*this) alSourcei(source, AL_BUFFER, buffer_);
+       }
+
+       operator bool () const
+       {
+               return buffer_ != (ALuint)-1;
+       }
+
+
+private:
 
-               ~buffer()
+       explicit buffer(ALuint buf) :
+               buffer_(buf) {}
+
+
+       void retain() const
+       {
+               retcount_lookup::iterator it = retain_counts_.find(buffer_);
+               if (it.valid()) ++it->second;
+       }
+
+       void release() const
+       {
+               retcount_lookup::iterator it = retain_counts_.find(buffer_);
+               if (it.valid() && --it->second <= 0)
                {
-                       if (mOggStream.datasource)
-                       {
-                               ov_clear(&mOggStream);
-                       }
-                       if (int(buffer_) != -1) alDeleteBuffers(1, &buffer_);
+                       alDeleteBuffers(1, &buffer_);
+                       retain_counts_.erase(it);
+                       log_warning("kill buffer:", buffer_);
                }
+       }
 
 
-               void init(const std::string& path)
-               {
-                       log_info("initializing audio buffer...");
-                       if (mOggStream.datasource)
-                       {
-                               ov_clear(&mOggStream);
-                               mOggStream.datasource = 0;
-                       }
+       ALuint                                  buffer_;
+       sound_backend                   backend_;
 
-                       if (ov_fopen((char*)path.c_str(), &mOggStream) < 0)
-                       {
-                               throw std::runtime_error("problem reading audio: " + path);
-                       }
+       static retcount_lookup  retain_counts_;
+};
 
-                       vorbis_info* vorbisInfo = ov_info(&mOggStream, -1);
-                       mFormat = get_audio_format(vorbisInfo);
-                       mFreq = vorbisInfo->rate;
-               }
+buffer::retcount_lookup buffer::retain_counts_;
 
 
-               void load_all(ALuint source)
-               {
-                       if (!mOggStream.datasource) init(name());
-                       if (!mOggStream.datasource) return;
 
-                       char data[BUF_SIZE];
-                       int size = 0;
+// SOUND RESOURCE
 
-                       for (;;)
-                       {
-                               int section;
-                               int result = ov_read(&mOggStream, data + size,
-                                               BUF_SIZE - size, 0, 2, 1, &section);
+class sound_resource
+{
+public:
 
-                               if (result > 0)
-                               {
-                                       size += result;
-                               }
-                               else
-                               {
-                                       if (result < 0) log_warning("vorbis playback error");
-                                       break;
-                               }
-                       }
-                       if (size == 0)
-                       {
-                               log_warning("decoded no bytes from", name());
-                               return;
-                       }
+       sound_resource(const std::string& path)
+       {
+               log_info("audio path is", path);
+               if (ov_fopen((char*)path.c_str(), &file_) < 0)
+               {
+                       throw std::runtime_error("problem reading audio: " + path);
+               }
+       }
+
+       ~sound_resource()
+       {
+               ov_clear(&file_);
+       }
 
-                       alGenBuffers(1, &buffer_);
 
-                       alBufferData(buffer_, mFormat, data, size, mFreq);
-                       alSourcei(source, AL_BUFFER, buffer_);
+       bool read(buffer& buf)
+       {
+               if (buffer_)
+               {
+                       buf = buffer_;
+                       return true;
+               }
 
-                       // don't need to keep this loaded
-                       ov_clear(&mOggStream);
-                       mOggStream.datasource = 0;
+               if (ov_pcm_seek_lap(&file_, 0) != 0)
+               {
+                       log_warning("vorbis seek error");
+                       return false;
                }
 
-               bool stream(ALuint buffer)
+               char    data[64*BUF_SIZE];
+               size_t  size = 0;
+
+               while (size < sizeof(data))
                {
-                       char data[BUF_SIZE];
-                       int size = 0;
+                       int     section;
+                       int     result = ov_read(&file_,
+                                                                data + size, sizeof(data) - size,
+                                                                0, 2, 1, &section);
 
-                       while (size < BUF_SIZE)
+                       if (result > 0)
                        {
-                               int section;
-                               int result = ov_read(&mOggStream, data + size,
-                                               BUF_SIZE - size, 0, 2, 1, &section);
-
-                               if (result > 0)
-                               {
-                                       size += result;
-                               }
-                               else
-                               {
-                                       if (result < 0) log_warning("vorbis playback error");
-                                       break;
-                               }
+                               size += result;
+                               continue;
                        }
+                       else if (result == 0 && size > 0)
+                       {
+                               log_info("loaded", size, "bytes from vorbis");
+                               vorbis_info* info = ov_info(&file_, section);
+                               buffer_ = buffer(data, size,
+                                                                get_audio_format(info), info->rate);
+                               buf = buffer_;
+                               log_info("this section is", section);
+                               log_info("audio format is", get_audio_format(info));
+                               log_info("audio freq is", info->rate);
+                               return true;
+                       }
+                       else
+                       {
+                               log_warning("vorbis playback error");
+                               break;
+                       }
+               }
 
-                       if (size == 0) return false;
+               if (size >= sizeof(data)) log_warning("sample is too big to play");
+               return false;
+       }
 
-                       alBufferData(buffer, mFormat, data, size, mFreq);
 
-                       return true;
+       bool read(buffer& buf, uint64_t& sample)
+       {
+               if (ov_pcm_seek_lap(&file_, sample) != 0)
+               {
+                       log_warning("vorbis seek error");
+                       return false;
                }
 
-               void rewind()
+               char data[BUF_SIZE];
+               int     section;
+               int     result = ov_read(&file_, data, sizeof(data), 0, 2, 1, &section);
+
+               if (result > 0)
                {
-                       if (!mOggStream.datasource) init(name());
-                       else ov_raw_seek(&mOggStream, 0);
+                       log_info("loaded", result, "bytes from vorbis");
+                       vorbis_info* info = ov_info(&file_, section);
+                       buf = buffer(data, result, get_audio_format(info), info->rate);
+                       sample = ov_pcm_tell(&file_);
+                       log_info("this section is", section);
+                       log_info("next sample is", sample);
+                       log_info("audio format is", get_audio_format(info));
+                       log_info("audio freq is", info->rate);
+                       return true;
                }
 
+               if (result < 0) log_warning("vorbis playback error");
+               return false;
+       }
 
-       private:
 
-               OggVorbis_File  mOggStream;
-               ALenum                  mFormat;
-               ALsizei                 mFreq;
-               ALuint                  buffer_;
-       };
+       static ALenum get_audio_format(const vorbis_info* info)
+       {
+               if (info->channels == 1) return AL_FORMAT_MONO16;
+               else                                     return AL_FORMAT_STEREO16;
+       }
 
 
+private:
+
+       OggVorbis_File  file_;
+       buffer                  buffer_;
+};
+
+
+
+class sound::impl
+{
+public:
+
        impl()
        {
                init();
@@ -202,36 +368,26 @@ public:
 
        void init()
        {
-               retain_backend();
-
-               is_loaded_ = false;
                is_playing_ = false;
                is_looping_ = false;
 
+               sample_ = 0;
+
                alGenSources(1, &source_);
+               log_error("alGenSources:", alGetError());
 
                ALfloat zero[] = {0.0f, 0.0f, 0.0f};
                alSourcef(source_,  AL_PITCH, 1.0f);
                alSourcef(source_,  AL_GAIN, 1.0f);
                alSourcefv(source_, AL_POSITION, zero);
                alSourcefv(source_, AL_VELOCITY, zero);
-
-               alSourcei(source_, AL_LOOPING, is_looping_);
+               log_error("init:", alGetError());
        }
 
        ~impl()
        {
                stop();
-
                alDeleteSources(1, &source_);
-
-               while (!buffers_.empty())
-               {
-                       alDeleteBuffers(1, &buffers_.back());
-                       buffers_.pop_back();
-               }
-
-               release_backend();
        }
 
 
@@ -239,53 +395,60 @@ public:
        {
                if (queue_.empty()) return;
 
-               if (!is_loaded_) queue_.front()->load_all(source_);
+               sound_handle    handle = queue_.front();
+               buffer                  buf;
 
-               alSourcePlay(source_);
-               is_loaded_ = true;
+               if (handle->read(buf))
+               {
+                       log_info("playing source...");
+                       buf.set(source_);
+                       alSourcei(source_, AL_LOOPING, is_looping_);
+                       alSourcePlay(source_);
+               }
        }
 
-
-       void play_stream()
+       void stream()
        {
                if (queue_.empty()) return;
 
                if (!is_playing_)
                {
                        alSourcei(source_, AL_LOOPING, false);
-                       buffer_stream();
+                       log_error("set not looping:", alGetError());
+
+                       sound_handle handle = queue_.front();
+
+                       for (int i = 0; i < NUM_BUFFERS; ++i)
+                       {
+                               buffer buf;
+                               if (handle->read(buf, sample_))
+                               {
+                                       buf.queue(source_);
+                               }
+                               else
+                               {
+                                       log_error("failed to start stream");
+                                       break;
+                               }
+
+                               ALint queued = 0;
+                               alGetSourcei(source_, AL_BUFFERS_QUEUED, &queued);
+                               log_info("buffers queued:", queued);
+                       }
                }
 
                if (!stream_timer_.is_valid())
                {
                        stream_timer_.init(boost::bind(&impl::stream_update, this, _1, _2),
-                                       1.0, timer::repeat);
+                                       0.01, timer::repeat);
                }
 
+               log_info("streaming source...");
                alSourcePlay(source_);
+               log_error("playing:", alGetError());
                is_playing_ = true;
        }
 
-       void buffer_stream()
-       {
-               ALuint buffer;
-               for (int i = buffers_.size(); i <= 8; ++i)
-               {
-                       alGenBuffers(1, &buffer);
-
-                       if (queue_.front()->stream(buffer))
-                       {
-                               alSourceQueueBuffers(source_, 1, &buffer);
-                               buffers_.push_back(buffer);
-                       }
-                       else
-                       {
-                               alDeleteBuffers(1, &buffer);
-                               break;
-                       }
-               }
-       }
-
 
        void update()
        {
@@ -295,47 +458,50 @@ public:
 
                while (finished-- > 0)
                {
-                       ALuint bufferObj;
-                       alSourceUnqueueBuffers(source_, 1, &bufferObj);
-
-                       buffer_ptr buffer = queue_.front();
-                       bool streamed = buffer->stream(bufferObj);
+                       buffer::unqueue(source_);
+                       bool streamed = false;
+                       //if (handle->is_loaded())
+                       //{
+                               //streamed = handle->read(buf);
+                       //}
+                       //else
+                       //{
+                               buffer buf;
+                               sound_handle handle = queue_.front();
+                               streamed = handle->read(buf, sample_);
+                       //}
 
                        if (streamed)
                        {
-                               alSourceQueueBuffers(source_, 1, &bufferObj);
+                               buf.queue(source_);
                        }
                        else
                        {
                                // the buffer couldn't be streamed, so get rid of it
                                queue_.pop_front();
+                               sample_ = 0;
 
                                if (!queue_.empty())
                                {
                                        // begin the next buffer in the queue
-                                       queue_.front()->rewind();
-                                       queue_.front()->stream(bufferObj);
-                                       alSourceQueueBuffers(source_, 1, &bufferObj);
+                                       handle->read(buf, sample_);
+                                       buf.queue(source_);
                                        log_info("loading new buffer");
-
-                                       // queue up any unused buffers
-                                       buffer_stream();
                                }
                                else if (is_looping_)
                                {
                                        // reload the same buffer
-                                       queue_.push_back(buffer);
-                                       buffer->rewind();
-                                       buffer->stream(bufferObj);
-                                       alSourceQueueBuffers(source_, 1, &bufferObj);
                                        log_info("looping same buffer");
+
+                                       queue_.push_back(handle);
+                                       handle->read(buf, sample_);
+                                       buf.queue(source_);
                                }
                                else
                                {
                                        // nothing more to play, stopping...
-                                       is_playing_ = false;
-                                       std::remove(buffers_.begin(), buffers_.end(),
-                                                               bufferObj);
+                                       stop();
+                                       queue_.push_back(handle);
                                }
                        }
                }
@@ -358,6 +524,8 @@ public:
                is_playing_ = false;
 
                stream_timer_.invalidate();
+
+               // TODO: clear buffers if streaming
        }
 
        void pause()
@@ -368,6 +536,12 @@ public:
                stream_timer_.invalidate();
        }
 
+       void rewind()
+       {
+               alSourceRewind(source_);
+               sample_ = 0;
+       }
+
 
        void sample(const std::string& path)
        {
@@ -375,32 +549,24 @@ public:
                alSourcei(source_, AL_BUFFER, AL_NONE);
 
                queue_.clear();
-               is_loaded_ = false;
 
                enqueue(path);
-
-               while (!buffers_.empty())
-               {
-                       alDeleteBuffers(1, &buffers_.back());
-                       buffers_.pop_back();
-               }
        }
 
        void enqueue(const std::string& path)
        {
-               buffer_ptr buffer = buffer::instance(path);
-               queue_.push_back(buffer);
+               sound_handle handle = resource::load(path);
+               queue_.push_back(handle);
        }
 
 
        bool is_playing() const
        {
-               if (is_playing_) return true;
-
                ALenum state;
                alGetSourcei(source_, AL_SOURCE_STATE, &state);
 
-               return state == AL_PLAYING;
+               if (state == AL_PLAYING) return true;
+               else                     return is_playing_;
        }
 
 
@@ -426,64 +592,23 @@ public:
        }
 
 
-       static void retain_backend()
-       {
-               if (retain_count_++ == 0)
-               {
-                       al_device_ = alcOpenDevice(0);
-                       al_context_ = alcCreateContext(al_device_, 0);
-                       if (!al_device_ || !al_context_)
-                       {
-                               const char* error = alcGetString(al_device_,
-                                                                                                alcGetError(al_device_));
-                               log_error("audio subsystem initialization failure", error);
-                       }
-                       else
-                       {
-                               alcMakeContextCurrent(al_context_);
-                               log_info << "opened sound device `"
-                                                << alcGetString(al_device_,
-                                                                                ALC_DEFAULT_DEVICE_SPECIFIER)
-                                                << "'" << std::endl;
-                       }
-               }
-       }
-
-       static void release_backend()
-       {
-               if (--retain_count_ == 0)
-               {
-                       alcMakeContextCurrent(0);
-                       alcDestroyContext(al_context_);
-                       alcCloseDevice(al_device_);
-               }
-       }
+       ALuint                                          source_;
 
+       bool                                            is_playing_;
+       bool                                            is_looping_;
 
-       ALuint                                  source_;
-       std::list<ALuint>               buffers_;
+       std::deque<sound_handle>        queue_;
+       uint64_t                                        sample_;
 
-       bool                                    is_loaded_;
-       bool                                    is_playing_;
-       bool                                    is_looping_;
+       timer                                           stream_timer_;
 
-       std::deque<buffer_ptr>  queue_;
-
-       timer                                   stream_timer_;
-
-       static unsigned                 retain_count_;
-       static ALCdevice*               al_device_;
-       static ALCcontext*              al_context_;
+       sound_backend                           backend_;
 };
 
-unsigned       sound::impl::retain_count_ = 0;
-ALCdevice*     sound::impl::al_device_ = 0;
-ALCcontext*    sound::impl::al_context_ = 0;
 
-
-//sound::sound() :
-       //// pass through
-       //impl_(new sound::impl) {}
+sound::sound() :
+       // pass through
+       impl_(new sound::impl) {}
 
 sound::sound(const std::string& path) :
        // pass through
@@ -499,6 +624,12 @@ void sound::sample(const std::string& path)
        impl_->sample(path);
 }
 
+void sound::enqueue(const std::string& path)
+{
+       // pass through
+       impl_->enqueue(path);
+}
+
 
 void sound::play()
 {
@@ -506,6 +637,12 @@ void sound::play()
        impl_->play();
 }
 
+void sound::stream()
+{
+       // pass through
+       impl_->stream();
+}
+
 void sound::stop()
 {
        // pass through
@@ -518,11 +655,18 @@ void sound::pause()
        impl_->pause();
 }
 
+void sound::rewind()
+{
+       // pass through
+       impl_->rewind();
+}
+
 
 void sound::toggle()
 {
        if (is_playing()) pause();
        else play();
+       // TODO: what about streaming sources?
 }
 
 bool sound::is_playing() const
@@ -587,22 +731,5 @@ void sound::listener_orientation(const vector3& forward,
 }
 
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
-void sound_stream::enqueue(const std::string& path)
-{
-       // pass through
-       impl_->enqueue(path);
-}
-
-
-void sound_stream::play()
-{
-       // pass through
-       impl_->play_stream();
-}
-
-
 } // namespace moof
 
index a0dd1033c1a1eb0f7979a62745537e12d8d36d08..a3c94f1009bbe698bf7cd9d5fa716a8ac9d5a92c 100644 (file)
 #include <boost/shared_ptr.hpp>
 
 #include <moof/math.hh>
-#include <moof/resource.hh>
 
 
 namespace moof {
 
 
-class sound;
-typedef resource_handle<sound> sound_handle;
-class sound_stream;
-typedef resource_handle<sound_stream> sound_stream_handle;
-
-
-class sound : public resource
+class sound
 {
 public:
 
-       //sound();
+       sound();
        explicit sound(const std::string& path);
 
-       virtual ~sound() {}
-
-       // this implicitly stops the sound if it is playing
        void sample(const std::string& path);
+       void enqueue(const std::string& path);
 
-       virtual void play();
+       void play();
+       void stream();
        void stop();
        void pause();
+       void rewind();
 
        void toggle();
        bool is_playing() const;
@@ -58,33 +51,21 @@ public:
        void gain(scalar gain);
        void pitch(scalar pitch);
        void loop(bool looping);
+       
+
+       void listener_position(const vector3& position);
+       void listener_velocity(const vector3& velocity);
+       void listener_orientation(const vector3& forward,
+                                                         const vector3& up);
 
-       static void listener_position(const vector3& position);
-       static void listener_velocity(const vector3& velocity);
-       static void listener_orientation(const vector3& forward,
-                                                                        const vector3& up);
 
-protected:
+private:
 
        class impl;
        boost::shared_ptr<impl> impl_;
 };
 
 
-class sound_stream : public sound
-{
-public:
-
-       //sound_stream();
-       explicit sound_stream(const std::string& path) :
-               sound(path) {}
-
-       void enqueue(const std::string& path);
-
-       void play();
-};
-
-
 } // namespace moof
 
 #endif // _MOOF_SOUND_HH_
index 5bb2092af68591a8dc6fa3df03dd5d0ecd736b3e..89f3e9da825676ef16e8ad94086e52f91615af74 100644 (file)
@@ -113,7 +113,7 @@ scalar timer::find_next_expiration()
        scalar next_fire = std::numeric_limits<scalar>::max();
 
        hash<unsigned,timer*,hash_function>::iterator it;
-       for (it = timers_.begin(); it != timers_.end(); ++it)
+       for (it = timers_.begin(); it.valid(); ++it)
        {
                scalar absolute = (*it).second->absolute_;
                if (absolute < next_fire) next_fire = absolute;
@@ -149,10 +149,12 @@ void timer::fire_expired_timers(scalar t)
        if (next_expiration_ > t) return;
 
        hash<unsigned,timer*,hash_function>::iterator it;
-       for (it = timers_.begin(); it != timers_.end(); ++it)
+       for (it = timers_.begin(); it.valid(); ++it)
        {
                timer* timer = (*it).second;
                if (timer->is_expired()) timer->fire();
+
+               if (it.end()) break;
        }
 }
 
This page took 0.052177 seconds and 4 git commands to generate.