From 1a6c940ed9d7f6136da0e13148314072665342c5 Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 10 May 2011 22:28:58 +0200 Subject: - refactorized audio once more: audio is now a plugin which gets loaded at runtime - thus server has no dependency to phonon any more - remove client dependency to qtnetwork - fix enet deinitialization on windows --- pacman-c++/client/client.cpp | 11 +- pacman-c++/client/client.pro | 2 + pacman-c++/client/mainwidget.cpp | 2 +- pacman-c++/common.pri | 21 +-- pacman-c++/common/actor.cpp | 6 +- pacman-c++/common/actor.h | 2 +- pacman-c++/common/audio.cpp | 262 ++++++++++++++++--------------- pacman-c++/common/audio.h | 147 ++++++++++++----- pacman-c++/common/common.pro | 2 + pacman-c++/pacman.pro | 1 + pacman-c++/phononplayer/phononplayer.cpp | 169 ++++++++++++++++++++ pacman-c++/phononplayer/phononplayer.h | 71 +++++++++ pacman-c++/phononplayer/phononplayer.pro | 11 ++ pacman-c++/proto/proto.pro | 1 - pacman-c++/rebuild.sh | 2 +- pacman-c++/rebuild_debug.sh | 6 + pacman-c++/server/server.cpp | 13 +- pacman-c++/server/server.pro | 5 +- 18 files changed, 539 insertions(+), 195 deletions(-) create mode 100644 pacman-c++/phononplayer/phononplayer.cpp create mode 100644 pacman-c++/phononplayer/phononplayer.h create mode 100644 pacman-c++/phononplayer/phononplayer.pro create mode 100755 pacman-c++/rebuild_debug.sh diff --git a/pacman-c++/client/client.cpp b/pacman-c++/client/client.cpp index 96ee59a..da505d1 100644 --- a/pacman-c++/client/client.cpp +++ b/pacman-c++/client/client.cpp @@ -272,14 +272,17 @@ int main(int argc, char **argv) qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); + /* load sound */ AudioManager::self(); - Client client; - client.show(); - client.setWindowTitle(app.applicationName()); - + Client *client = new Client; + client->show(); + client->setWindowTitle(app.applicationName()); int ret = app.exec(); + /* delete client so that we'll disconnect from server before enet deinitialize */ + delete client; + enet_deinitialize(); /* Delete all global objects allocated by libprotobuf */ diff --git a/pacman-c++/client/client.pro b/pacman-c++/client/client.pro index 4b326fe..178ccf4 100644 --- a/pacman-c++/client/client.pro +++ b/pacman-c++/client/client.pro @@ -1,6 +1,8 @@ TEMPLATE = app TARGET = pacman +DEFINES += PACMAN_CLIENT + SOURCES += clicklabel.cpp \ client.cpp \ mainwidget.cpp diff --git a/pacman-c++/client/mainwidget.cpp b/pacman-c++/client/mainwidget.cpp index f6f088b..f2e3f46 100644 --- a/pacman-c++/client/mainwidget.cpp +++ b/pacman-c++/client/mainwidget.cpp @@ -231,7 +231,7 @@ void MainWidget::tick(ENetEvent *event) timer->setInterval(Sound::length[Sound::Intro] + Constants::tick); connect(timer, SIGNAL(timeout()), this, SLOT(startGame())); timer->start(); - AudioManager::self()->play(Sound::Intro, true); + AudioManager::self()->audioPlayer()->play(Sound::Intro); } Transmission::map_t map = Util::createUninitialisedMap(); diff --git a/pacman-c++/common.pri b/pacman-c++/common.pri index 51db8ac..38e5c72 100644 --- a/pacman-c++/common.pri +++ b/pacman-c++/common.pri @@ -1,21 +1,24 @@ LANGUAGE = C++ VERSION = 0.1 -QT += phonon network - DESTDIR = ../ INCLUDEPATH += ../common DEPENDPATH += ../common -LIBS += -L.. -lcommon - INCLUDEPATH += $$OUT_PWD/../proto -LIBS += -L.. -lproto -lprotobuf - INCLUDEPATH += ../enet/include -LIBS += -L$$PWD/enet/.libs -lenet -# enable this if you want to link the archive -#win32:LIBS += -lws2_32 -lwinmm + +contains(TEMPLATE, app) { + LIBS += -L.. -lcommon + LIBS += -L.. -lproto -lprotobuf + LIBS += -L$$PWD/enet/.libs -lenet + # enable this if you want to link the archive + #win32:LIBS += -lws2_32 -lwinmm +} + +contains(CONFIG, plugin) { + LIBS += -L.. -lcommon +} CONFIG(release, debug|release) { DEFINES += QT_NO_DEBUG_OUTPUT diff --git a/pacman-c++/common/actor.cpp b/pacman-c++/common/actor.cpp index de8d77e..83a54e3 100644 --- a/pacman-c++/common/actor.cpp +++ b/pacman-c++/common/actor.cpp @@ -296,21 +296,21 @@ void Actor::die() setZValue(zValue() * 10); m_dieing->start(); if (m_local) - AudioManager::self()->play(Sound::Die); + AudioManager::self()->audioPlayer()->play(Sound::Die); } void Actor::eatingFruit() { if (!m_local) return; - AudioManager::self()->play(Sound::EatingFruit); + AudioManager::self()->audioPlayer()->play(Sound::EatingFruit); } void Actor::eatingPacman() { if (!m_local) return; - AudioManager::self()->play(Sound::EatingGhost); + AudioManager::self()->audioPlayer()->play(Sound::EatingGhost); } void Actor::startEating() diff --git a/pacman-c++/common/actor.h b/pacman-c++/common/actor.h index c30c62a..189afba 100644 --- a/pacman-c++/common/actor.h +++ b/pacman-c++/common/actor.h @@ -11,7 +11,7 @@ class Actor : public GameEntity { -Q_OBJECT + Q_OBJECT public: enum Movement diff --git a/pacman-c++/common/audio.cpp b/pacman-c++/common/audio.cpp index 70cd37e..d29303d 100644 --- a/pacman-c++/common/audio.cpp +++ b/pacman-c++/common/audio.cpp @@ -1,11 +1,12 @@ #include "audio.h" #include "constants.h" -#include #include #include #include #include #include +#include +#include /* the universe's only audio manager */ AudioManager *AudioManager::m_instance = NULL; @@ -17,16 +18,22 @@ AudioManager::AudioManager() if (Constants::server) { qDebug() << "Server has no sound"; - m_players.append(new AudioPlayer(this)); + m_players.append(new FakeAudioPlayer(this)); + return; } - else + + preload(); + if (!tryLoadPhononPlugin()) { - preload(); - AudioPlayer *firstplayer = new AudioPlayer(this); - firstplayer->test(m_sounds[Sound::WakaWaka]); - m_working = firstplayer->m_working; - m_players.append(firstplayer); + qWarning() << "Unable to load audio plugin. Audio disabled.."; + m_players.append(new NoopAudioPlayer(this)); + return; } + + AudioPlayer *firstplayer = m_factory->create(this); + firstplayer->test(m_sounds[Sound::EatingFruit], Sound::length[Sound::EatingFruit] * 2); + m_working = firstplayer->isWorking(); + m_players.append(firstplayer); m_muted = false; } @@ -37,7 +44,7 @@ AudioManager *AudioManager::self() return m_instance; } -bool AudioManager::isWorking() const +bool AudioManager::isWorking() { return m_working; } @@ -98,18 +105,6 @@ AudioPlayer *AudioManager::audioPlayer() return m_players.at(0); } -void AudioManager::play(Sound::Type sound, bool wait) -{ - audioPlayer()->play(sound, wait); -} - -void AudioManager::enqueue(Sound::Type sound) -{ - if (!isWorking()) - return; - audioPlayer()->enqueue(Phonon::MediaSource(m_sounds[sound])); -} - void AudioManager::registerAudioPlayer(AudioPlayer *player) { player->setMuted(m_muted); @@ -123,6 +118,13 @@ void AudioManager::unregisterAudioPlayer(AudioPlayer *player) m_players.removeAll(player); } +QFile *AudioManager::sound(Sound::Type sound) +{ + if (!isWorking()) + return NULL; + return m_sounds.at(sound); +} + void AudioManager::unregisterAudioPlayer_helper(QObject *player) { unregisterAudioPlayer(static_cast(player)); @@ -132,141 +134,160 @@ void AudioManager::preload() { m_sounds.clear(); QDir sounds(":/sound"); + Q_ASSERT(sounds.count() > 0); for(unsigned i = 1; i <= sounds.count(); ++i) m_sounds.append(new QFile(QString(":/sound/sound%1").arg(i), this)); } -QFile *AudioManager::sound(Sound::Type sound) +bool AudioManager::tryLoadPhononPlugin() { - if (!isWorking()) + QDir dir = qApp->applicationDirPath(); + QStringList filters; + filters << "*phononplayer*"; + foreach (QString file, dir.entryList(filters, QDir::Files)) + { + file = dir.absoluteFilePath(file); + if (!QLibrary::isLibrary(file)) + continue; + QPluginLoader pluginloader(file); + if (pluginloader.load()) + { + qDebug() << "Audio plugin loaded" << file; + QObject *plugin = pluginloader.instance(); + m_factory = qobject_cast(plugin); + if (m_factory != NULL) + return true; + } + qDebug() << "Unable to load audio plugin:" << file << pluginloader.errorString(); + } + return false; +} + +AudioPlayer *AudioManager::createAudioPlayer() +{ + if (m_factory == NULL) return NULL; - return m_sounds.at(sound); + + AudioPlayer *player = m_factory->create(this); + registerAudioPlayer(player); + return player; } /* --------------------------------------------------------------- */ -AudioPlayer::AudioPlayer(QObject *parent) - : Phonon::MediaObject(parent), m_working(false) +AudioPlayer *NoopAudioPlayerFactory::create(QObject *parent) { - if (!Constants::server) - { - m_working = AudioManager::m_working; - m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this); - Phonon::createPath(this, m_output); - } + return new FakeAudioPlayer(parent); } -bool AudioPlayer::isWorking() const +/* --------------------------------------------------------------- */ + +NoopAudioPlayer::NoopAudioPlayer(QObject *parent) + : AudioPlayer(parent), m_working(false), m_muted(false), m_playing(false), m_paused(false) +{} + +bool NoopAudioPlayer::isWorking() const { return m_working; } -void AudioPlayer::setMuted(bool mute) +void NoopAudioPlayer::setMuted(bool mute) { - m_output->setMuted(mute); + m_muted = mute; } -bool AudioPlayer::isMuted() const +bool NoopAudioPlayer::isMuted() const { - return m_output->isMuted(); + return m_muted; } -void AudioPlayer::setLoop(QFile *sound) +void NoopAudioPlayer::play() { - if (!isWorking()) - return; - - if (sound == NULL) - { - disconnect(this, SIGNAL(aboutToFinish()), this, SLOT(loopEnqueue())); - return; - } + m_playing = true; + m_paused = false; + emit finished(); + m_playing = false; +} - m_loopsound = sound; - connect(this, SIGNAL(aboutToFinish()), this, SLOT(loopEnqueue())); - setCurrentSource(Phonon::MediaSource(m_loopsound)); - enqueue(Phonon::MediaSource(m_loopsound)); +void NoopAudioPlayer::play(Sound::Type /* sound */) +{ + play(); } -void AudioPlayer::setLoop(Sound::Type sound) +bool NoopAudioPlayer::isPlaying() { - setLoop(AudioManager::self()->sound(sound)); + return m_playing; } -void AudioPlayer::play() +void NoopAudioPlayer::enqueue(Sound::Type /* sound */) +{} + +void NoopAudioPlayer::pause() { - Phonon::MediaObject::play(); + m_paused = true; + m_playing = false; } -void AudioPlayer::play(Sound::Type sound, bool wait) +bool NoopAudioPlayer::isPaused() { - if (m_working) - { - setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound))); - play(); - } - else if (wait) - { - QTimer *timer = new QTimer(this); - timer->setSingleShot(true); - unsigned int interval = Sound::length[sound]; - /* add a small delay server side only */ - if (Constants::server) - interval += Constants::tick; - timer->setInterval(interval); - connect(timer, SIGNAL(timeout()), this, SLOT(finished_ex())); - timer->start(); - } + return m_paused; } -/* this is a simple hack to check if phonon can actually play sounds.. */ -void AudioPlayer::test(QFile *testsound) +void NoopAudioPlayer::stop() { - stop(); - m_output->setVolume(0); - setCurrentSource(Phonon::MediaSource(testsound)); - connect(this, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State,Phonon::State))); - play(); + m_paused = false; + m_playing = false; +} - QTimer timer; - timer.setSingleShot(true); - connect(&timer, SIGNAL(timeout()), this, SLOT(testFinished())); - timer.start(500); - while(timer.isActive()) - { - qApp->processEvents(); - Sleeper::msleep(1); - } - clear(); +bool NoopAudioPlayer::isStopped() +{ + return !m_playing && !m_paused; } -void AudioPlayer::finished_ex() +void NoopAudioPlayer::clear() +{} + +void NoopAudioPlayer::clearQueue() +{} + +void NoopAudioPlayer::setPrefinishMark(qint32 /* msecToEnd */) +{} + +void NoopAudioPlayer::prefinishMarkReached_ex(qint32 mark) { - emit finished(); + emit prefinishMarkReached(mark); } -void AudioPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State /* oldstate */) +void NoopAudioPlayer::test(QFile * /* testsound */, qint32 /* length */) +{} + +/* --------------------------------------------------------------- */ + +FakeAudioPlayer::FakeAudioPlayer(QObject *parent) + : NoopAudioPlayer(parent) { - if (newstate != Phonon::ErrorState) - { - m_working = true; - m_output->setVolume(1); - qDebug() << "Sound is working for you!"; - } - disconnect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); - stop(); + m_working = true; + connect(&m_timer, SIGNAL(timeout()), this, SLOT(finished_ex())); } -void AudioPlayer::testFinished() +void FakeAudioPlayer::play(Sound::Type sound) { - if (!m_working) - qWarning() << "There's no sound for you :("; - disconnect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); + m_playing = true; + m_paused = false; + + m_timer.setSingleShot(true); + unsigned int interval = Sound::length[sound]; + /* add a small delay server side only */ + if (Constants::server) + interval += Constants::tick; + m_timer.setInterval(interval); + m_timer.start(); } -void AudioPlayer::loopEnqueue() +void FakeAudioPlayer::finished_ex() { - enqueue(Phonon::MediaSource(m_loopsound)); + m_playing = false; + emit finished(); } /* --------------------------------------------------------------- */ @@ -274,12 +295,12 @@ void AudioPlayer::loopEnqueue() GaplessAudioPlayer::GaplessAudioPlayer(Sound::Type sound, qint32 mark, QObject *parent) : QObject(parent), m_sound(sound) { - m_working = AudioManager::m_working; + m_working = AudioManager::isWorking(); if (!m_working) return; - m_player1 = new AudioPlayer(this); - m_player2 = new AudioPlayer(this); + m_player1 = AudioManager::self()->createAudioPlayer(); + m_player2 = AudioManager::self()->createAudioPlayer(); m_player2->setPrefinishMark(mark); m_player1->setPrefinishMark(mark); @@ -313,7 +334,7 @@ void GaplessAudioPlayer::play() { if (!m_working) return; - if (m_player1->state() != Phonon::PlayingState && m_player2->state() != Phonon::PlayingState) + if (!m_player1->isPlaying() && !m_player2->isPlaying()) startPlayer1(); } @@ -321,9 +342,9 @@ void GaplessAudioPlayer::pause() { if (!m_working) return; - if (m_player1->state() != Phonon::PausedState) + if (!m_player1->isPaused()) m_player1->pause(); - if (m_player2->state() != Phonon::PausedState) + if (!m_player2->isPaused()) m_player2->pause(); } @@ -336,20 +357,3 @@ void GaplessAudioPlayer::startPlayer2() { m_player2->play(m_sound); } - -/* --------------------------------------------------------------- */ - -void AudioPlayer::Sleeper::sleep(unsigned long secs) -{ - QThread::sleep(secs); -} - -void AudioPlayer::Sleeper::msleep(unsigned long msecs) -{ - QThread::msleep(msecs); -} - -void AudioPlayer::Sleeper::usleep(unsigned long usecs) -{ - QThread::usleep(usecs); -} diff --git a/pacman-c++/common/audio.h b/pacman-c++/common/audio.h index 6aec42d..bc7d66e 100644 --- a/pacman-c++/common/audio.h +++ b/pacman-c++/common/audio.h @@ -4,13 +4,7 @@ #include #include #include -#include -#include - -namespace Phonon -{ - class AudioOutput; -} +#include namespace Sound { @@ -32,46 +26,98 @@ namespace Sound /* --------------------------------------------------------------- */ class AudioPlayer - : public Phonon::MediaObject + : public QObject { Q_OBJECT friend class AudioManager; -private: - class Sleeper - : public QThread - { - public: - static void sleep(unsigned long secs); - static void msleep(unsigned long msecs); - static void usleep(unsigned long usecs); - }; +public: + AudioPlayer(QObject *parent = 0) + : QObject(parent) + {} + virtual ~AudioPlayer() + {} + virtual bool isWorking() const = 0; + virtual void setMuted(bool mute = true) = 0; + virtual bool isMuted() const = 0; + virtual void play() = 0; + virtual void play(Sound::Type sound) = 0; + virtual bool isPlaying() = 0; + virtual void enqueue(Sound::Type sound) = 0; + virtual void pause() = 0; + virtual bool isPaused() = 0; + virtual void stop() = 0; + virtual bool isStopped() = 0; + virtual void clear() = 0; + virtual void clearQueue() = 0; + virtual void setPrefinishMark(qint32 msecToEnd) = 0; + +protected slots: + virtual void prefinishMarkReached_ex(qint32 mark) = 0; + +signals: + void finished(); + void prefinishMarkReached(qint32 mark); + +protected: + virtual void test(QFile *testsound, qint32 length) = 0; +}; + +/* --------------------------------------------------------------- */ + +class NoopAudioPlayer + : public AudioPlayer +{ + Q_OBJECT + friend class AudioManager; public: - AudioPlayer(QObject *parent = 0); - bool isWorking() const; - void setMuted(bool mute = true); - bool isMuted() const; - void setLoop(Sound::Type sound); - void play(); - void play(Sound::Type sound, bool wait = false); + NoopAudioPlayer(QObject *parent = 0); + virtual bool isWorking() const; + virtual void setMuted(bool mute = true); + virtual bool isMuted() const; + virtual void play(); + virtual void play(Sound::Type sound); + virtual bool isPlaying(); + virtual void enqueue(Sound::Type sound); + virtual void pause(); + virtual bool isPaused(); + virtual void stop(); + virtual bool isStopped(); + virtual void clear(); + virtual void clearQueue(); + virtual void setPrefinishMark(qint32 msecToEnd); + +protected slots: + virtual void prefinishMarkReached_ex(qint32 mark); protected: - void test(QFile *testsound); - void setLoop(QFile *sound); + virtual void test(QFile *testsound, qint32 length); -public slots: - void loopEnqueue(); +protected: + bool m_working; + bool m_muted; + bool m_playing; + bool m_paused; +}; + +/* --------------------------------------------------------------- */ + +class FakeAudioPlayer + : public NoopAudioPlayer +{ + Q_OBJECT + friend class AudioManager; + +public: + FakeAudioPlayer(QObject *parent = 0); + virtual void play(Sound::Type sound); protected slots: void finished_ex(); - void testFinished(); - void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate); protected: - bool m_working; - QFile *m_loopsound; - Phonon::AudioOutput *m_output; + QTimer m_timer; }; /* --------------------------------------------------------------- */ @@ -102,17 +148,37 @@ protected: /* --------------------------------------------------------------- */ +class AudioPlayerFactory +{ +public: + virtual ~AudioPlayerFactory() + {} + virtual AudioPlayer *create(QObject *parent = 0) = 0; +}; + +Q_DECLARE_INTERFACE(AudioPlayerFactory, "at.ac.tuwien.foop.pacman.AudioPlayerFactory/1.0"); + +/* --------------------------------------------------------------- */ + +class NoopAudioPlayerFactory + : public AudioPlayerFactory +{ +public: + virtual AudioPlayer *create(QObject *parent = 0); +}; + +/* --------------------------------------------------------------- */ + class AudioManager : public QObject { Q_OBJECT - friend class AudioPlayer; friend class GaplessAudioPlayer; public: AudioManager(); static AudioManager *self(); - bool isWorking() const; + static bool isWorking(); void setMuted(bool mute = true); bool isMuted() const; void pause(); @@ -121,21 +187,21 @@ public: void clearQueue() const; AudioPlayer *audioPlayer(); - void play(Sound::Type sound, bool wait = false); - void enqueue(Sound::Type sound); - void registerAudioPlayer(AudioPlayer *player); void unregisterAudioPlayer(AudioPlayer *player); + QFile *sound(Sound::Type sound); + signals: void mutedChanged(bool muted); private slots: void unregisterAudioPlayer_helper(QObject *player); -private: +protected: void preload(); - QFile *sound(Sound::Type sound); + bool tryLoadPhononPlugin(); + AudioPlayer *createAudioPlayer(); private: bool m_muted; @@ -143,6 +209,7 @@ private: static AudioManager *m_instance; QList m_sounds; QList m_players; + AudioPlayerFactory *m_factory; }; #endif // AUDIOPLAYER_H diff --git a/pacman-c++/common/common.pro b/pacman-c++/common/common.pro index ca82382..e7e415e 100644 --- a/pacman-c++/common/common.pro +++ b/pacman-c++/common/common.pro @@ -1,6 +1,8 @@ TEMPLATE = lib CONFIG += staticlib +DEFINES += PACMAN_COMMON + include(../common.pri) SOURCES += pixmapitem.cpp \ diff --git a/pacman-c++/pacman.pro b/pacman-c++/pacman.pro index ed5f303..8439d38 100644 --- a/pacman-c++/pacman.pro +++ b/pacman-c++/pacman.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS = proto \ common \ + phononplayer \ client \ server CONFIG += ordered diff --git a/pacman-c++/phononplayer/phononplayer.cpp b/pacman-c++/phononplayer/phononplayer.cpp new file mode 100644 index 0000000..1f537d6 --- /dev/null +++ b/pacman-c++/phononplayer/phononplayer.cpp @@ -0,0 +1,169 @@ +#include "phononplayer.h" +#include +#include + +AudioPlayer *PhononPlayerFactory::create(QObject *parent) +{ + return new PhononPlayer(parent); +} + +Q_EXPORT_PLUGIN2(phononplayer, PhononPlayerFactory) + +/* --------------------------------------------------------------- */ + +PhononPlayer::PhononPlayer(QObject *parent) + : AudioPlayer(parent) +{ + m_working = AudioManager::isWorking(); + m_player = new Phonon::MediaObject(this); + m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this); + Phonon::createPath(m_player, m_output); +} + +bool PhononPlayer::isWorking() const +{ + return m_working; +} + +void PhononPlayer::setMuted(bool mute) +{ + if (!isWorking()) + return; + m_output->setMuted(mute); +} + +bool PhononPlayer::isMuted() const +{ + return m_output->isMuted(); +} + +void PhononPlayer::play() +{ + m_player->play(); +} + +void PhononPlayer::play(Sound::Type sound) +{ + if (!m_working) + return; + m_player->setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound))); + play(); +} + +bool PhononPlayer::isPlaying() +{ + return m_player->state() == Phonon::PlayingState; +} + +void PhononPlayer::enqueue(Sound::Type sound) +{ + m_player->enqueue(Phonon::MediaSource(AudioManager::self()->sound(sound))); +} + +void PhononPlayer::pause() +{ + m_player->pause(); +} + +bool PhononPlayer::isPaused() +{ + return m_player->state() == Phonon::PausedState; +} + +void PhononPlayer::stop() +{ + m_player->stop(); +} + +bool PhononPlayer::isStopped() +{ + return m_player->state() == Phonon::StoppedState; +} + +void PhononPlayer::clear() +{ + m_player->clear(); +} + +void PhononPlayer::clearQueue() +{ + m_player->clearQueue(); +} + +void PhononPlayer::setPrefinishMark(qint32 msecToEnd) +{ + connect(m_player, SIGNAL(prefinishMarkReached(qint32)), this, SLOT(prefinishMarkReached_ex(qint32)), Qt::UniqueConnection); + m_player->setPrefinishMark(msecToEnd); +} + +/* this is a simple hack to check if phonon can actually play sounds.. */ +void PhononPlayer::test(QFile *testsound, qint32 length) +{ + m_player->stop(); + m_output->setVolume(0); + m_player->setCurrentSource(Phonon::MediaSource(testsound)); + connect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); + m_player->play(); + + QTimer timer; + timer.setSingleShot(true); + connect(&timer, SIGNAL(timeout()), this, SLOT(testFinished())); + timer.start(length); + while(timer.isActive()) + { + qApp->processEvents(); + Sleeper::msleep(1); + } + clear(); +} + +void PhononPlayer::prefinishMarkReached_ex(qint32 mark) +{ + emit prefinishMarkReached(mark); +} + +void PhononPlayer::finished_ex() +{ + emit finished(); +} + +void PhononPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State oldstate) +{ + if (newstate == Phonon::PlayingState) + m_player->pause(); + if (oldstate == Phonon::PlayingState && newstate == Phonon::PausedState) + m_player->stop(); + else if (oldstate == Phonon::PausedState && newstate == Phonon::StoppedState) + { + m_working = true; + m_player->stop(); + m_output->setVolume(1); + qDebug() << "Sound is working for you!"; + disconnect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); + } +} + +void PhononPlayer::testFinished() +{ + if (!m_working) + qWarning() << "There's no sound for you :("; + disconnect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); +} + +/* --------------------------------------------------------------- */ + +void PhononPlayer::Sleeper::sleep(unsigned long secs) +{ + QThread::sleep(secs); +} + +void PhononPlayer::Sleeper::msleep(unsigned long msecs) +{ + QThread::msleep(msecs); +} + +void PhononPlayer::Sleeper::usleep(unsigned long usecs) +{ + QThread::usleep(usecs); +} + diff --git a/pacman-c++/phononplayer/phononplayer.h b/pacman-c++/phononplayer/phononplayer.h new file mode 100644 index 0000000..ca56726 --- /dev/null +++ b/pacman-c++/phononplayer/phononplayer.h @@ -0,0 +1,71 @@ +#ifndef PHONONPLAYER_H +#define PHONONPLAYER_H + +#include "audio.h" +#include +#include +#include +#include +#include + +class PhononPlayerFactory + : public QObject, public AudioPlayerFactory +{ + Q_OBJECT + Q_INTERFACES(AudioPlayerFactory) + +public: + virtual AudioPlayer *create(QObject *parent = 0); +}; + +/* --------------------------------------------------------------- */ + +class PhononPlayer + : public AudioPlayer +{ + Q_OBJECT + friend class AudioManager; + +private: + class Sleeper + : public QThread + { + public: + static void sleep(unsigned long secs); + static void msleep(unsigned long msecs); + static void usleep(unsigned long usecs); + }; + +public: + PhononPlayer(QObject *parent = 0); + virtual bool isWorking() const; + virtual void setMuted(bool mute = true); + virtual bool isMuted() const; + virtual void play(); + virtual void play(Sound::Type sound); + virtual bool isPlaying(); + virtual void enqueue(Sound::Type sound); + virtual void pause(); + virtual bool isPaused(); + virtual void stop(); + virtual bool isStopped(); + virtual void clear(); + virtual void clearQueue(); + virtual void setPrefinishMark(qint32 msecToEnd); + +protected: + void test(QFile *testsound, qint32 length); + +protected slots: + virtual void prefinishMarkReached_ex(qint32 mark); + void finished_ex(); + void testFinished(); + void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate); + +protected: + bool m_working; + Phonon::MediaObject *m_player; + Phonon::AudioOutput *m_output; +}; + +#endif // PHONONPLAYER_H diff --git a/pacman-c++/phononplayer/phononplayer.pro b/pacman-c++/phononplayer/phononplayer.pro new file mode 100644 index 0000000..9482454 --- /dev/null +++ b/pacman-c++/phononplayer/phononplayer.pro @@ -0,0 +1,11 @@ +TEMPLATE = lib +TARGET = $$qtLibraryTarget(phononplayer) +CONFIG += plugin + +DEFINES += PACMAN_AUDIO +QT += phonon + +include(../common.pri) + +SOURCES += phononplayer.cpp +HEADERS += phononplayer.h diff --git a/pacman-c++/proto/proto.pro b/pacman-c++/proto/proto.pro index 7c0b334..85d9ef7 100644 --- a/pacman-c++/proto/proto.pro +++ b/pacman-c++/proto/proto.pro @@ -5,5 +5,4 @@ include(../common.pri) PROTOS = pacman.proto include(protobuf.pri) -LIBS += -lprotobuf OTHER_FILES += $${PROTOS} diff --git a/pacman-c++/rebuild.sh b/pacman-c++/rebuild.sh index 01454ed..2f18663 100755 --- a/pacman-c++/rebuild.sh +++ b/pacman-c++/rebuild.sh @@ -2,5 +2,5 @@ mkdir -p build cd build #make distclean -qmake CONFIG+=debug ../pacman.pro +qmake CONFIG+=release ../pacman.pro make -j2 diff --git a/pacman-c++/rebuild_debug.sh b/pacman-c++/rebuild_debug.sh new file mode 100755 index 0000000..5c5486b --- /dev/null +++ b/pacman-c++/rebuild_debug.sh @@ -0,0 +1,6 @@ +#!/bin/sh +mkdir -p build_debug +cd build_debug +#make distclean +qmake CONFIG+=debug ../pacman.pro +make -j2 diff --git a/pacman-c++/server/server.cpp b/pacman-c++/server/server.cpp index 65db87d..f9502ba 100644 --- a/pacman-c++/server/server.cpp +++ b/pacman-c++/server/server.cpp @@ -760,7 +760,7 @@ void Server::initRoundMap() disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame())); - AudioManager::self()->play(Sound::Intro, true); + AudioManager::self()->audioPlayer()->play(Sound::Intro); m_tickTimer->start(); } @@ -782,7 +782,7 @@ void Server::stopGame(bool delay) { disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(stopGame())); - AudioManager::self()->play(Sound::Die, true); + AudioManager::self()->audioPlayer()->play(Sound::Die); return; } @@ -962,14 +962,17 @@ int main(int argc, char **argv) qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); int ret = 0; - Server server; - if (!ret && !server.parseCommandline()) + Server *server = new Server; + if (!ret && !server->parseCommandline()) ret = 1; - if (!ret && !server.run()) + if (!ret && !server->run()) ret = 1; if (!ret) ret = app.exec(); + /* delete server so that we'll disconnect all clients before enet deinitialize */ + delete server; + enet_deinitialize(); /* Delete all global objects allocated by libprotobuf */ diff --git a/pacman-c++/server/server.pro b/pacman-c++/server/server.pro index 3e80423..23b88fc 100644 --- a/pacman-c++/server/server.pro +++ b/pacman-c++/server/server.pro @@ -1,8 +1,11 @@ TEMPLATE = app TARGET = pacman-server - win32:CONFIG += console +DEFINES += PACMAN_SERVER + +QT += network + SOURCES += anyoption.cpp \ server.cpp HEADERS += anyoption.h \ -- cgit v1.2.3