From 1da520638918096276158ecdfaeebc14a3d70be7 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Thu, 17 Jun 2010 15:40:46 -0600 Subject: [PATCH] resource loading bugs and new sound class --- src/GameLayer.cc | 19 +- src/GameLayer.hh | 4 +- src/Main.cc | 1 + src/moof/hash.hh | 5 +- src/moof/resource.cc | 45 +++- src/moof/resource.hh | 23 +- src/moof/sound.cc | 613 ++++++++++++++++++++++++++----------------- src/moof/sound.hh | 45 +--- src/moof/timer.cc | 6 +- 9 files changed, 450 insertions(+), 311 deletions(-) diff --git a/src/GameLayer.cc b/src/GameLayer.cc index fcb77ed..8299d63 100644 --- a/src/GameLayer.cc +++ b/src/GameLayer.cc @@ -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) diff --git a/src/GameLayer.hh b/src/GameLayer.hh index 37eb8e0..f2a70f9 100644 --- a/src/GameLayer.hh +++ b/src/GameLayer.hh @@ -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; diff --git a/src/Main.cc b/src/Main.cc index 6914c97..adda533 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -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); diff --git a/src/moof/hash.hh b/src/moof/hash.hh index 0963912..ea63db1 100644 --- a/src/moof/hash.hh +++ b/src/moof/hash.hh @@ -39,9 +39,10 @@ struct hash_function return (*this)(val.data(), val.length()); } - unsigned operator () (int val) const + template + unsigned operator () (T val) const { - return val; + return static_cast(val); } }; diff --git a/src/moof/resource.cc b/src/moof/resource.cc index 359d1b4..314f80b 100644 --- a/src/moof/resource.cc +++ b/src/moof/resource.cc @@ -33,6 +33,25 @@ 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::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_weakptr; static hash 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::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::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()); diff --git a/src/moof/resource.hh b/src/moof/resource.hh index 29ae114..f8fd4f6 100644 --- a/src/moof/resource.hh +++ b/src/moof/resource.hh @@ -88,9 +88,11 @@ public: template 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); - (*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 type_lookup; - typedef boost::shared_ptr type_lookup_ptr; - static type_lookup_ptr type_lookup_; + //typedef boost::shared_ptr 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_; diff --git a/src/moof/sound.cc b/src/moof/sound.cc index a1da62b..853c21a 100644 --- a/src/moof/sound.cc +++ b/src/moof/sound.cc @@ -16,178 +16,344 @@ #include #include +#include #include #include #include #include +#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_handle; + + +class sound_resource_loader { public: - impl() + sound_resource_loader() { - resource::register_type("ogg"); + resource::register_type("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 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_ptr; - - class buffer : public manager + 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, §ion); +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, §ion); - while (size < BUF_SIZE) + if (result > 0) { - int section; - int result = ov_read(&mOggStream, data + size, - BUF_SIZE - size, 0, 2, 1, §ion); - - 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, §ion); + + 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 buffers_; + std::deque queue_; + uint64_t sample_; - bool is_loaded_; - bool is_playing_; - bool is_looping_; + timer stream_timer_; - std::deque 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 diff --git a/src/moof/sound.hh b/src/moof/sound.hh index a0dd103..a3c94f1 100644 --- a/src/moof/sound.hh +++ b/src/moof/sound.hh @@ -22,33 +22,26 @@ #include #include -#include namespace moof { -class sound; -typedef resource_handle sound_handle; -class sound_stream; -typedef resource_handle 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_; }; -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_ diff --git a/src/moof/timer.cc b/src/moof/timer.cc index 5bb2092..89f3e9d 100644 --- a/src/moof/timer.cc +++ b/src/moof/timer.cc @@ -113,7 +113,7 @@ scalar timer::find_next_expiration() scalar next_fire = std::numeric_limits::max(); hash::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::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; } } -- 2.45.2