media-libs/sdl-image[png]
virtual/opengl
media-libs/sdl-sound[mikmod, vorbis]
- media-libs/openal"
+ media-libs/openal
+ media-libs/freealut"
DEPEND="${RDEPEND}
dev-libs/boost
dev-util/pkgconfig"
calculateSecondary();
}
-void Camera::adjustFromInput(const Event& event)
+void Camera::handleEvent(const Event& event)
{
switch (event.type)
{
return frustum_;
}
- void adjustFromInput(const Event& event);
+ void handleEvent(const Event& event);
void update(Scalar t, Scalar dt);
private:
Notification::~Notification() {}
-class Dispatcher::DispatcherImpl
+struct Dispatcher::Impl
{
-public:
- DispatcherImpl() : id(1) {}
+ Impl() :
+ id(1) {}
- Dispatcher::Handler getNewHandlerID()
+ Dispatcher::Handler getNewHandler()
{
- id += 4;
+ id += 2;
return (Dispatcher::Handler)id;
}
typedef std::multimap<Dispatcher::Handler,std::string> HandlerLookup;
typedef HandlerLookup::iterator HandlerIter;
- unsigned long long id;
- CallbackLookup callbacks;
- HandlerLookup handlers;
+ inline Handler addHandler(const std::string& message,
+ const Function& callback, Handler id)
+ {
+ callbacks.insert(std::make_pair(message, std::make_pair(id, callback)));
+ handlers.insert(std::make_pair(id, message));
+
+ return id;
+ }
+
+ inline void removeHandler(Handler id)
+ {
+ std::pair<HandlerIter,HandlerIter> matching(handlers.equal_range(id));
+
+ for (HandlerIter it = matching.first; it != matching.second; ++it)
+ {
+ CallbackIter first = callbacks.find((*it).second);
+ CallbackIter last = callbacks.end();
+
+ for (CallbackIter jt = first; jt != last; ++jt)
+ {
+ if (((*jt).second).first == id)
+ {
+ callbacks.erase(jt);
+ break;
+ }
+ }
+ }
+
+ handlers.erase(id);
+ }
+
+ unsigned long id;
+
+ CallbackLookup callbacks;
+ HandlerLookup handlers;
};
Dispatcher::Dispatcher() :
- impl_(new Dispatcher::DispatcherImpl) {}
+ impl_(new Dispatcher::Impl) {}
-// TODO these methods are ugly
-
Dispatcher::Handler Dispatcher::addHandler(const std::string& message,
const Function& callback)
{
- return addHandler(message, callback, impl_->getNewHandlerID());
+ return addHandler(message, callback, impl_->getNewHandler());
}
Dispatcher::Handler Dispatcher::addHandler(const std::string& message,
const Function& callback, Handler id)
{
- std::pair<std::string,Dispatcher::DispatcherImpl::Callback>
- callbackPair(message, Dispatcher::DispatcherImpl::Callback(id, callback));
-
- std::pair<Handler,std::string> handlerPair(id, message);
-
- impl_->callbacks.insert(callbackPair);
- impl_->handlers.insert(handlerPair);
-
- return id;
+ // pass through
+ return impl_->addHandler(message, callback, id);
}
void Dispatcher::removeHandler(Handler id)
{
- std::pair<Dispatcher::DispatcherImpl::HandlerIter,Dispatcher::DispatcherImpl::HandlerIter>
- handlers(impl_->handlers.equal_range(id));
-
- Dispatcher::DispatcherImpl::HandlerIter it;
- for (it = handlers.first; it != handlers.second; ++it)
- {
- Dispatcher::DispatcherImpl::CallbackIter first = impl_->callbacks.find((*it).second);
- Dispatcher::DispatcherImpl::CallbackIter last = impl_->callbacks.end();
-
- Dispatcher::DispatcherImpl::CallbackIter jt;
- for (jt = first; jt != last; ++jt)
- {
- if (((*jt).second).first == id)
- {
- impl_->callbacks.erase(jt);
- break;
- }
- }
- }
-
- impl_->handlers.erase(id);
+ // pass through
+ return impl_->removeHandler(id);
}
-void Dispatcher::dispatch(const std::string& message)
-{
- dispatch(message, Notification());
-}
-
-void Dispatcher::dispatch(const std::string& message, const Notification& param)
+void Dispatcher::dispatch(const std::string& message, const Notification* param)
{
- std::pair<Dispatcher::DispatcherImpl::CallbackIter,Dispatcher::DispatcherImpl::CallbackIter>
+ std::pair<Impl::CallbackIter,Impl::CallbackIter>
callbacks(impl_->callbacks.equal_range(message));
- Dispatcher::DispatcherImpl::CallbackIter it;
- for (it = callbacks.first; it != callbacks.second; ++it)
+ for (Impl::CallbackIter it = callbacks.first; it != callbacks.second; ++it)
{
Function callback = ((*it).second).second;
callback(param);
{
public:
typedef void* Handler;
- typedef boost::function<void(const Notification&)> Function;
+ typedef boost::function<void(const Notification*)> Function;
Dispatcher();
void removeHandler(Handler id);
- void dispatch(const std::string& message);
- void dispatch(const std::string& message, const Notification& param);
+ void dispatch(const std::string& message, const Notification* param = 0);
private:
- class DispatcherImpl;
- boost::shared_ptr<DispatcherImpl> impl_;
+ class Impl;
+ boost::shared_ptr<Impl> impl_;
};
#include "Mippleton.hh"
#include "Sound.hh"
+#define BUFFER_SIZE (8 * 4096)
namespace Mf {
struct Buffer : public Mippleton<Buffer>
{
Buffer(const std::string& name) :
- Mippleton<Buffer>(name),
- object(0)
- {}
+ Mippleton<Buffer>(name)
+ {
+ objects[0] = 0;
+ objects[1] = 0;
+ }
~Buffer()
{
- alDeleteBuffers(1, &object);
+ alDeleteBuffers(2, objects);
+
+ if (sound) Sound_FreeSample(sound);
}
+
+
void loadFromFile(const std::string& filePath, bool stream)
{
- if (object != 0) return;
+ if (objects[0] != 0) return;
- Sound_Sample* sound = Sound_NewSampleFromFile(filePath.c_str(),
- NULL, 8096);
+ sound = Sound_NewSampleFromFile(filePath.c_str(),
+ NULL, BUFFER_SIZE);
if (!sound)
{
exit(1);
}
+ if (!stream)
+ {
unsigned decoded = Sound_DecodeAll(sound);
if (decoded == 0)
{
std::cout << "decoded no bytes" << std::endl;
exit(1);
}
+
+ alGenBuffers(2, objects);
+ alBufferData(objects[0], getAudioFormat(sound->actual), sound->buffer,
+ sound->buffer_size, sound->actual.rate);
std::cerr << "buffer size: " << sound->buffer_size << std::endl;
std::cerr << "channels: " << (int)sound->actual.channels << std::endl;
std::cerr << "format: " << sound->actual.format << std::endl;
std::cerr << "frequency: " << sound->actual.rate << std::endl;
- alGenBuffers(1, &object);
- alBufferData(object, getAudioFormat(sound->actual), sound->buffer,
- sound->buffer_size, sound->actual.rate);
-
Sound_FreeSample(sound);
+ sound = 0;
+ }
+ else
+ {
+ std::cerr << "buffer size: " << sound->buffer_size << std::endl;
+ std::cerr << "channels: " << (int)sound->actual.channels << std::endl;
+ std::cerr << "format: " << sound->actual.format << std::endl;
+ std::cerr << "frequency: " << sound->actual.rate << std::endl;
+ alGenBuffers(2, objects);
+ }
+ }
+
+ bool stream(ALuint buffer)
+ {
+ int bytes = Sound_Decode(sound);
+
+ if (bytes < BUFFER_SIZE) return false;
+
+ alBufferData(buffer, getAudioFormat(sound->actual), sound->buffer,
+ sound->buffer_size, sound->actual.rate);
+ return false;
}
- ALuint object;
+ Sound_Sample* sound;
+ ALuint objects[2];
//ALfloat location[] = {0.0f, 0.0f, 0.0f};
//ALfloat location2[] = {0.0f, 0.0f, 0.0f};
ALfloat location[] = {0.0f, 0.0f, 0.0f};
alGenSources(1, &source_);
- alSourcei(source_, AL_BUFFER, buffer_->object);
+
alSourcef(source_, AL_PITCH, 1.0f);
alSourcef(source_, AL_GAIN, 1.0f);
alSourcefv(source_, AL_POSITION, location);
alSourcefv(source_, AL_VELOCITY, location);
alSourcei(source_, AL_LOOPING, AL_FALSE);
+
+ if (!stream)
+ {
+ alSourcei(source_, AL_BUFFER, buffer_->objects[0]);
+ }
+ else
+ {
+ buffer_->stream(buffer_->objects[0]);
+ buffer_->stream(buffer_->objects[1]);
+
+ alSourceQueueBuffers(source_, 2, buffer_->objects);
+ }
}
~Impl()
void update()
{
+ int finished = 0;
+
+ alGetSourcei(source_, AL_BUFFERS_PROCESSED, &finished);
+
+ while (finished-- > 0)
+ {
+ ALuint buffer;
+
+ alSourceUnqueueBuffers(source_, 1, &buffer);
+ buffer_->stream(buffer);
+ alSourceQueueBuffers(source_, 1, &buffer);
+ }
}
boost::shared_ptr<Buffer> buffer_;
ALuint source_;
+ bool playing;
};
void Sound::play()
{
- alSourceRewind(impl_->source_);
+ //alSourceRewind(impl_->source_);
alSourcePlay(impl_->source_);
+ impl_->playing = true;
+}
+
+void Sound::pause()
+{
+ alSourcePause(impl_->source_);
+ impl_->playing = false;
+}
+
+void Sound::togglePlayPause()
+{
+ if (impl_->playing) pause();
+ else play();
+}
+
+void Sound::setGain(Scalar gain)
+{
+ alSourcef(impl_->source_, AL_GAIN, gain);
}
Sound(const std::string& name);
void play();
+ void pause();
+ void togglePlayPause();
+
+ void setGain(Scalar gain);
static std::string getPath(const std::string& name);
* to cache it if the client has plenty of RAM.
*/
- void contextRecreated(const Notification& note)
+ void contextRecreated(const Notification* note)
{
object_ = globalObject_ = 0;
uploadToGL();
boost::bind(&YoinkApp::contextRecreated, this, _1), this);
setupGL();
+ Mf::Scalar fade[2] = {0.0, 1.0};
+ musicFade.init(fade, 0.0);
music.play();
state = 0.0;
//glLineWidth(10.0f);
}
-void YoinkApp::contextRecreated(const Mf::Notification& note)
+void YoinkApp::contextRecreated(const Mf::Notification* note)
{
// Whenever the context and a new one created, it probably won't contain our
// state so we need to set that up again.
void YoinkApp::update(Mf::Scalar t, Mf::Scalar dt)
{
//dt *= 0.2;
+
+ musicFade.update(dt);
+ music.update(t, dt);
+ music.setGain(musicFade.getValue());
fadeIn.update(dt);
{
testScene->refresh();
}
+ else if (event.key.keysym.sym == SDLK_p)
+ {
+ music.togglePlayPause();
+ }
else if (event.key.keysym.sym == SDLK_l)
{
getVideo().toggleCursorGrab();
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
- camera.adjustFromInput(event);
+ camera.handleEvent(event);
break;
case SDL_QUIT:
* Set OpenGL to a state we can know and depend on.
*/
void setupGL();
- void contextRecreated(const Mf::Notification& note);
+ void contextRecreated(const Mf::Notification* note);
+ Mf::Lerps musicFade;
Mf::SoundStream music;
CharacterPtr heroine;