From d0eafb0124a39eeda6c00595a943ce9811d589c4 Mon Sep 17 00:00:00 2001 From: manuel Date: Sun, 10 Apr 2011 20:50:54 +0200 Subject: major audio rewrite --- pacman-c++/actor.cpp | 43 ++++--- pacman-c++/actor.h | 5 +- pacman-c++/audio.cpp | 262 +++++++++++++++++++++++++++++++++++++++++++ pacman-c++/audio.h | 108 ++++++++++++++++++ pacman-c++/audioplayer.cpp | 187 ------------------------------ pacman-c++/audioplayer.h | 65 ----------- pacman-c++/client.cpp | 12 +- pacman-c++/mainwidget.cpp | 2 +- pacman-c++/pacman.pro | 4 +- pacman-c++/pacman.server.pro | 4 +- 10 files changed, 403 insertions(+), 289 deletions(-) create mode 100644 pacman-c++/audio.cpp create mode 100644 pacman-c++/audio.h delete mode 100644 pacman-c++/audioplayer.cpp delete mode 100644 pacman-c++/audioplayer.h (limited to 'pacman-c++') diff --git a/pacman-c++/actor.cpp b/pacman-c++/actor.cpp index bd50a3c..8184c6f 100644 --- a/pacman-c++/actor.cpp +++ b/pacman-c++/actor.cpp @@ -1,6 +1,5 @@ #include "actor.h" #include "animationmanager.h" -#include "audioplayer.h" #include #include #include @@ -12,7 +11,7 @@ static QVariant myBooleanInterpolator(const bool &start, const bool &end, qreal Actor::Actor(Color::Color color, bool local, QGraphicsItem *parent) : PixmapItem(parent), m_color(color), m_direction(Actor::None), m_local(local), - m_roundPoints(0), m_gamePoints(0) + m_player(NULL), m_roundPoints(0), m_gamePoints(0) { m_pix = ":/" + QString("actor%1").arg((m_color >> 1) + 1); /* DON'T set any pixmap here. we've a pixmap in the animation @@ -50,8 +49,16 @@ Actor::Actor(Color::Color color, bool local, QGraphicsItem *parent) m_eating.append(setupEatingAnimation(Actor::Up)); m_eating.append(setupEatingAnimation(Actor::Down)); - /* setup player */ - connect(AudioPlayer::self(), SIGNAL(aboutToFinish()), this, SLOT(enqueue())); + /* setup sound */ + if (local) + { + m_player = new AudioPlayer(this); + if (m_player->isWorking()) + { + m_player->setLoop(Sound::WakaWaka); + AudioManager::self()->registerAudioPlayer(m_player); + } + } /* make the picture showing the current direction visible */ m_images[m_direction]->setVisible(true); @@ -159,26 +166,22 @@ void Actor::move(Actor::Movement direction) if (direction == Actor::None) m_images[m_direction]->setVisible(true); else - { m_eating[direction]->start(); - } - m_direction = direction; } if (direction != Actor::None) { - if (m_local && AudioPlayer::self()->state() != Phonon::PlayingState) - { - AudioPlayer::self()->clear(); - AudioPlayer::self()->play(AudioPlayer::WakaWaka); - AudioPlayer::self()->enqueue(AudioPlayer::WakaWaka); - } + if (m_local && m_player->isWorking() && m_player->state() != Phonon::PlayingState) + m_player->play(); m_moving->start(); } - else + else if (direction != m_direction) { - AudioPlayer::self()->stop(); + if (m_local && m_player->isWorking() && m_player->state() != Phonon::PausedState) + m_player->pause(); } + + m_direction = direction; } bool Actor::isMoving() @@ -186,22 +189,16 @@ bool Actor::isMoving() return (m_moving->state() == QAbstractAnimation::Running); } -void Actor::enqueue() -{ - if (isMoving()) - AudioPlayer::self()->enqueue(AudioPlayer::WakaWaka); -} - void Actor::die() { if (!m_local) return; - AudioPlayer::self()->play(AudioPlayer::Die); + AudioManager::self()->play(Sound::Die); } void Actor::eatingCherry() { if (!m_local) return; - AudioPlayer::self()->play(AudioPlayer::EatingCherry); + AudioManager::self()->play(Sound::EatingCherry); } diff --git a/pacman-c++/actor.h b/pacman-c++/actor.h index 965d240..78b7c01 100644 --- a/pacman-c++/actor.h +++ b/pacman-c++/actor.h @@ -3,6 +3,7 @@ #include "pixmapitem.h" #include "constants.h" +#include "audio.h" #include #include #include @@ -39,15 +40,13 @@ public: void addRoundPoints(unsigned int amount) { m_roundPoints += amount; } void finishRound() { m_gamePoints += m_roundPoints; m_roundPoints = 0; } -private slots: - void enqueue(); - private: QPixmap m_pix; Color::Color m_color; Movement m_direction; PixmapItem m_icon; bool m_local; + AudioPlayer *m_player; unsigned int m_roundPoints, m_gamePoints; diff --git a/pacman-c++/audio.cpp b/pacman-c++/audio.cpp new file mode 100644 index 0000000..0692cd1 --- /dev/null +++ b/pacman-c++/audio.cpp @@ -0,0 +1,262 @@ +#include "audio.h" +#include +#include +#include +#include +#include +#include + +/* the universe's only audio manager */ +AudioManager *AudioManager::m_instance = NULL; +bool AudioManager::m_working = false; + +AudioManager::AudioManager() + : m_muted(true) +{ +#ifndef SERVER + preload(); + + AudioPlayer *firstplayer = new AudioPlayer(this); + firstplayer->test(m_sounds[Sound::WakaWaka]); + m_working = firstplayer->m_working; + m_players.append(firstplayer); + + m_muted = false; +#endif // SERVER +} + +AudioManager *AudioManager::self() +{ + if (m_instance == NULL) + m_instance = new AudioManager(); + return m_instance; +} + +bool AudioManager::isWorking() const +{ + return m_working; +} + +void AudioManager::setMuted(bool mute) +{ + if (!isWorking()) + return; + + if (mute == m_muted) + return; + + qDebug() << "mute"; + for(int i = 0; i < m_players.count(); ++i) + m_players.at(i)->setMuted(mute); + m_muted = mute; + emit mutedChanged(mute); +} + +bool AudioManager::isMuted() const +{ + return m_muted; +} + +void AudioManager::pause() +{ + if (!isWorking()) + return; + qDebug() << "pause"; + for(int i = 0; i < m_players.count(); ++i) + m_players.at(i)->pause(); +} + +void AudioManager::stop() +{ + if (!isWorking()) + return; + qDebug() << "stop"; + for(int i = 0; i < m_players.count(); ++i) + m_players.at(i)->stop(); +} + +void AudioManager::clear() +{ + if (!isWorking()) + return; + qDebug() << "clear"; + for(int i = 0; i < m_players.count(); ++i) + m_players.at(i)->clear(); +} + +void AudioManager::clearQueue() const +{ + if (!isWorking()) + return; + for(int i = 0; i < m_players.count(); ++i) + m_players.at(i)->clearQueue(); +} + +AudioPlayer *AudioManager::audioPlayer() +{ + return m_players.at(0); +} + +void AudioManager::play(Sound::Type sound) +{ + if (!isWorking()) + { + emit audioPlayer()->finished(); + return; + } + + qDebug() << "play"; + AudioPlayer *player = audioPlayer(); + player->setCurrentSource(Phonon::MediaSource(m_sounds[sound])); + player->play(); +} + +void AudioManager::enqueue(Sound::Type sound) +{ + if (!isWorking()) + return; + qDebug() << "manager enqueue"; + audioPlayer()->enqueue(Phonon::MediaSource(m_sounds[sound])); +} + +void AudioManager::registerAudioPlayer(AudioPlayer *player) +{ + player->setMuted(m_muted); + connect(player, SIGNAL(destroyed(QObject *)), this, SLOT(unregisterAudioPlayer_helper(QObject *))); + m_players.append(player); +} + +void AudioManager::unregisterAudioPlayer(AudioPlayer *player) +{ + disconnect(player, SIGNAL(destroyed(QObject *)), this, SLOT(unregisterAudioPlayer_helper(QObject *))); + m_players.removeAll(player); +} + +void AudioManager::unregisterAudioPlayer_helper(QObject *player) +{ + unregisterAudioPlayer(static_cast(player)); +} + +void AudioManager::preload() +{ + m_sounds.clear(); + QDir sounds(":/sound"); + 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) +{ + if (!isWorking()) + return NULL; + return m_sounds.at(sound); +} + +/* --------------------------------------------------------------- */ + +AudioPlayer::AudioPlayer(QObject *parent) + : Phonon::MediaObject(parent) +{ + m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this); + Phonon::createPath(this, m_output); + m_working = AudioManager::m_working; +} + +bool AudioPlayer::isWorking() const +{ + return m_working; +} + +void AudioPlayer::setMuted(bool mute) +{ + m_output->setMuted(mute); +} + +bool AudioPlayer::isMuted() const +{ + return m_output->isMuted(); +} + +void AudioPlayer::setLoop(QFile *sound) +{ + if (!isWorking()) + return; + + if (sound == NULL) + { + disconnect(this, SIGNAL(aboutToFinish()), this, SLOT(loopEnqueue())); + return; + } + + m_loopsound = sound; + connect(this, SIGNAL(aboutToFinish()), this, SLOT(loopEnqueue())); + setCurrentSource(Phonon::MediaSource(m_loopsound)); + enqueue(Phonon::MediaSource(m_loopsound)); +} + +void AudioPlayer::setLoop(Sound::Type sound) +{ + setLoop(AudioManager::self()->sound(sound)); +} + +/* this is a simple hack to check if phonon can actually play sounds.. */ +void AudioPlayer::test(QFile *testsound) +{ + 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(); + + QTimer timer; + timer.setSingleShot(true); + connect(&timer, SIGNAL(timeout()), this, SLOT(testFinished())); + timer.start(500); + while(timer.isActive()) + { + qApp->processEvents(); + Sleeper::msleep(1); + } + clear(); +} + +void AudioPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State /* oldstate */) +{ + 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(); +} + +void AudioPlayer::testFinished() +{ + if (!m_working) + qDebug() << "There's no sound for you :("; + disconnect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); +} + +void AudioPlayer::loopEnqueue() +{ + enqueue(Phonon::MediaSource(m_loopsound)); +} + +/* --------------------------------------------------------------- */ + +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++/audio.h b/pacman-c++/audio.h new file mode 100644 index 0000000..bea7fb8 --- /dev/null +++ b/pacman-c++/audio.h @@ -0,0 +1,108 @@ +#ifndef AUDIO_H +#define AUDIO_H + +#include +#include +#include +#include +#include + +namespace Phonon +{ + class AudioOutput; +} + +namespace Sound +{ + enum Type + { + Intro = 0, + WakaWaka, + EatingCherry, + Die + }; +}; + +class AudioPlayer + : public Phonon::MediaObject +{ + 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); + bool isWorking() const; + void setMuted(bool mute = true); + bool isMuted() const; + void setLoop(QFile *sound); + void setLoop(Sound::Type sound); + +private: + void test(QFile *testsound); + +public slots: + void loopEnqueue(); + +private slots: + void testFinished(); + void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate); + +private: + bool m_working; + QFile *m_loopsound; + Phonon::AudioOutput *m_output; +}; + +class AudioManager + : public QObject +{ + Q_OBJECT + friend class AudioPlayer; + +public: + AudioManager(); + static AudioManager *self(); + bool isWorking() const; + void setMuted(bool mute = true); + bool isMuted() const; + void pause(); + void stop(); + void clear(); + void clearQueue() const; + + AudioPlayer *audioPlayer(); + void play(Sound::Type sound); + void enqueue(Sound::Type sound); + + void registerAudioPlayer(AudioPlayer *player); + void unregisterAudioPlayer(AudioPlayer *player); + +signals: + void mutedChanged(bool muted); + +private slots: + void unregisterAudioPlayer_helper(QObject *player); + +private: + void preload(); + QFile *sound(Sound::Type sound); + +private: + bool m_muted; + static bool m_working; + static AudioManager *m_instance; + QList m_sounds; + QList m_players; +}; + +#endif // AUDIOPLAYER_H diff --git a/pacman-c++/audioplayer.cpp b/pacman-c++/audioplayer.cpp deleted file mode 100644 index c360a23..0000000 --- a/pacman-c++/audioplayer.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "audioplayer.h" -#include -#include -#include -#include -#include -#include -#include -#include - -class Sleeper - : public QThread -{ -public: - static void sleep(unsigned long secs) - { - QThread::sleep(secs); - } - - static void msleep(unsigned long msecs) - { - QThread::msleep(msecs); - } - - static void usleep(unsigned long usecs) - { - QThread::usleep(usecs); - } -}; - -// the universe's only audio player -AudioPlayer *AudioPlayer::m_instance = NULL; - -AudioPlayer::AudioPlayer() - : m_working(false) -{ -#ifndef SERVER - m_player = new Phonon::MediaObject(this); - connect(m_player, SIGNAL(finished()), this, SLOT(finished_p())); - connect(m_player, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish_p())); - - m_output = new Phonon::AudioOutput(Phonon::MusicCategory, m_player); - connect(m_output, SIGNAL(mutedChanged(bool)), this, SLOT(mutedChanged_p(bool))); - - Phonon::createPath(m_player, m_output); - - preload(); - test(); -#endif // SERVER -} - -AudioPlayer *AudioPlayer::self() -{ - if (!m_instance) - m_instance = new AudioPlayer(); - return m_instance; -} - -bool AudioPlayer::isWorking() const -{ - return m_working; -} - -void AudioPlayer::stop() -{ - if (!isWorking()) - return; - m_player->stop(); -} - -void AudioPlayer::setMuted(bool mute) -{ - if (!isWorking()) - return; - m_output->setMuted(mute); -} - -bool AudioPlayer::isMuted() const -{ - if (!isWorking()) - return true; - return m_output->isMuted(); -} - -void AudioPlayer::play(AudioPlayer::Sound sound) -{ - if (!isWorking()) - { - emit finished_p(); - return; - } - - m_player->stop(); - m_player->setCurrentSource(Phonon::MediaSource(m_sounds[sound])); - m_player->play(); -} - -void AudioPlayer::clear() -{ - if (!isWorking()) - return; - m_player->clear(); -} - -void AudioPlayer::enqueue(AudioPlayer::Sound sound) -{ - if (!isWorking()) - return; - m_player->enqueue(Phonon::MediaSource(m_sounds[sound])); -} - -void AudioPlayer::clearQueue() const -{ - if (!isWorking()) - return; - m_player->clearQueue(); -} - -Phonon::State AudioPlayer::state() -{ - if (!isWorking()) - return Phonon::ErrorState; - return m_player->state(); -} - -void AudioPlayer::preload() -{ - m_sounds.clear(); - QDir sounds(":/sound"); - for(unsigned i = 1; i <= sounds.count(); ++i) - m_sounds.append(new QFile(QString(":/sound/sound%1").arg(i), m_player)); -} - -/* this is a simple hack to check if phonon can actually play sounds.. */ -void AudioPlayer::test() -{ - m_player->stop(); - connect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_p(Phonon::State, Phonon::State))); - m_output->setVolume(0); - m_player->setCurrentSource(Phonon::MediaSource(m_sounds[AudioPlayer::WakaWaka])); - m_player->play(); - - QTimer timer; - timer.setSingleShot(true); - connect(&timer, SIGNAL(timeout()), this, SLOT(testFinished())); - timer.start(500); - while(timer.isActive()) - { - qApp->processEvents(); - Sleeper::msleep(1); - } -} - -void AudioPlayer::finished_p() -{ - emit finished(); -} - -void AudioPlayer::aboutToFinish_p() -{ - emit aboutToFinish(); -} - -void AudioPlayer::stateChanged_p(Phonon::State newstate, Phonon::State /* oldstate */) -{ - if (newstate != Phonon::ErrorState) - { - m_working = true; - m_output->setVolume(1); - qDebug() << "Sound is working for you!"; - } - disconnect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_p(Phonon::State, Phonon::State))); - m_player->stop(); -} - -void AudioPlayer::testFinished() -{ - if (!m_working) - qDebug() << "There's no sound for you :("; - disconnect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_p(Phonon::State, Phonon::State))); -} - - -void AudioPlayer::mutedChanged_p(bool muted) -{ - emit mutedChanged(muted); -} diff --git a/pacman-c++/audioplayer.h b/pacman-c++/audioplayer.h deleted file mode 100644 index 474b6ca..0000000 --- a/pacman-c++/audioplayer.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef AUDIOPLAYER_H -#define AUDIOPLAYER_H - -#include -#include -#include -#include - -namespace Phonon -{ - class MediaObject; - class AudioOutput; -} - -class AudioPlayer - : public QObject -{ - Q_OBJECT - -public: - enum Sound { - Intro = 0, - WakaWaka, - EatingCherry, - Die - }; - -public: - AudioPlayer(); - static AudioPlayer *self(); - bool isWorking() const; - void stop(); - void setMuted(bool mute = true); - bool isMuted() const; - void play(Sound sound); - void clear(); - void enqueue(Sound sound); - void clearQueue() const; - Phonon::State state(); - -signals: - void finished(); - void aboutToFinish(); - void mutedChanged(bool muted); - -private: - void test(); - void preload(); - -private slots: - void finished_p(); - void aboutToFinish_p(); - void stateChanged_p(Phonon::State newstate, Phonon::State oldstate); - void mutedChanged_p(bool muted); - void testFinished(); - -private: - bool m_working; - Phonon::MediaObject *m_player; - Phonon::AudioOutput *m_output; - static AudioPlayer *m_instance; - QList m_sounds; -}; - -#endif // AUDIOPLAYER_H diff --git a/pacman-c++/client.cpp b/pacman-c++/client.cpp index c35510a..394b446 100644 --- a/pacman-c++/client.cpp +++ b/pacman-c++/client.cpp @@ -1,6 +1,6 @@ #include "client.h" #include "clicklabel.h" -#include "audioplayer.h" +#include "audio.h" #include "pacman.pb.h" Client::Client() @@ -25,9 +25,9 @@ void Client::createMenu() toggleSound->setFixedHeight(16); toggleSound->setAlignment(Qt::AlignBottom); - bool sound = AudioPlayer::self()->isWorking(); + bool sound = AudioManager::self()->isWorking(); bool muted = !(sound && m_settings->value("muted", false).toBool()); - AudioPlayer::self()->setMuted(muted); + AudioManager::self()->setMuted(muted); QImage img(muted ? ":/soundoff" : ":/soundon"); img.setColor(1, menuBar()->palette().color( @@ -38,7 +38,7 @@ void Client::createMenu() if (sound) { connect(toggleSound, SIGNAL(clicked()), this, SLOT(toggleSound())); - connect(AudioPlayer::self(), SIGNAL(mutedChanged(bool)), this, SLOT(mutedChanged(bool))); + connect(AudioManager::self(), SIGNAL(mutedChanged(bool)), this, SLOT(mutedChanged(bool))); } menuBar()->setCornerWidget(toggleSound); @@ -46,9 +46,9 @@ void Client::createMenu() void Client::toggleSound() const { - if (!AudioPlayer::self()->isWorking()) + if (!AudioManager::self()->isWorking()) return; - AudioPlayer::self()->setMuted(!AudioPlayer::self()->isMuted()); + AudioManager::self()->setMuted(!AudioManager::self()->isMuted()); } void Client::mutedChanged(bool muted) const diff --git a/pacman-c++/mainwidget.cpp b/pacman-c++/mainwidget.cpp index c21e81d..ebd0f02 100644 --- a/pacman-c++/mainwidget.cpp +++ b/pacman-c++/mainwidget.cpp @@ -2,7 +2,7 @@ #include "actor.h" #include "block.h" #include "constants.h" -#include "audioplayer.h" +#include "audio.h" #include "util.h" #include "pacman.pb.h" diff --git a/pacman-c++/pacman.pro b/pacman-c++/pacman.pro index a346f20..45592c5 100644 --- a/pacman-c++/pacman.pro +++ b/pacman-c++/pacman.pro @@ -11,7 +11,7 @@ SOURCES += pixmapitem.cpp \ bonuspoint.cpp \ mainwidget.cpp \ point.cpp \ - audioplayer.cpp \ + audio.cpp \ clicklabel.cpp \ sceneholder.cpp \ util.cpp @@ -24,7 +24,7 @@ HEADERS += pixmapitem.h \ mainwidget.h \ constants.h \ point.h \ - audioplayer.h \ + audio.h \ clicklabel.h \ sceneholder.h \ util.h diff --git a/pacman-c++/pacman.server.pro b/pacman-c++/pacman.server.pro index 631bc50..4284286 100644 --- a/pacman-c++/pacman.server.pro +++ b/pacman-c++/pacman.server.pro @@ -14,7 +14,7 @@ SOURCES += pixmapitem.cpp \ bonuspoint.cpp \ mainwidget.cpp \ point.cpp \ - audioplayer.cpp \ + audio.cpp \ sceneholder.cpp \ util.cpp \ clicklabel.cpp @@ -27,7 +27,7 @@ HEADERS += pixmapitem.h \ mainwidget.h \ constants.h \ point.h \ - audioplayer.h \ + audio.h \ sceneholder.h \ util.h \ clicklabel.h -- cgit v1.2.3