summaryrefslogtreecommitdiffstats
path: root/pacman-c++/common/audio.cpp
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2011-05-10 22:28:58 +0200
committermanuel <manuel@mausz.at>2011-05-10 22:28:58 +0200
commit1a6c940ed9d7f6136da0e13148314072665342c5 (patch)
tree467b259d966ea1ddf9f66440066f57cf3eed68c4 /pacman-c++/common/audio.cpp
parentcc1bb779661217171418adb0ddbd1ce01815463b (diff)
downloadfoop-1a6c940ed9d7f6136da0e13148314072665342c5.tar.gz
foop-1a6c940ed9d7f6136da0e13148314072665342c5.tar.bz2
foop-1a6c940ed9d7f6136da0e13148314072665342c5.zip
- 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
Diffstat (limited to 'pacman-c++/common/audio.cpp')
-rw-r--r--pacman-c++/common/audio.cpp262
1 files changed, 133 insertions, 129 deletions
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 @@
1#include "audio.h" 1#include "audio.h"
2#include "constants.h" 2#include "constants.h"
3#include <phonon/AudioOutput>
4#include <QCoreApplication> 3#include <QCoreApplication>
5#include <QTimer> 4#include <QTimer>
6#include <QFile> 5#include <QFile>
7#include <QDir> 6#include <QDir>
8#include <QDebug> 7#include <QDebug>
8#include <QLibrary>
9#include <QPluginLoader>
9 10
10/* the universe's only audio manager */ 11/* the universe's only audio manager */
11AudioManager *AudioManager::m_instance = NULL; 12AudioManager *AudioManager::m_instance = NULL;
@@ -17,16 +18,22 @@ AudioManager::AudioManager()
17 if (Constants::server) 18 if (Constants::server)
18 { 19 {
19 qDebug() << "Server has no sound"; 20 qDebug() << "Server has no sound";
20 m_players.append(new AudioPlayer(this)); 21 m_players.append(new FakeAudioPlayer(this));
22 return;
21 } 23 }
22 else 24
25 preload();
26 if (!tryLoadPhononPlugin())
23 { 27 {
24 preload(); 28 qWarning() << "Unable to load audio plugin. Audio disabled..";
25 AudioPlayer *firstplayer = new AudioPlayer(this); 29 m_players.append(new NoopAudioPlayer(this));
26 firstplayer->test(m_sounds[Sound::WakaWaka]); 30 return;
27 m_working = firstplayer->m_working;
28 m_players.append(firstplayer);
29 } 31 }
32
33 AudioPlayer *firstplayer = m_factory->create(this);
34 firstplayer->test(m_sounds[Sound::EatingFruit], Sound::length[Sound::EatingFruit] * 2);
35 m_working = firstplayer->isWorking();
36 m_players.append(firstplayer);
30 m_muted = false; 37 m_muted = false;
31} 38}
32 39
@@ -37,7 +44,7 @@ AudioManager *AudioManager::self()
37 return m_instance; 44 return m_instance;
38} 45}
39 46
40bool AudioManager::isWorking() const 47bool AudioManager::isWorking()
41{ 48{
42 return m_working; 49 return m_working;
43} 50}
@@ -98,18 +105,6 @@ AudioPlayer *AudioManager::audioPlayer()
98 return m_players.at(0); 105 return m_players.at(0);
99} 106}
100 107
101void AudioManager::play(Sound::Type sound, bool wait)
102{
103 audioPlayer()->play(sound, wait);
104}
105
106void AudioManager::enqueue(Sound::Type sound)
107{
108 if (!isWorking())
109 return;
110 audioPlayer()->enqueue(Phonon::MediaSource(m_sounds[sound]));
111}
112
113void AudioManager::registerAudioPlayer(AudioPlayer *player) 108void AudioManager::registerAudioPlayer(AudioPlayer *player)
114{ 109{
115 player->setMuted(m_muted); 110 player->setMuted(m_muted);
@@ -123,6 +118,13 @@ void AudioManager::unregisterAudioPlayer(AudioPlayer *player)
123 m_players.removeAll(player); 118 m_players.removeAll(player);
124} 119}
125 120
121QFile *AudioManager::sound(Sound::Type sound)
122{
123 if (!isWorking())
124 return NULL;
125 return m_sounds.at(sound);
126}
127
126void AudioManager::unregisterAudioPlayer_helper(QObject *player) 128void AudioManager::unregisterAudioPlayer_helper(QObject *player)
127{ 129{
128 unregisterAudioPlayer(static_cast<AudioPlayer *>(player)); 130 unregisterAudioPlayer(static_cast<AudioPlayer *>(player));
@@ -132,141 +134,160 @@ void AudioManager::preload()
132{ 134{
133 m_sounds.clear(); 135 m_sounds.clear();
134 QDir sounds(":/sound"); 136 QDir sounds(":/sound");
137 Q_ASSERT(sounds.count() > 0);
135 for(unsigned i = 1; i <= sounds.count(); ++i) 138 for(unsigned i = 1; i <= sounds.count(); ++i)
136 m_sounds.append(new QFile(QString(":/sound/sound%1").arg(i), this)); 139 m_sounds.append(new QFile(QString(":/sound/sound%1").arg(i), this));
137} 140}
138 141
139QFile *AudioManager::sound(Sound::Type sound) 142bool AudioManager::tryLoadPhononPlugin()
140{ 143{
141 if (!isWorking()) 144 QDir dir = qApp->applicationDirPath();
145 QStringList filters;
146 filters << "*phononplayer*";
147 foreach (QString file, dir.entryList(filters, QDir::Files))
148 {
149 file = dir.absoluteFilePath(file);
150 if (!QLibrary::isLibrary(file))
151 continue;
152 QPluginLoader pluginloader(file);
153 if (pluginloader.load())
154 {
155 qDebug() << "Audio plugin loaded" << file;
156 QObject *plugin = pluginloader.instance();
157 m_factory = qobject_cast<AudioPlayerFactory *>(plugin);
158 if (m_factory != NULL)
159 return true;
160 }
161 qDebug() << "Unable to load audio plugin:" << file << pluginloader.errorString();
162 }
163 return false;
164}
165
166AudioPlayer *AudioManager::createAudioPlayer()
167{
168 if (m_factory == NULL)
142 return NULL; 169 return NULL;
143 return m_sounds.at(sound); 170
171 AudioPlayer *player = m_factory->create(this);
172 registerAudioPlayer(player);
173 return player;
144} 174}
145 175
146/* --------------------------------------------------------------- */ 176/* --------------------------------------------------------------- */
147 177
148AudioPlayer::AudioPlayer(QObject *parent) 178AudioPlayer *NoopAudioPlayerFactory::create(QObject *parent)
149 : Phonon::MediaObject(parent), m_working(false)
150{ 179{
151 if (!Constants::server) 180 return new FakeAudioPlayer(parent);
152 {
153 m_working = AudioManager::m_working;
154 m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
155 Phonon::createPath(this, m_output);
156 }
157} 181}
158 182
159bool AudioPlayer::isWorking() const 183/* --------------------------------------------------------------- */
184
185NoopAudioPlayer::NoopAudioPlayer(QObject *parent)
186 : AudioPlayer(parent), m_working(false), m_muted(false), m_playing(false), m_paused(false)
187{}
188
189bool NoopAudioPlayer::isWorking() const
160{ 190{
161 return m_working; 191 return m_working;
162} 192}
163 193
164void AudioPlayer::setMuted(bool mute) 194void NoopAudioPlayer::setMuted(bool mute)
165{ 195{
166 m_output->setMuted(mute); 196 m_muted = mute;
167} 197}
168 198
169bool AudioPlayer::isMuted() const 199bool NoopAudioPlayer::isMuted() const
170{ 200{
171 return m_output->isMuted(); 201 return m_muted;
172} 202}
173 203
174void AudioPlayer::setLoop(QFile *sound) 204void NoopAudioPlayer::play()
175{ 205{
176 if (!isWorking()) 206 m_playing = true;
177 return; 207 m_paused = false;
178 208 emit finished();
179 if (sound == NULL) 209 m_playing = false;
180 { 210}
181 disconnect(this, SIGNAL(aboutToFinish()), this, SLOT(loopEnqueue()));
182 return;
183 }
184 211
185 m_loopsound = sound; 212void NoopAudioPlayer::play(Sound::Type /* sound */)
186 connect(this, SIGNAL(aboutToFinish()), this, SLOT(loopEnqueue())); 213{
187 setCurrentSource(Phonon::MediaSource(m_loopsound)); 214 play();
188 enqueue(Phonon::MediaSource(m_loopsound));
189} 215}
190 216
191void AudioPlayer::setLoop(Sound::Type sound) 217bool NoopAudioPlayer::isPlaying()
192{ 218{
193 setLoop(AudioManager::self()->sound(sound)); 219 return m_playing;
194} 220}
195 221
196void AudioPlayer::play() 222void NoopAudioPlayer::enqueue(Sound::Type /* sound */)
223{}
224
225void NoopAudioPlayer::pause()
197{ 226{
198 Phonon::MediaObject::play(); 227 m_paused = true;
228 m_playing = false;
199} 229}
200 230
201void AudioPlayer::play(Sound::Type sound, bool wait) 231bool NoopAudioPlayer::isPaused()
202{ 232{
203 if (m_working) 233 return m_paused;
204 {
205 setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound)));
206 play();
207 }
208 else if (wait)
209 {
210 QTimer *timer = new QTimer(this);
211 timer->setSingleShot(true);
212 unsigned int interval = Sound::length[sound];
213 /* add a small delay server side only */
214 if (Constants::server)
215 interval += Constants::tick;
216 timer->setInterval(interval);
217 connect(timer, SIGNAL(timeout()), this, SLOT(finished_ex()));
218 timer->start();
219 }
220} 234}
221 235
222/* this is a simple hack to check if phonon can actually play sounds.. */ 236void NoopAudioPlayer::stop()
223void AudioPlayer::test(QFile *testsound)
224{ 237{
225 stop(); 238 m_paused = false;
226 m_output->setVolume(0); 239 m_playing = false;
227 setCurrentSource(Phonon::MediaSource(testsound)); 240}
228 connect(this, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State,Phonon::State)));
229 play();
230 241
231 QTimer timer; 242bool NoopAudioPlayer::isStopped()
232 timer.setSingleShot(true); 243{
233 connect(&timer, SIGNAL(timeout()), this, SLOT(testFinished())); 244 return !m_playing && !m_paused;
234 timer.start(500);
235 while(timer.isActive())
236 {
237 qApp->processEvents();
238 Sleeper::msleep(1);
239 }
240 clear();
241} 245}
242 246
243void AudioPlayer::finished_ex() 247void NoopAudioPlayer::clear()
248{}
249
250void NoopAudioPlayer::clearQueue()
251{}
252
253void NoopAudioPlayer::setPrefinishMark(qint32 /* msecToEnd */)
254{}
255
256void NoopAudioPlayer::prefinishMarkReached_ex(qint32 mark)
244{ 257{
245 emit finished(); 258 emit prefinishMarkReached(mark);
246} 259}
247 260
248void AudioPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State /* oldstate */) 261void NoopAudioPlayer::test(QFile * /* testsound */, qint32 /* length */)
262{}
263
264/* --------------------------------------------------------------- */
265
266FakeAudioPlayer::FakeAudioPlayer(QObject *parent)
267 : NoopAudioPlayer(parent)
249{ 268{
250 if (newstate != Phonon::ErrorState) 269 m_working = true;
251 { 270 connect(&m_timer, SIGNAL(timeout()), this, SLOT(finished_ex()));
252 m_working = true;
253 m_output->setVolume(1);
254 qDebug() << "Sound is working for you!";
255 }
256 disconnect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State)));
257 stop();
258} 271}
259 272
260void AudioPlayer::testFinished() 273void FakeAudioPlayer::play(Sound::Type sound)
261{ 274{
262 if (!m_working) 275 m_playing = true;
263 qWarning() << "There's no sound for you :("; 276 m_paused = false;
264 disconnect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State))); 277
278 m_timer.setSingleShot(true);
279 unsigned int interval = Sound::length[sound];
280 /* add a small delay server side only */
281 if (Constants::server)
282 interval += Constants::tick;
283 m_timer.setInterval(interval);
284 m_timer.start();
265} 285}
266 286
267void AudioPlayer::loopEnqueue() 287void FakeAudioPlayer::finished_ex()
268{ 288{
269 enqueue(Phonon::MediaSource(m_loopsound)); 289 m_playing = false;
290 emit finished();
270} 291}
271 292
272/* --------------------------------------------------------------- */ 293/* --------------------------------------------------------------- */
@@ -274,12 +295,12 @@ void AudioPlayer::loopEnqueue()
274GaplessAudioPlayer::GaplessAudioPlayer(Sound::Type sound, qint32 mark, QObject *parent) 295GaplessAudioPlayer::GaplessAudioPlayer(Sound::Type sound, qint32 mark, QObject *parent)
275 : QObject(parent), m_sound(sound) 296 : QObject(parent), m_sound(sound)
276{ 297{
277 m_working = AudioManager::m_working; 298 m_working = AudioManager::isWorking();
278 if (!m_working) 299 if (!m_working)
279 return; 300 return;
280 301
281 m_player1 = new AudioPlayer(this); 302 m_player1 = AudioManager::self()->createAudioPlayer();
282 m_player2 = new AudioPlayer(this); 303 m_player2 = AudioManager::self()->createAudioPlayer();
283 304
284 m_player2->setPrefinishMark(mark); 305 m_player2->setPrefinishMark(mark);
285 m_player1->setPrefinishMark(mark); 306 m_player1->setPrefinishMark(mark);
@@ -313,7 +334,7 @@ void GaplessAudioPlayer::play()
313{ 334{
314 if (!m_working) 335 if (!m_working)
315 return; 336 return;
316 if (m_player1->state() != Phonon::PlayingState && m_player2->state() != Phonon::PlayingState) 337 if (!m_player1->isPlaying() && !m_player2->isPlaying())
317 startPlayer1(); 338 startPlayer1();
318} 339}
319 340
@@ -321,9 +342,9 @@ void GaplessAudioPlayer::pause()
321{ 342{
322 if (!m_working) 343 if (!m_working)
323 return; 344 return;
324 if (m_player1->state() != Phonon::PausedState) 345 if (!m_player1->isPaused())
325 m_player1->pause(); 346 m_player1->pause();
326 if (m_player2->state() != Phonon::PausedState) 347 if (!m_player2->isPaused())
327 m_player2->pause(); 348 m_player2->pause();
328} 349}
329 350
@@ -336,20 +357,3 @@ void GaplessAudioPlayer::startPlayer2()
336{ 357{
337 m_player2->play(m_sound); 358 m_player2->play(m_sound);
338} 359}
339
340/* --------------------------------------------------------------- */
341
342void AudioPlayer::Sleeper::sleep(unsigned long secs)
343{
344 QThread::sleep(secs);
345}
346
347void AudioPlayer::Sleeper::msleep(unsigned long msecs)
348{
349 QThread::msleep(msecs);
350}
351
352void AudioPlayer::Sleeper::usleep(unsigned long usecs)
353{
354 QThread::usleep(usecs);
355}