moving and renaming SDLs.*, making it a singleton; cleaning up class responsibilties wrt SDLInteraction; some comments
authorsheepluva
Fri, 21 Oct 2011 07:00:49 +0200
changeset 6165 6fe3e922246e
parent 6164 62aa418ed214
child 6166 701c5b8fac56
moving and renaming SDLs.*, making it a singleton; cleaning up class responsibilties wrt SDLInteraction; some comments
QTfrontend/CMakeLists.txt
QTfrontend/Doxyfile
QTfrontend/SDLs.cpp
QTfrontend/SDLs.h
QTfrontend/hwform.cpp
QTfrontend/hwform.h
QTfrontend/ui/page/pageeditteam.cpp
QTfrontend/ui/page/pageeditteam.h
QTfrontend/ui/page/pagenetgame.cpp
QTfrontend/ui/page/pagenetgame.h
QTfrontend/ui/page/pageroomslist.cpp
QTfrontend/ui/page/pageroomslist.h
QTfrontend/ui/widget/chatwidget.cpp
QTfrontend/ui/widget/chatwidget.h
QTfrontend/ui_hwform.cpp
QTfrontend/util/HWDataManager.h
QTfrontend/util/SDLInteraction.cpp
QTfrontend/util/SDLInteraction.h
project_files/hedgewars.pro
--- a/QTfrontend/CMakeLists.txt	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/CMakeLists.txt	Fri Oct 21 07:00:49 2011 +0200
@@ -83,7 +83,6 @@
     HWApplication.cpp
     hwform.cpp
     main.cpp
-    SDLs.cpp
     team.cpp
     ui_hwform.cpp
     ${CMAKE_CURRENT_BINARY_DIR}/hwconsts.cpp
@@ -121,7 +120,6 @@
     gameuiconfig.h
     HWApplication.h
     hwform.h
-    SDLs.h
     )
 
 set(hwfr_hdrs
--- a/QTfrontend/Doxyfile	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/Doxyfile	Fri Oct 21 07:00:49 2011 +0200
@@ -504,7 +504,7 @@
 # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
 # in the documentation. The default is NO.
 
-SHOW_DIRECTORIES       = NO
+SHOW_DIRECTORIES       = YES
 
 # Set the SHOW_FILES tag to NO to disable the generation of the Files page.
 # This will remove the Files entry from the Quick Index and from the
--- a/QTfrontend/SDLs.cpp	Fri Oct 21 04:11:26 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "SDLs.h"
-
-#include "SDL.h"
-#include "SDL_mixer.h"
-
-#include "HWDataManager.h"
-
-#include "HWApplication.h"
-
-
-extern char sdlkeys[1024][2][128];
-extern char xb360buttons[][128];
-extern char xb360dpad[128];
-extern char xbox360axes[][128];
-
-SDLInteraction::SDLInteraction()
-{
-
-    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
-
-    musicInitialized = 0;
-    music = NULL;
-    if(SDL_NumJoysticks())
-        addGameControllerKeys();
-    SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
-}
-
-SDLInteraction::~SDLInteraction()
-{
-    if (musicInitialized == 1) {
-        if (music != NULL)
-            Mix_FreeMusic(music);
-        Mix_CloseAudio();
-    }
-    SDL_Quit();
-}
-
-QStringList SDLInteraction::getResolutions() const
-{
-    QStringList result;
-
-    SDL_Rect **modes;
-
-    modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
-
-    if((modes == (SDL_Rect **)0) || (modes == (SDL_Rect **)-1))
-    {
-        result << "640x480";
-    } else
-    {
-        for(int i = 0; modes[i]; ++i)
-            if ((modes[i]->w >= 640) && (modes[i]->h >= 480))
-                result << QString("%1x%2").arg(modes[i]->w).arg(modes[i]->h);
-    }
-
-    return result;
-}
-
-void SDLInteraction::addGameControllerKeys() const
-{
-    QStringList result;
-
-    int i = 0;
-    while(i < 1024 && sdlkeys[i][1][0] != '\0')
-        i++;
-
-    // Iterate through all game controllers
-    for(int jid = 0; jid < SDL_NumJoysticks(); jid++)
-    {
-        SDL_Joystick* joy = SDL_JoystickOpen(jid);
-
-        // Retrieve the game controller's name and strip "Controller (...)" that's added by some drivers (English only)
-        QString joyname = QString(SDL_JoystickName(jid)).replace(QRegExp("^Controller \\((.*)\\)$"), "\\1");
-
-        // Connected Xbox 360 controller? Use specific button names then
-        // Might be interesting to add 'named' buttons for the most often used gamepads
-        bool isxb = joyname.contains("Xbox 360");
-
-        // This part of the string won't change for multiple keys/hats, so keep it
-        QString prefix = QString("%1 (%2): ").arg(joyname).arg(jid + 1);
-
-        // Register entries for missing axes not assigned to sticks of this joystick/gamepad
-        for(int aid = 0; aid < SDL_JoystickNumAxes(joy) && i < 1021; aid++)
-        {
-            // Again store the part of the string not changing for multiple uses
-            QString axis = prefix + HWApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1);
-
-            // Entry for "Axis Up"
-            sprintf(sdlkeys[i][0], "j%da%du", jid, aid);
-            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
-
-            // Entry for "Axis Down"
-            sprintf(sdlkeys[i][0], "j%da%dd", jid, aid);
-            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : axis + HWApplication::translate("binds (keys)", "(Down)")).toUtf8().constData());
-        }
-
-        // Register entries for all coolie hats of this joystick/gamepad
-        for(int hid = 0; hid < SDL_JoystickNumHats(joy) && i < 1019; hid++)
-        {
-            // Again store the part of the string not changing for multiple uses
-            QString hat = prefix + (isxb ? (HWApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : HWApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1));
-
-            // Entry for "Hat Up"
-            sprintf(sdlkeys[i][0], "j%dh%du", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
-
-            // Entry for "Hat Down"
-            sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Down)")).toUtf8().constData());
-
-            // Entry for "Hat Left"
-            sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Left)")).toUtf8().constData());
-
-            // Entry for "Hat Right"
-            sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid);
-            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Right)")).toUtf8().constData());
-        }
-
-        // Register entries for all buttons of this joystick/gamepad
-        for(int bid = 0; bid < SDL_JoystickNumButtons(joy) && i < 1022; bid++)
-        {
-            // Buttons
-            sprintf(sdlkeys[i][0], "j%db%d", jid, bid);
-            sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (HWApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : HWApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toUtf8().constData());
-        }
-        // Close the game controller as we no longer need it
-        SDL_JoystickClose(joy);
-    }
-
-    // Terminate the list
-    sdlkeys[i][0][0] = '\0';
-    sdlkeys[i][1][0] = '\0';
-}
-
-void SDLInteraction::SDLMusicInit()
-{
-    if (musicInitialized == 0) {
-        SDL_Init(SDL_INIT_AUDIO);
-        Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
-        musicInitialized = 1;
-    }
-}
-
-void SDLInteraction::StartMusic()
-{
-    SDLMusicInit();
-    QFile * tmpFile = HWDataManager::instance().findFileForRead("Music/main_theme.ogg");
-
-    if (music == NULL)
-        music = Mix_LoadMUS(tmpFile->fileName().toLocal8Bit().constData());
-
-    // this QFile isn't needed any further
-    delete tmpFile;
-
-    Mix_VolumeMusic(MIX_MAX_VOLUME - 28);
-    Mix_FadeInMusic(music, -1, 1750);
-}
-
-void SDLInteraction::StopMusic()
-{
-    if (music != NULL) {
-        // fade out music to finish 0,5 seconds from now
-        while(!Mix_FadeOutMusic(1000) && Mix_PlayingMusic()) {
-            SDL_Delay(100);
-        }
-    }
-}
-
--- a/QTfrontend/SDLs.h	Fri Oct 21 04:11:26 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef SDLS_H
-#define SDLS_H
-
-
-#include <QStringList>
-#include "SDL_mixer.h"
-
-/// Class for interacting with SDL (used for music and keys)
-class SDLInteraction : public QObject
-{
-    Q_OBJECT
-
-private:
-    Mix_Music *music;
-    int musicInitialized;
-
-public:
-    /// Class Constructor.
-    SDLInteraction();
-
-    /// Class Destructor.
-    ~SDLInteraction();
-
-    /**
-     * @brief Returns available (screen) resolutions.
-     *
-     * @return list of resolutions in the format WIDTHxHEIGHT.
-     */
-    QStringList getResolutions() const;
-
-    /// Adds all available joystick controlls to the list of SDL keys.
-    void addGameControllerKeys() const;
-
-    /// Starts the background music.
-    void StartMusic();
-
-    /// Fades out and stops the background music.
-    void StopMusic();
-
-    /// Initializes SDL for playing music.
-    void SDLMusicInit();
-};
-
-
-#endif
-
--- a/QTfrontend/hwform.cpp	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/hwform.cpp	Fri Oct 21 07:00:49 2011 +0200
@@ -112,7 +112,7 @@
     //setFocusPolicy(Qt::StrongFocus);
     CustomizePalettes();
 
-    ui.pageOptions->CBResolution->addItems(sdli.getResolutions());
+    ui.pageOptions->CBResolution->addItems(SDLInteraction::instance().getResolutions());
 
     config = new GameUIConfig(this, cfgdir->absolutePath() + "/hedgewars.ini");
 
@@ -1176,9 +1176,9 @@
 void HWForm::Music(bool checked)
 {
     if (checked)
-        sdli.StartMusic();
+        SDLInteraction::instance().startMusic();
     else
-        sdli.StopMusic();
+        SDLInteraction::instance().stopMusic();
 }
 
 void HWForm::NetGameChangeStatus(bool isMaster)
--- a/QTfrontend/hwform.h	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/hwform.h	Fri Oct 21 07:00:49 2011 +0200
@@ -26,7 +26,7 @@
 #include "netserver.h"
 #include "game.h"
 #include "ui_hwform.h"
-#include "SDLs.h"
+#include "SDLInteraction.h"
 #include "bgwidget.h"
 
 #ifdef __APPLE__
@@ -54,7 +54,6 @@
 public:
     HWForm(QWidget *parent = 0, QString styleSheet = "");
     Ui_HWForm ui;
-    SDLInteraction sdli;
     GameUIConfig * config;
     QSettings * gameSettings; // Same file GameUIConfig points to but without the baggage.  Needs sync() calls if you want to get GameUIConfig changes though
     void updateXfire();
--- a/QTfrontend/ui/page/pageeditteam.cpp	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Fri Oct 21 07:00:49 2011 +0200
@@ -238,13 +238,12 @@
     connect(CBFort, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(CBFort_activated(const QString &)));
 }
 
-PageEditTeam::PageEditTeam(QWidget* parent, SDLInteraction * sdli) :
+PageEditTeam::PageEditTeam(QWidget* parent) :
   AbstractPage(parent)
 {
     initPage();
 
     m_playerHash = "0000000000000000000000000000000000000000";
-    mySdli = sdli;
 
     QDir tmpdir;
     QStringList list;
@@ -401,22 +400,28 @@
 
 void PageEditTeam::testSound()
 {
-    Mix_Chunk *sound;
-    QDir tmpdir;
-    mySdli->SDLMusicInit();
-    
-    tmpdir.cd(cfgdir->absolutePath());
-    if (!tmpdir.cd("Data/Sounds/voices/"+CBVoicepack->currentText()))
+    QString voiceDir = QString("Sounds/voices/") + CBVoicepack->currentText();
+
+    QStringList list = HWDataManager::instance().entryList(
+            voiceDir,
+            QDir::Files/*,
+            QStringList() <<
+                "Illgetyou.ogg" <<
+                "Incoming.ogg" <<
+                "Stupid.ogg" <<
+                "Coward.ogg" <<
+                "Firstblood.ogg"*/
+            );
+
+    if (list.size())
     {
-        tmpdir.cd(datadir->absolutePath());
-        tmpdir.cd("Sounds/voices");
-        tmpdir.cd(CBVoicepack->currentText());
-    }
+        QFile * tmpFile = HWDataManager::instance().findFileForRead(
+                                voiceDir + "/" + list[rand() % list.size()]);
 
-    QStringList list = tmpdir.entryList(QStringList() << "Illgetyou.ogg" << "Incoming.ogg" << "Stupid.ogg" << "Coward.ogg" << "Firstblood.ogg", QDir::Files);
-    if (list.size()) {
-        sound = Mix_LoadWAV(QString(tmpdir.absolutePath() + "/" + list[rand() % list.size()]).toLocal8Bit().constData());
-        Mix_PlayChannel(-1, sound, 0);
+        SDLInteraction::instance().playSoundFile(tmpFile->fileName());
+
+        // this QFile isn't needed any further
+        delete tmpFile;
     }
 }
 
--- a/QTfrontend/ui/page/pageeditteam.h	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/page/pageeditteam.h	Fri Oct 21 07:00:49 2011 +0200
@@ -22,8 +22,9 @@
 #include "AbstractPage.h"
 #include "binds.h"
 #include "hwconsts.h"
+#include "HWDataManager.h"
 #include "namegen.h"
-#include "SDLs.h"
+#include "SDLInteraction.h"
 
 #include "team.h"
 
@@ -34,7 +35,7 @@
     Q_OBJECT
 
 public:
-    PageEditTeam(QWidget* parent, SDLInteraction * sdli);
+    PageEditTeam(QWidget* parent);
 
     void createTeam(const QString & name, const QString & playerHash);
     void editTeam(const QString & name, const QString & playerHash);
@@ -64,7 +65,6 @@
     QLineEdit * HHNameEdit[HEDGEHOGS_PER_TEAM];
     QComboBox * HHHats[HEDGEHOGS_PER_TEAM];
     QComboBox * CBBind[BINDS_NUMBER];
-    SDLInteraction * mySdli;
     HWTeam data();
     QString m_playerHash;
 
@@ -85,8 +85,12 @@
 private slots:
     void saveTeam();
     void setRandomNames();
+
     void setRandomName(int hh_index);
+    
+    /// Plays a random voice sound of the currently edited team.
     void testSound();
+
     void fixHHname(int idx);
 };
 
--- a/QTfrontend/ui/page/pagenetgame.cpp	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/page/pagenetgame.cpp	Fri Oct 21 07:00:49 2011 +0200
@@ -36,7 +36,7 @@
     pageLayout->setColumnStretch(1, 50);
 
     // chatwidget
-    pChatWidget = new HWChatWidget(this, m_gameSettings, m_sdli, true);
+    pChatWidget = new HWChatWidget(this, m_gameSettings, true);
     pChatWidget->setShowReady(true); // show status bulbs by default
     pChatWidget->setShowFollow(false); // don't show follow in nicks' context menus
     pageLayout->addWidget(pChatWidget, 2, 0, 1, 2);
@@ -93,10 +93,9 @@
     connect(BtnUpdate, SIGNAL(clicked()), this, SLOT(onUpdateClick()));
 }
 
-PageNetGame::PageNetGame(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli) : AbstractPage(parent)
+PageNetGame::PageNetGame(QWidget* parent, QSettings * gameSettings) : AbstractPage(parent)
 {
     m_gameSettings = gameSettings;
-    m_sdli = sdli;
 
     initPage();
 
--- a/QTfrontend/ui/page/pagenetgame.h	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/page/pagenetgame.h	Fri Oct 21 07:00:49 2011 +0200
@@ -22,7 +22,6 @@
 #include "HistoryLineEdit.h"
 
 #include "AbstractPage.h"
-#include "SDLs.h"
 
 class HWChatWidget;
 class TeamSelWidget;
@@ -33,7 +32,7 @@
     Q_OBJECT
 
 public:
-    PageNetGame(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli);
+    PageNetGame(QWidget* parent, QSettings * gameSettings);
 
     /**
      * Sets the room name to display.
@@ -69,7 +68,6 @@
     void connectSignals();
 
     QSettings * m_gameSettings;
-    SDLInteraction * m_sdli;
 
     HistoryLineEdit * leRoomName;
     QPushButton * btnSetup;
--- a/QTfrontend/ui/page/pageroomslist.cpp	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/page/pageroomslist.cpp	Fri Oct 21 07:00:49 2011 +0200
@@ -87,7 +87,7 @@
 
     pageLayout->addLayout(filterLayout, 4, 0, 1, 2);
 
-    chatWidget = new HWChatWidget(this, m_gameSettings, m_sdli, false);
+    chatWidget = new HWChatWidget(this, m_gameSettings, false);
     pageLayout->addWidget(chatWidget, 5, 0, 1, 3);
     pageLayout->setRowStretch(5, 350);
 
@@ -140,11 +140,10 @@
 }
 
 
-PageRoomsList::PageRoomsList(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli) :
+PageRoomsList::PageRoomsList(QWidget* parent, QSettings * gameSettings) :
   AbstractPage(parent)
 {
     m_gameSettings = gameSettings;
-    m_sdli = sdli;
 
     initPage();
 
--- a/QTfrontend/ui/page/pageroomslist.h	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/page/pageroomslist.h	Fri Oct 21 07:00:49 2011 +0200
@@ -20,7 +20,6 @@
 #define PAGE_ROOMLIST_H
 
 #include "AbstractPage.h"
-#include "SDLs.h"
 
 class HWChatWidget;
 class AmmoSchemeModel;
@@ -30,7 +29,7 @@
     Q_OBJECT
 
 public:
-    PageRoomsList(QWidget* parent, QSettings * config, SDLInteraction * sdli);
+    PageRoomsList(QWidget* parent, QSettings * config);
 
     QLineEdit * roomName;
     QLineEdit * searchText;
@@ -71,7 +70,6 @@
 
 private:
     QSettings * m_gameSettings;
-    SDLInteraction * m_sdli;
 
     bool gameInLobby;
     QString gameInLobbyName;
--- a/QTfrontend/ui/widget/chatwidget.cpp	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/widget/chatwidget.cpp	Fri Oct 21 07:00:49 2011 +0200
@@ -22,9 +22,8 @@
 #include <QLineEdit>
 #include <QAction>
 #include <QTextDocument>
-#include <QDir>
+#include <QFile>
 #include <QSettings>
-#include <QFile>
 #include <QTextStream>
 #include <QMenu>
 #include <QCursor>
@@ -32,9 +31,10 @@
 #include <QItemSelectionModel>
 #include <QStringList>
 
+#include "HWDataManager.h"
 #include "hwconsts.h"
-#include "SDLs.h"
 #include "gameuiconfig.h"
+
 #include "chatwidget.h"
 
 ListWidgetNickItem::ListWidgetNickItem(const QString& nick, bool isFriend, bool isIgnored) : QListWidgetItem(nick)
@@ -116,22 +116,20 @@
 .Notice { color: #fefefe }\
 ";
 
-HWChatWidget::HWChatWidget(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli, bool notify) :
+HWChatWidget::HWChatWidget(QWidget* parent, QSettings * gameSettings, bool notify) :
   QWidget(parent),
   mainLayout(this)
 {
     this->gameSettings = gameSettings;
-    this->sdli = sdli;
     this->notify = notify;
     if(notify && gameSettings->value("frontend/sound", true).toBool()) {
-        QFile tmpfile;
-        sdli->SDLMusicInit();
-        for(int i=0;i<4;i++) {
-            tmpfile.setFileName(cfgdir->absolutePath() + "/Data/Sounds/voices/Classic/Hello.ogg");
-            if (tmpfile.exists()) sound[i] = Mix_LoadWAV(QFileInfo(tmpfile).absoluteFilePath().toLocal8Bit().constData());
-            else sound[i] = Mix_LoadWAV(QString(datadir->absolutePath() + 
-                "/Sounds/voices/Classic/Hello.ogg").toLocal8Bit().constData());
-        }
+        QFile * tmpFile = HWDataManager::instance().findFileForRead(
+                                            "Sounds/voices/Classic/Hello.ogg");
+
+        helloSound = tmpFile->fileName();
+
+        // this QFile isn't needed any further
+        delete tmpFile;
     }
 
     mainLayout.setSpacing(1);
@@ -426,7 +424,7 @@
     emit nickCountUpdate(chatNicks->count());
 
     if(notifyNick && notify && gameSettings->value("frontend/sound", true).toBool()) {
-       Mix_PlayChannel(-1, sound[rand()%4], 0);
+       SDLInteraction::instance().playSoundFile(helloSound);
     }
 }
 
--- a/QTfrontend/ui/widget/chatwidget.h	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui/widget/chatwidget.h	Fri Oct 21 07:00:49 2011 +0200
@@ -26,7 +26,7 @@
 #include <QGridLayout>
 #include <QRegExp>
 
-#include "SDLs.h"
+#include "SDLInteraction.h"
 
 #include "SmartLineEdit.h"
 
@@ -35,9 +35,8 @@
 class QLineEdit;
 class QListWidget;
 class QSettings;
-class SDLInteraction;
 
-// this class is for custom nick sorting
+/// This class is for custom nickname sorting
 class ListWidgetNickItem : public QListWidgetItem
 {
 public:
@@ -58,7 +57,7 @@
   Q_OBJECT
 
  public:
-  HWChatWidget(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli, bool notify);
+  HWChatWidget(QWidget* parent, QSettings * gameSettings, bool notify);
   void loadLists(const QString & nick);
   void saveLists(const QString & nick);
   void setShowReady(bool s);
@@ -105,8 +104,7 @@
   QAction * acIgnore;
   QAction * acFriend;
   QSettings * gameSettings;
-  SDLInteraction * sdli;
-  Mix_Chunk *sound[4];
+  QString helloSound;
   bool notify;
   bool showReady;
 
--- a/QTfrontend/ui_hwform.cpp	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/ui_hwform.cpp	Fri Oct 21 07:00:49 2011 +0200
@@ -76,7 +76,7 @@
 {
     Pages = new QStackedLayout(Parent);
 
-    pageEditTeam = new PageEditTeam(Parent, &HWForm->sdli);
+    pageEditTeam = new PageEditTeam(Parent);
     Pages->addWidget(pageEditTeam);
 
     pageOptions = new PageOptions();
@@ -91,7 +91,7 @@
     pageNet = new PageNet();
     Pages->addWidget(pageNet);
 
-    pageNetGame = new PageNetGame(Parent, HWForm->gameSettings, &HWForm->sdli);
+    pageNetGame = new PageNetGame(Parent, HWForm->gameSettings);
     Pages->addWidget(pageNetGame);
 
     pageInfo = new PageInfo();
@@ -118,7 +118,7 @@
     pageInGame = new PageInGame();
     Pages->addWidget(pageInGame);
 
-    pageRoomsList = new PageRoomsList(Parent, HWForm->gameSettings, &HWForm->sdli);
+    pageRoomsList = new PageRoomsList(Parent, HWForm->gameSettings);
     Pages->addWidget(pageRoomsList);
 
     pageConnecting = new PageConnecting();
--- a/QTfrontend/util/HWDataManager.h	Fri Oct 21 04:11:26 2011 +0200
+++ b/QTfrontend/util/HWDataManager.h	Fri Oct 21 07:00:49 2011 +0200
@@ -41,11 +41,11 @@
 {
 public:
     /**
-     * @brief Returns a pointer to the <i>singleton</i> instance of this class.
+     * @brief Returns reference to the <i>singleton</i> instance of this class.
      * 
      * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
      * 
-     * @return pointer to the instance.
+     * @return reference to the instance.
      */
     static HWDataManager & instance();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/SDLInteraction.cpp	Fri Oct 21 07:00:49 2011 +0200
@@ -0,0 +1,209 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include "SDL.h"
+#include "SDL_mixer.h"
+
+#include "HWDataManager.h"
+
+#include "HWApplication.h"
+
+#include "SDLInteraction.h"
+
+extern char sdlkeys[1024][2][128];
+extern char xb360buttons[][128];
+extern char xb360dpad[128];
+extern char xbox360axes[][128];
+
+
+SDLInteraction & SDLInteraction::instance()
+{
+    static SDLInteraction instance;
+    return instance;
+}
+
+
+SDLInteraction::SDLInteraction()
+{
+
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
+
+    musicInitialized = 0;
+    music = NULL;
+    if(SDL_NumJoysticks())
+        addGameControllerKeys();
+    SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+
+    soundMap = new QMap<QString,Mix_Chunk*>();
+}
+
+SDLInteraction::~SDLInteraction()
+{
+    stopMusic();
+    if (musicInitialized == 1) {
+        if (music != NULL)
+            Mix_FreeMusic(music);
+        Mix_CloseAudio();
+    }
+    SDL_Quit();
+
+    delete soundMap;
+}
+
+QStringList SDLInteraction::getResolutions() const
+{
+    QStringList result;
+
+    SDL_Rect **modes;
+
+    modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
+
+    if((modes == (SDL_Rect **)0) || (modes == (SDL_Rect **)-1))
+    {
+        result << "640x480";
+    } else
+    {
+        for(int i = 0; modes[i]; ++i)
+            if ((modes[i]->w >= 640) && (modes[i]->h >= 480))
+                result << QString("%1x%2").arg(modes[i]->w).arg(modes[i]->h);
+    }
+
+    return result;
+}
+
+void SDLInteraction::addGameControllerKeys() const
+{
+    QStringList result;
+
+    int i = 0;
+    while(i < 1024 && sdlkeys[i][1][0] != '\0')
+        i++;
+
+    // Iterate through all game controllers
+    for(int jid = 0; jid < SDL_NumJoysticks(); jid++)
+    {
+        SDL_Joystick* joy = SDL_JoystickOpen(jid);
+
+        // Retrieve the game controller's name and strip "Controller (...)" that's added by some drivers (English only)
+        QString joyname = QString(SDL_JoystickName(jid)).replace(QRegExp("^Controller \\((.*)\\)$"), "\\1");
+
+        // Connected Xbox 360 controller? Use specific button names then
+        // Might be interesting to add 'named' buttons for the most often used gamepads
+        bool isxb = joyname.contains("Xbox 360");
+
+        // This part of the string won't change for multiple keys/hats, so keep it
+        QString prefix = QString("%1 (%2): ").arg(joyname).arg(jid + 1);
+
+        // Register entries for missing axes not assigned to sticks of this joystick/gamepad
+        for(int aid = 0; aid < SDL_JoystickNumAxes(joy) && i < 1021; aid++)
+        {
+            // Again store the part of the string not changing for multiple uses
+            QString axis = prefix + HWApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1);
+
+            // Entry for "Axis Up"
+            sprintf(sdlkeys[i][0], "j%da%du", jid, aid);
+            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
+
+            // Entry for "Axis Down"
+            sprintf(sdlkeys[i][0], "j%da%dd", jid, aid);
+            sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2 + 1])) : axis + HWApplication::translate("binds (keys)", "(Down)")).toUtf8().constData());
+        }
+
+        // Register entries for all coolie hats of this joystick/gamepad
+        for(int hid = 0; hid < SDL_JoystickNumHats(joy) && i < 1019; hid++)
+        {
+            // Again store the part of the string not changing for multiple uses
+            QString hat = prefix + (isxb ? (HWApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : HWApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1));
+
+            // Entry for "Hat Up"
+            sprintf(sdlkeys[i][0], "j%dh%du", jid, hid);
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
+
+            // Entry for "Hat Down"
+            sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid);
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Down)")).toUtf8().constData());
+
+            // Entry for "Hat Left"
+            sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid);
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Left)")).toUtf8().constData());
+
+            // Entry for "Hat Right"
+            sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid);
+            sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Right)")).toUtf8().constData());
+        }
+
+        // Register entries for all buttons of this joystick/gamepad
+        for(int bid = 0; bid < SDL_JoystickNumButtons(joy) && i < 1022; bid++)
+        {
+            // Buttons
+            sprintf(sdlkeys[i][0], "j%db%d", jid, bid);
+            sprintf(sdlkeys[i++][1], "%s", (prefix + ((isxb && bid < 10) ? (HWApplication::translate("binds (keys)", xb360buttons[bid]) + QString(" ")) : HWApplication::translate("binds (keys)", "Button") + QString(" %1").arg(bid + 1))).toUtf8().constData());
+        }
+        // Close the game controller as we no longer need it
+        SDL_JoystickClose(joy);
+    }
+
+    // Terminate the list
+    sdlkeys[i][0][0] = '\0';
+    sdlkeys[i][1][0] = '\0';
+}
+
+void SDLInteraction::SDLSoundInit()
+{
+    if (musicInitialized == 0) {
+        SDL_Init(SDL_INIT_AUDIO);
+        Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
+        musicInitialized = 1;
+    }
+}
+
+void SDLInteraction::playSoundFile(const QString & soundFile)
+{
+    SDLSoundInit();
+    if (!soundMap->contains(soundFile))
+        soundMap->insert(soundFile, Mix_LoadWAV(soundFile.toLocal8Bit().constData()));
+
+    Mix_PlayChannel(-1, soundMap->value(soundFile), 0);
+}
+
+void SDLInteraction::startMusic()
+{
+    SDLSoundInit();
+    QFile * tmpFile = HWDataManager::instance().findFileForRead("Music/main_theme.ogg");
+
+    if (music == NULL)
+        music = Mix_LoadMUS(tmpFile->fileName().toLocal8Bit().constData());
+
+    // this QFile isn't needed any further
+    delete tmpFile;
+
+    Mix_VolumeMusic(MIX_MAX_VOLUME - 28);
+    Mix_FadeInMusic(music, -1, 1750);
+}
+
+void SDLInteraction::stopMusic()
+{
+    if (music != NULL) {
+        // fade out music to finish 0,5 seconds from now
+        while(!Mix_FadeOutMusic(1000) && Mix_PlayingMusic()) {
+            SDL_Delay(100);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/util/SDLInteraction.h	Fri Oct 21 07:00:49 2011 +0200
@@ -0,0 +1,94 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef HEDGEWARS_SDLINTERACTION_H
+#define HEDGEWARS_SDLINTERACTION_H
+
+
+#include <QMap>
+#include <QStringList>
+
+#include "SDL_mixer.h"
+
+/**
+ * @brief Class for interacting with SDL (used for music and keys)
+ * 
+ * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
+ */
+class SDLInteraction
+{
+
+private:
+    /**
+     * @brief Class constructor of the <i>singleton</i>.
+     * 
+     * Not to be used from outside the class,
+     * use the static {@link HWDataManager::instance()} instead.
+     * 
+     * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
+     */
+    SDLInteraction();
+
+    /// Initializes SDL for sound output if needed.
+    void SDLSoundInit();
+
+    Mix_Music *music;
+    int musicInitialized;
+
+    QMap<QString,Mix_Chunk*> * soundMap; ///< maps sound file paths to channel
+
+public:
+    /**
+     * @brief Returns reference to the <i>singleton</i> instance of this class.
+     * 
+     * @see <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton pattern</a>
+     * 
+     * @return reference to the instance.
+     */
+    static SDLInteraction & instance();
+
+    /// Class Destructor.
+    ~SDLInteraction();
+
+    /**
+     * @brief Returns available (screen) resolutions.
+     *
+     * @return list of resolutions in the format WIDTHxHEIGHT.
+     */
+    QStringList getResolutions() const;
+
+    /// Adds all available joystick controlls to the list of SDL keys.
+    void addGameControllerKeys() const;
+
+    /**
+     * @brief Plays a sound file.
+     * 
+     * @param soundFile path of the sound file.
+     */
+    void playSoundFile(const QString & soundFile);
+
+    /// Starts the background music.
+    void startMusic();
+
+    /// Fades out and stops the background music.
+    void stopMusic();
+};
+
+
+#endif //HEDGEWARS_SDLINTERACTION_H
+
--- a/project_files/hedgewars.pro	Fri Oct 21 04:11:26 2011 +0200
+++ b/project_files/hedgewars.pro	Fri Oct 21 07:00:49 2011 +0200
@@ -88,7 +88,7 @@
     ../QTfrontend/gameuiconfig.h \
     ../QTfrontend/HWApplication.h \
     ../QTfrontend/hwform.h \
-    ../QTfrontend/SDLs.h \
+    ../QTfrontend/util/SDLInteraction.h \
     ../QTfrontend/team.h \
     ../QTfrontend/achievements.h \
     ../QTfrontend/binds.h \
@@ -166,7 +166,7 @@
     ../QTfrontend/HWApplication.cpp \
     ../QTfrontend/hwform.cpp \
     ../QTfrontend/main.cpp \
-    ../QTfrontend/SDLs.cpp \
+    ../QTfrontend/util/SDLInteraction.h.cpp \
     ../QTfrontend/team.cpp \
     ../QTfrontend/ui_hwform.cpp \
     ../QTfrontend/hwconsts.cpp