summaryrefslogtreecommitdiffstats
path: root/pacman-c++
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++
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++')
-rw-r--r--pacman-c++/client/client.cpp11
-rw-r--r--pacman-c++/client/client.pro2
-rw-r--r--pacman-c++/client/mainwidget.cpp2
-rw-r--r--pacman-c++/common.pri21
-rw-r--r--pacman-c++/common/actor.cpp6
-rw-r--r--pacman-c++/common/actor.h2
-rw-r--r--pacman-c++/common/audio.cpp262
-rw-r--r--pacman-c++/common/audio.h147
-rw-r--r--pacman-c++/common/common.pro2
-rw-r--r--pacman-c++/pacman.pro1
-rw-r--r--pacman-c++/phononplayer/phononplayer.cpp169
-rw-r--r--pacman-c++/phononplayer/phononplayer.h71
-rw-r--r--pacman-c++/phononplayer/phononplayer.pro11
-rw-r--r--pacman-c++/proto/proto.pro1
-rwxr-xr-xpacman-c++/rebuild.sh2
-rwxr-xr-xpacman-c++/rebuild_debug.sh6
-rw-r--r--pacman-c++/server/server.cpp13
-rw-r--r--pacman-c++/server/server.pro5
18 files changed, 539 insertions, 195 deletions
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)
272 272
273 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); 273 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
274 274
275 /* load sound */
275 AudioManager::self(); 276 AudioManager::self();
276 277
277 Client client; 278 Client *client = new Client;
278 client.show(); 279 client->show();
279 client.setWindowTitle(app.applicationName()); 280 client->setWindowTitle(app.applicationName());
280
281 int ret = app.exec(); 281 int ret = app.exec();
282 282
283 /* delete client so that we'll disconnect from server before enet deinitialize */
284 delete client;
285
283 enet_deinitialize(); 286 enet_deinitialize();
284 287
285 /* Delete all global objects allocated by libprotobuf */ 288 /* 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 @@
1TEMPLATE = app 1TEMPLATE = app
2TARGET = pacman 2TARGET = pacman
3 3
4DEFINES += PACMAN_CLIENT
5
4SOURCES += clicklabel.cpp \ 6SOURCES += clicklabel.cpp \
5 client.cpp \ 7 client.cpp \
6 mainwidget.cpp 8 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)
231 timer->setInterval(Sound::length[Sound::Intro] + Constants::tick); 231 timer->setInterval(Sound::length[Sound::Intro] + Constants::tick);
232 connect(timer, SIGNAL(timeout()), this, SLOT(startGame())); 232 connect(timer, SIGNAL(timeout()), this, SLOT(startGame()));
233 timer->start(); 233 timer->start();
234 AudioManager::self()->play(Sound::Intro, true); 234 AudioManager::self()->audioPlayer()->play(Sound::Intro);
235 } 235 }
236 236
237 Transmission::map_t map = Util::createUninitialisedMap(); 237 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 @@
1LANGUAGE = C++ 1LANGUAGE = C++
2VERSION = 0.1 2VERSION = 0.1
3 3
4QT += phonon network
5
6DESTDIR = ../ 4DESTDIR = ../
7 5
8INCLUDEPATH += ../common 6INCLUDEPATH += ../common
9DEPENDPATH += ../common 7DEPENDPATH += ../common
10LIBS += -L.. -lcommon
11
12INCLUDEPATH += $$OUT_PWD/../proto 8INCLUDEPATH += $$OUT_PWD/../proto
13LIBS += -L.. -lproto -lprotobuf
14
15INCLUDEPATH += ../enet/include 9INCLUDEPATH += ../enet/include
16LIBS += -L$$PWD/enet/.libs -lenet 10
17# enable this if you want to link the archive 11contains(TEMPLATE, app) {
18#win32:LIBS += -lws2_32 -lwinmm 12 LIBS += -L.. -lcommon
13 LIBS += -L.. -lproto -lprotobuf
14 LIBS += -L$$PWD/enet/.libs -lenet
15 # enable this if you want to link the archive
16 #win32:LIBS += -lws2_32 -lwinmm
17}
18
19contains(CONFIG, plugin) {
20 LIBS += -L.. -lcommon
21}
19 22
20CONFIG(release, debug|release) { 23CONFIG(release, debug|release) {
21 DEFINES += QT_NO_DEBUG_OUTPUT 24 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()
296 setZValue(zValue() * 10); 296 setZValue(zValue() * 10);
297 m_dieing->start(); 297 m_dieing->start();
298 if (m_local) 298 if (m_local)
299 AudioManager::self()->play(Sound::Die); 299 AudioManager::self()->audioPlayer()->play(Sound::Die);
300} 300}
301 301
302void Actor::eatingFruit() 302void Actor::eatingFruit()
303{ 303{
304 if (!m_local) 304 if (!m_local)
305 return; 305 return;
306 AudioManager::self()->play(Sound::EatingFruit); 306 AudioManager::self()->audioPlayer()->play(Sound::EatingFruit);
307} 307}
308 308
309void Actor::eatingPacman() 309void Actor::eatingPacman()
310{ 310{
311 if (!m_local) 311 if (!m_local)
312 return; 312 return;
313 AudioManager::self()->play(Sound::EatingGhost); 313 AudioManager::self()->audioPlayer()->play(Sound::EatingGhost);
314} 314}
315 315
316void Actor::startEating() 316void 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 @@
11class Actor 11class Actor
12 : public GameEntity 12 : public GameEntity
13{ 13{
14Q_OBJECT 14 Q_OBJECT
15 15
16public: 16public:
17 enum Movement 17 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 @@
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}
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 @@
4#include <QObject> 4#include <QObject>
5#include <QList> 5#include <QList>
6#include <QFile> 6#include <QFile>
7#include <QThread> 7#include <QTimer>
8#include <phonon/MediaObject>
9
10namespace Phonon
11{
12 class AudioOutput;
13}
14 8
15namespace Sound 9namespace Sound
16{ 10{
@@ -32,46 +26,98 @@ namespace Sound
32/* --------------------------------------------------------------- */ 26/* --------------------------------------------------------------- */
33 27
34class AudioPlayer 28class AudioPlayer
35 : public Phonon::MediaObject 29 : public QObject
36{ 30{
37 Q_OBJECT 31 Q_OBJECT
38 friend class AudioManager; 32 friend class AudioManager;
39 33
40private: 34public:
41 class Sleeper 35 AudioPlayer(QObject *parent = 0)
42 : public QThread 36 : QObject(parent)
43 { 37 {}
44 public: 38 virtual ~AudioPlayer()
45 static void sleep(unsigned long secs); 39 {}
46 static void msleep(unsigned long msecs); 40 virtual bool isWorking() const = 0;
47 static void usleep(unsigned long usecs); 41 virtual void setMuted(bool mute = true) = 0;
48 }; 42 virtual bool isMuted() const = 0;
43 virtual void play() = 0;
44 virtual void play(Sound::Type sound) = 0;
45 virtual bool isPlaying() = 0;
46 virtual void enqueue(Sound::Type sound) = 0;
47 virtual void pause() = 0;
48 virtual bool isPaused() = 0;
49 virtual void stop() = 0;
50 virtual bool isStopped() = 0;
51 virtual void clear() = 0;
52 virtual void clearQueue() = 0;
53 virtual void setPrefinishMark(qint32 msecToEnd) = 0;
54
55protected slots:
56 virtual void prefinishMarkReached_ex(qint32 mark) = 0;
57
58signals:
59 void finished();
60 void prefinishMarkReached(qint32 mark);
61
62protected:
63 virtual void test(QFile *testsound, qint32 length) = 0;
64};
65
66/* --------------------------------------------------------------- */
67
68class NoopAudioPlayer
69 : public AudioPlayer
70{
71 Q_OBJECT
72 friend class AudioManager;
49 73
50public: 74public:
51 AudioPlayer(QObject *parent = 0); 75 NoopAudioPlayer(QObject *parent = 0);
52 bool isWorking() const; 76 virtual bool isWorking() const;
53 void setMuted(bool mute = true); 77 virtual void setMuted(bool mute = true);
54 bool isMuted() const; 78 virtual bool isMuted() const;
55 void setLoop(Sound::Type sound); 79 virtual void play();
56 void play(); 80 virtual void play(Sound::Type sound);
57 void play(Sound::Type sound, bool wait = false); 81 virtual bool isPlaying();
82 virtual void enqueue(Sound::Type sound);
83 virtual void pause();
84 virtual bool isPaused();
85 virtual void stop();
86 virtual bool isStopped();
87 virtual void clear();
88 virtual void clearQueue();
89 virtual void setPrefinishMark(qint32 msecToEnd);
90
91protected slots:
92 virtual void prefinishMarkReached_ex(qint32 mark);
58 93
59protected: 94protected:
60 void test(QFile *testsound); 95 virtual void test(QFile *testsound, qint32 length);
61 void setLoop(QFile *sound);
62 96
63public slots: 97protected:
64 void loopEnqueue(); 98 bool m_working;
99 bool m_muted;
100 bool m_playing;
101 bool m_paused;
102};
103
104/* --------------------------------------------------------------- */
105
106class FakeAudioPlayer
107 : public NoopAudioPlayer
108{
109 Q_OBJECT
110 friend class AudioManager;
111
112public:
113 FakeAudioPlayer(QObject *parent = 0);
114 virtual void play(Sound::Type sound);
65 115
66protected slots: 116protected slots:
67 void finished_ex(); 117 void finished_ex();
68 void testFinished();
69 void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate);
70 118
71protected: 119protected:
72 bool m_working; 120 QTimer m_timer;
73 QFile *m_loopsound;
74 Phonon::AudioOutput *m_output;
75}; 121};
76 122
77/* --------------------------------------------------------------- */ 123/* --------------------------------------------------------------- */
@@ -102,17 +148,37 @@ protected:
102 148
103/* --------------------------------------------------------------- */ 149/* --------------------------------------------------------------- */
104 150
151class AudioPlayerFactory
152{
153public:
154 virtual ~AudioPlayerFactory()
155 {}
156 virtual AudioPlayer *create(QObject *parent = 0) = 0;
157};
158
159Q_DECLARE_INTERFACE(AudioPlayerFactory, "at.ac.tuwien.foop.pacman.AudioPlayerFactory/1.0");
160
161/* --------------------------------------------------------------- */
162
163class NoopAudioPlayerFactory
164 : public AudioPlayerFactory
165{
166public:
167 virtual AudioPlayer *create(QObject *parent = 0);
168};
169
170/* --------------------------------------------------------------- */
171
105class AudioManager 172class AudioManager
106 : public QObject 173 : public QObject
107{ 174{
108 Q_OBJECT 175 Q_OBJECT
109 friend class AudioPlayer;
110 friend class GaplessAudioPlayer; 176 friend class GaplessAudioPlayer;
111 177
112public: 178public:
113 AudioManager(); 179 AudioManager();
114 static AudioManager *self(); 180 static AudioManager *self();
115 bool isWorking() const; 181 static bool isWorking();
116 void setMuted(bool mute = true); 182 void setMuted(bool mute = true);
117 bool isMuted() const; 183 bool isMuted() const;
118 void pause(); 184 void pause();
@@ -121,21 +187,21 @@ public:
121 void clearQueue() const; 187 void clearQueue() const;
122 188
123 AudioPlayer *audioPlayer(); 189 AudioPlayer *audioPlayer();
124 void play(Sound::Type sound, bool wait = false);
125 void enqueue(Sound::Type sound);
126
127 void registerAudioPlayer(AudioPlayer *player); 190 void registerAudioPlayer(AudioPlayer *player);
128 void unregisterAudioPlayer(AudioPlayer *player); 191 void unregisterAudioPlayer(AudioPlayer *player);
129 192
193 QFile *sound(Sound::Type sound);
194
130signals: 195signals:
131 void mutedChanged(bool muted); 196 void mutedChanged(bool muted);
132 197
133private slots: 198private slots:
134 void unregisterAudioPlayer_helper(QObject *player); 199 void unregisterAudioPlayer_helper(QObject *player);
135 200
136private: 201protected:
137 void preload(); 202 void preload();
138 QFile *sound(Sound::Type sound); 203 bool tryLoadPhononPlugin();
204 AudioPlayer *createAudioPlayer();
139 205
140private: 206private:
141 bool m_muted; 207 bool m_muted;
@@ -143,6 +209,7 @@ private:
143 static AudioManager *m_instance; 209 static AudioManager *m_instance;
144 QList<QFile *> m_sounds; 210 QList<QFile *> m_sounds;
145 QList<AudioPlayer *> m_players; 211 QList<AudioPlayer *> m_players;
212 AudioPlayerFactory *m_factory;
146}; 213};
147 214
148#endif // AUDIOPLAYER_H 215#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 @@
1TEMPLATE = lib 1TEMPLATE = lib
2CONFIG += staticlib 2CONFIG += staticlib
3 3
4DEFINES += PACMAN_COMMON
5
4include(../common.pri) 6include(../common.pri)
5 7
6SOURCES += pixmapitem.cpp \ 8SOURCES += 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 @@
1TEMPLATE = subdirs 1TEMPLATE = subdirs
2SUBDIRS = proto \ 2SUBDIRS = proto \
3 common \ 3 common \
4 phononplayer \
4 client \ 5 client \
5 server 6 server
6CONFIG += ordered 7CONFIG += 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 @@
1#include "phononplayer.h"
2#include <QtPlugin>
3#include <QCoreApplication>
4
5AudioPlayer *PhononPlayerFactory::create(QObject *parent)
6{
7 return new PhononPlayer(parent);
8}
9
10Q_EXPORT_PLUGIN2(phononplayer, PhononPlayerFactory)
11
12/* --------------------------------------------------------------- */
13
14PhononPlayer::PhononPlayer(QObject *parent)
15 : AudioPlayer(parent)
16{
17 m_working = AudioManager::isWorking();
18 m_player = new Phonon::MediaObject(this);
19 m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
20 Phonon::createPath(m_player, m_output);
21}
22
23bool PhononPlayer::isWorking() const
24{
25 return m_working;
26}
27
28void PhononPlayer::setMuted(bool mute)
29{
30 if (!isWorking())
31 return;
32 m_output->setMuted(mute);
33}
34
35bool PhononPlayer::isMuted() const
36{
37 return m_output->isMuted();
38}
39
40void PhononPlayer::play()
41{
42 m_player->play();
43}
44
45void PhononPlayer::play(Sound::Type sound)
46{
47 if (!m_working)
48 return;
49 m_player->setCurrentSource(Phonon::MediaSource(AudioManager::self()->sound(sound)));
50 play();
51}
52
53bool PhononPlayer::isPlaying()
54{
55 return m_player->state() == Phonon::PlayingState;
56}
57
58void PhononPlayer::enqueue(Sound::Type sound)
59{
60 m_player->enqueue(Phonon::MediaSource(AudioManager::self()->sound(sound)));
61}
62
63void PhononPlayer::pause()
64{
65 m_player->pause();
66}
67
68bool PhononPlayer::isPaused()
69{
70 return m_player->state() == Phonon::PausedState;
71}
72
73void PhononPlayer::stop()
74{
75 m_player->stop();
76}
77
78bool PhononPlayer::isStopped()
79{
80 return m_player->state() == Phonon::StoppedState;
81}
82
83void PhononPlayer::clear()
84{
85 m_player->clear();
86}
87
88void PhononPlayer::clearQueue()
89{
90 m_player->clearQueue();
91}
92
93void PhononPlayer::setPrefinishMark(qint32 msecToEnd)
94{
95 connect(m_player, SIGNAL(prefinishMarkReached(qint32)), this, SLOT(prefinishMarkReached_ex(qint32)), Qt::UniqueConnection);
96 m_player->setPrefinishMark(msecToEnd);
97}
98
99/* this is a simple hack to check if phonon can actually play sounds.. */
100void PhononPlayer::test(QFile *testsound, qint32 length)
101{
102 m_player->stop();
103 m_output->setVolume(0);
104 m_player->setCurrentSource(Phonon::MediaSource(testsound));
105 connect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State)));
106 m_player->play();
107
108 QTimer timer;
109 timer.setSingleShot(true);
110 connect(&timer, SIGNAL(timeout()), this, SLOT(testFinished()));
111 timer.start(length);
112 while(timer.isActive())
113 {
114 qApp->processEvents();
115 Sleeper::msleep(1);
116 }
117 clear();
118}
119
120void PhononPlayer::prefinishMarkReached_ex(qint32 mark)
121{
122 emit prefinishMarkReached(mark);
123}
124
125void PhononPlayer::finished_ex()
126{
127 emit finished();
128}
129
130void PhononPlayer::stateChanged_ex(Phonon::State newstate, Phonon::State oldstate)
131{
132 if (newstate == Phonon::PlayingState)
133 m_player->pause();
134 if (oldstate == Phonon::PlayingState && newstate == Phonon::PausedState)
135 m_player->stop();
136 else if (oldstate == Phonon::PausedState && newstate == Phonon::StoppedState)
137 {
138 m_working = true;
139 m_player->stop();
140 m_output->setVolume(1);
141 qDebug() << "Sound is working for you!";
142 disconnect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State)));
143 }
144}
145
146void PhononPlayer::testFinished()
147{
148 if (!m_working)
149 qWarning() << "There's no sound for you :(";
150 disconnect(m_player, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged_ex(Phonon::State, Phonon::State)));
151}
152
153/* --------------------------------------------------------------- */
154
155void PhononPlayer::Sleeper::sleep(unsigned long secs)
156{
157 QThread::sleep(secs);
158}
159
160void PhononPlayer::Sleeper::msleep(unsigned long msecs)
161{
162 QThread::msleep(msecs);
163}
164
165void PhononPlayer::Sleeper::usleep(unsigned long usecs)
166{
167 QThread::usleep(usecs);
168}
169
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 @@
1#ifndef PHONONPLAYER_H
2#define PHONONPLAYER_H
3
4#include "audio.h"
5#include <QObject>
6#include <QFile>
7#include <QThread>
8#include <phonon/MediaObject>
9#include <phonon/AudioOutput>
10
11class PhononPlayerFactory
12 : public QObject, public AudioPlayerFactory
13{
14 Q_OBJECT
15 Q_INTERFACES(AudioPlayerFactory)
16
17public:
18 virtual AudioPlayer *create(QObject *parent = 0);
19};
20
21/* --------------------------------------------------------------- */
22
23class PhononPlayer
24 : public AudioPlayer
25{
26 Q_OBJECT
27 friend class AudioManager;
28
29private:
30 class Sleeper
31 : public QThread
32 {
33 public:
34 static void sleep(unsigned long secs);
35 static void msleep(unsigned long msecs);
36 static void usleep(unsigned long usecs);
37 };
38
39public:
40 PhononPlayer(QObject *parent = 0);
41 virtual bool isWorking() const;
42 virtual void setMuted(bool mute = true);
43 virtual bool isMuted() const;
44 virtual void play();
45 virtual void play(Sound::Type sound);
46 virtual bool isPlaying();
47 virtual void enqueue(Sound::Type sound);
48 virtual void pause();
49 virtual bool isPaused();
50 virtual void stop();
51 virtual bool isStopped();
52 virtual void clear();
53 virtual void clearQueue();
54 virtual void setPrefinishMark(qint32 msecToEnd);
55
56protected:
57 void test(QFile *testsound, qint32 length);
58
59protected slots:
60 virtual void prefinishMarkReached_ex(qint32 mark);
61 void finished_ex();
62 void testFinished();
63 void stateChanged_ex(Phonon::State newstate, Phonon::State oldstate);
64
65protected:
66 bool m_working;
67 Phonon::MediaObject *m_player;
68 Phonon::AudioOutput *m_output;
69};
70
71#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 @@
1TEMPLATE = lib
2TARGET = $$qtLibraryTarget(phononplayer)
3CONFIG += plugin
4
5DEFINES += PACMAN_AUDIO
6QT += phonon
7
8include(../common.pri)
9
10SOURCES += phononplayer.cpp
11HEADERS += 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)
5 5
6PROTOS = pacman.proto 6PROTOS = pacman.proto
7include(protobuf.pri) 7include(protobuf.pri)
8LIBS += -lprotobuf
9OTHER_FILES += $${PROTOS} 8OTHER_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 @@
2mkdir -p build 2mkdir -p build
3cd build 3cd build
4#make distclean 4#make distclean
5qmake CONFIG+=debug ../pacman.pro 5qmake CONFIG+=release ../pacman.pro
6make -j2 6make -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 @@
1#!/bin/sh
2mkdir -p build_debug
3cd build_debug
4#make distclean
5qmake CONFIG+=debug ../pacman.pro
6make -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()
760 760
761 disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); 761 disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL);
762 connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame())); 762 connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(startGame()));
763 AudioManager::self()->play(Sound::Intro, true); 763 AudioManager::self()->audioPlayer()->play(Sound::Intro);
764 m_tickTimer->start(); 764 m_tickTimer->start();
765} 765}
766 766
@@ -782,7 +782,7 @@ void Server::stopGame(bool delay)
782 { 782 {
783 disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL); 783 disconnect(AudioManager::self()->audioPlayer(), NULL, this, NULL);
784 connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(stopGame())); 784 connect(AudioManager::self()->audioPlayer(), SIGNAL(finished()), this, SLOT(stopGame()));
785 AudioManager::self()->play(Sound::Die, true); 785 AudioManager::self()->audioPlayer()->play(Sound::Die);
786 return; 786 return;
787 } 787 }
788 788
@@ -962,14 +962,17 @@ int main(int argc, char **argv)
962 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); 962 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
963 963
964 int ret = 0; 964 int ret = 0;
965 Server server; 965 Server *server = new Server;
966 if (!ret && !server.parseCommandline()) 966 if (!ret && !server->parseCommandline())
967 ret = 1; 967 ret = 1;
968 if (!ret && !server.run()) 968 if (!ret && !server->run())
969 ret = 1; 969 ret = 1;
970 if (!ret) 970 if (!ret)
971 ret = app.exec(); 971 ret = app.exec();
972 972
973 /* delete server so that we'll disconnect all clients before enet deinitialize */
974 delete server;
975
973 enet_deinitialize(); 976 enet_deinitialize();
974 977
975 /* Delete all global objects allocated by libprotobuf */ 978 /* 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 @@
1TEMPLATE = app 1TEMPLATE = app
2TARGET = pacman-server 2TARGET = pacman-server
3
4win32:CONFIG += console 3win32:CONFIG += console
5 4
5DEFINES += PACMAN_SERVER
6
7QT += network
8
6SOURCES += anyoption.cpp \ 9SOURCES += anyoption.cpp \
7 server.cpp 10 server.cpp
8HEADERS += anyoption.h \ 11HEADERS += anyoption.h \