#include "audio.h" #include "constants.h" #include #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) { if (Constants::server) { qDebug() << "Server has no sound"; m_players.append(new FakeAudioPlayer(this)); return; } preload(); if (!tryLoadAudioPlugin("*phononplayer*")) { qWarning() << "Unable to load audio plugin. Audio disabled.."; m_players.append(new NoopAudioPlayer(this)); return; } AudioPlayer *firstplayer = m_factory->create(this); firstplayer->setWorking(m_working); firstplayer->test(m_sounds[Sound::EatingFruit], Sound::length[Sound::EatingFruit] * 2); m_working = firstplayer->isWorking(); m_players.append(firstplayer); m_muted = false; } AudioManager *AudioManager::self() { if (m_instance == NULL) m_instance = new AudioManager(); return m_instance; } bool AudioManager::isWorking() { return m_working; } void AudioManager::setMuted(bool mute) { if (!isWorking()) return; if (mute == m_muted) return; 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; for(int i = 0; i < m_players.count(); ++i) m_players.at(i)->pause(); } void AudioManager::stop() { if (!isWorking()) return; for(int i = 0; i < m_players.count(); ++i) m_players.at(i)->stop(); } void AudioManager::clear() { if (!isWorking()) return; 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::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::play(Sound::Type sound, AudioPlayer *player) { if (player == NULL) player = audioPlayer(); player->play(this->sound(sound), length(sound)); } void AudioManager::setSource(Sound::Type sound, AudioPlayer *player) { if (player == NULL) player = audioPlayer(); player->setSource(this->sound(sound), length(sound)); } void AudioManager::enqueue(Sound::Type sound, AudioPlayer *player) { if (player == NULL) player = audioPlayer(); player->enqueue(this->sound(sound), length(sound)); } QFile *AudioManager::sound(Sound::Type sound) { if (!isWorking()) return NULL; return m_sounds.at(sound); } unsigned int AudioManager::length(Sound::Type sound) { return Sound::length[sound]; } 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)); Q_ASSERT(m_sounds.count() == (sizeof(Sound::length) / sizeof(unsigned int))); } bool AudioManager::tryLoadAudioPlugin(const QString &libraryname) { QDir dir = qApp->applicationDirPath(); QStringList filters; filters << libraryname; 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(QObject *parent) { if (m_factory == NULL) return NULL; AudioPlayer *player = m_factory->create(parent != NULL ? parent : this); player->setWorking(m_working); registerAudioPlayer(player); return player; } /* --------------------------------------------------------------- */ 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 NoopAudioPlayer::setMuted(bool mute) { m_muted = mute; } bool NoopAudioPlayer::isMuted() const { return m_muted; } void NoopAudioPlayer::play() { m_playing = true; m_paused = false; emit finished(); m_playing = false; } void NoopAudioPlayer::pause() { m_paused = true; m_playing = false; } bool NoopAudioPlayer::isPaused() { return m_paused; } void NoopAudioPlayer::stop() { m_paused = false; m_playing = false; } bool NoopAudioPlayer::isStopped() { return !m_playing && !m_paused; } void NoopAudioPlayer::clear() {} void NoopAudioPlayer::clearQueue() {} void NoopAudioPlayer::setPrefinishMark(qint32 /* msecToEnd */) {} void NoopAudioPlayer::prefinishMarkReached_ex(qint32 mark) { emit prefinishMarkReached(mark); } void NoopAudioPlayer::seek(qint64 /* time */) {} void NoopAudioPlayer::setWorking(bool working) { m_working = working; } void NoopAudioPlayer::test(QFile * /* sound */, unsigned int /* length */) {} void NoopAudioPlayer::play(QFile *sound, unsigned int length) { setSource(sound, length); play(); } void NoopAudioPlayer::setSource(QFile * /* sound */, unsigned int /* length */) {} bool NoopAudioPlayer::isPlaying() { return m_playing; } void NoopAudioPlayer::enqueue(QFile * /* sound */, unsigned int /* length */) {} /* --------------------------------------------------------------- */ FakeAudioPlayer::FakeAudioPlayer(QObject *parent) : NoopAudioPlayer(parent) { m_working = true; connect(&m_timer, SIGNAL(timeout()), this, SLOT(finished_ex())); } void FakeAudioPlayer::play(QFile * /* sound */, unsigned int length) { m_playing = true; m_paused = false; m_timer.setSingleShot(true); unsigned int interval = length; /* add a small delay server side only */ if (Constants::server) interval += Constants::tick; m_timer.setInterval(interval); m_timer.start(); } void FakeAudioPlayer::finished_ex() { m_playing = false; emit finished(); } /* --------------------------------------------------------------- */ GaplessAudioPlayer::GaplessAudioPlayer(Sound::Type sound, qint32 mark, QObject *parent) : QObject(parent), m_paused(false), m_sound(sound) { m_working = AudioManager::isWorking(); if (!m_working) return; m_player1 = AudioManager::self()->createAudioPlayer(this); m_player2 = AudioManager::self()->createAudioPlayer(this); /* this doesn't work reliable on all platforms (e.g. windows) */ m_player2->setPrefinishMark(mark); m_player1->setPrefinishMark(mark); connect(m_player1, SIGNAL(prefinishMarkReached(qint32)), this, SLOT(startPlayer2())); connect(m_player2, SIGNAL(prefinishMarkReached(qint32)), this, SLOT(startPlayer1())); } bool GaplessAudioPlayer::isWorking() const { return m_working; } void GaplessAudioPlayer::setMuted(bool mute) { if (!m_working) return; m_player1->setMuted(mute); m_player2->setMuted(mute); } bool GaplessAudioPlayer::isMuted() const { return m_player1->isMuted() && m_player2->isMuted(); } void GaplessAudioPlayer::play() { if (!m_working) return; m_paused = false; if (!m_player1->isPlaying() && !m_player2->isPlaying()) startPlayer1(); } void GaplessAudioPlayer::pause() { if (!m_working) return; m_paused = true; m_player1->pause(); m_player2->pause(); } void GaplessAudioPlayer::startPlayer1() { if (m_paused) return; AudioManager::self()->play(m_sound, m_player1); m_player2->pause(); } void GaplessAudioPlayer::startPlayer2() { if (m_paused) return; AudioManager::self()->play(m_sound, m_player2); m_player1->pause(); }