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++/common/audio.cpp | 262 ++++++++++++++++++++++---------------------- 1 file changed, 133 insertions(+), 129 deletions(-) (limited to 'pacman-c++/common/audio.cpp') 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); -} -- cgit v1.2.3