QTfrontend/util/SDLInteraction.cpp
branchhedgeroid
changeset 6224 42b256eca362
parent 6170 2b1748161278
child 6524 416fdfb666da
equal deleted inserted replaced
6055:88cfcd9161d3 6224:42b256eca362
       
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2007-2011 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 /**
       
    20  * @file
       
    21  * @brief SDLInteraction class implementation
       
    22  */
       
    23 
       
    24 #include "SDL.h"
       
    25 #include "SDL_mixer.h"
       
    26 
       
    27 #include "HWApplication.h"
       
    28 
       
    29 #include "SDLInteraction.h"
       
    30 
       
    31 extern char sdlkeys[1024][2][128];
       
    32 extern char xb360buttons[][128];
       
    33 extern char xb360dpad[128];
       
    34 extern char xbox360axes[][128];
       
    35 
       
    36 
       
    37 SDLInteraction & SDLInteraction::instance()
       
    38 {
       
    39     static SDLInteraction instance;
       
    40     return instance;
       
    41 }
       
    42 
       
    43 
       
    44 SDLInteraction::SDLInteraction()
       
    45 {
       
    46 
       
    47     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
       
    48 
       
    49     m_audioInitialized = false;
       
    50     m_music = NULL;
       
    51     m_musicTrack = "";
       
    52     m_isPlayingMusic = false;
       
    53     if(SDL_NumJoysticks())
       
    54         addGameControllerKeys();
       
    55     SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
       
    56 
       
    57     m_soundMap = new QMap<QString,Mix_Chunk*>();
       
    58 }
       
    59 
       
    60 
       
    61 SDLInteraction::~SDLInteraction()
       
    62 {
       
    63     stopMusic();
       
    64     if (m_audioInitialized)
       
    65     {
       
    66         if (m_music != NULL)
       
    67             Mix_FreeMusic(m_music);
       
    68         Mix_CloseAudio();
       
    69     }
       
    70     SDL_Quit();
       
    71 
       
    72     delete m_soundMap;
       
    73 }
       
    74 
       
    75 
       
    76 QStringList SDLInteraction::getResolutions() const
       
    77 {
       
    78     QStringList result;
       
    79 
       
    80     SDL_Rect **modes;
       
    81 
       
    82     modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
       
    83 
       
    84     if((modes == (SDL_Rect **)0) || (modes == (SDL_Rect **)-1))
       
    85     {
       
    86         result << "640x480";
       
    87     } else
       
    88     {
       
    89         for(int i = 0; modes[i]; ++i)
       
    90             if ((modes[i]->w >= 640) && (modes[i]->h >= 480))
       
    91                 result << QString("%1x%2").arg(modes[i]->w).arg(modes[i]->h);
       
    92     }
       
    93 
       
    94     return result;
       
    95 }
       
    96 
       
    97 
       
    98 void SDLInteraction::addGameControllerKeys() const
       
    99 {
       
   100     QStringList result;
       
   101 
       
   102     int i = 0;
       
   103     while(i < 1024 && sdlkeys[i][1][0] != '\0')
       
   104         i++;
       
   105 
       
   106     // Iterate through all game controllers
       
   107     for(int jid = 0; jid < SDL_NumJoysticks(); jid++)
       
   108     {
       
   109         SDL_Joystick* joy = SDL_JoystickOpen(jid);
       
   110 
       
   111         // Retrieve the game controller's name and strip "Controller (...)" that's added by some drivers (English only)
       
   112         QString joyname = QString(SDL_JoystickName(jid)).replace(QRegExp("^Controller \\((.*)\\)$"), "\\1");
       
   113 
       
   114         // Connected Xbox 360 controller? Use specific button names then
       
   115         // Might be interesting to add 'named' buttons for the most often used gamepads
       
   116         bool isxb = joyname.contains("Xbox 360");
       
   117 
       
   118         // This part of the string won't change for multiple keys/hats, so keep it
       
   119         QString prefix = QString("%1 (%2): ").arg(joyname).arg(jid + 1);
       
   120 
       
   121         // Register entries for missing axes not assigned to sticks of this joystick/gamepad
       
   122         for(int aid = 0; aid < SDL_JoystickNumAxes(joy) && i < 1021; aid++)
       
   123         {
       
   124             // Again store the part of the string not changing for multiple uses
       
   125             QString axis = prefix + HWApplication::translate("binds (keys)", "Axis") + QString(" %1 ").arg(aid + 1);
       
   126 
       
   127             // Entry for "Axis Up"
       
   128             sprintf(sdlkeys[i][0], "j%da%du", jid, aid);
       
   129             sprintf(sdlkeys[i++][1], "%s", ((isxb && aid < 5) ? (prefix + HWApplication::translate("binds (keys)", xbox360axes[aid * 2])) : axis + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
       
   130 
       
   131             // Entry for "Axis Down"
       
   132             sprintf(sdlkeys[i][0], "j%da%dd", jid, aid);
       
   133             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());
       
   134         }
       
   135 
       
   136         // Register entries for all coolie hats of this joystick/gamepad
       
   137         for(int hid = 0; hid < SDL_JoystickNumHats(joy) && i < 1019; hid++)
       
   138         {
       
   139             // Again store the part of the string not changing for multiple uses
       
   140             QString hat = prefix + (isxb ? (HWApplication::translate("binds (keys)", xb360dpad) + QString(" ")) : HWApplication::translate("binds (keys)", "Hat") + QString(" %1 ").arg(hid + 1));
       
   141 
       
   142             // Entry for "Hat Up"
       
   143             sprintf(sdlkeys[i][0], "j%dh%du", jid, hid);
       
   144             sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Up)")).toUtf8().constData());
       
   145 
       
   146             // Entry for "Hat Down"
       
   147             sprintf(sdlkeys[i][0], "j%dh%dd", jid, hid);
       
   148             sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Down)")).toUtf8().constData());
       
   149 
       
   150             // Entry for "Hat Left"
       
   151             sprintf(sdlkeys[i][0], "j%dh%dl", jid, hid);
       
   152             sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Left)")).toUtf8().constData());
       
   153 
       
   154             // Entry for "Hat Right"
       
   155             sprintf(sdlkeys[i][0], "j%dh%dr", jid, hid);
       
   156             sprintf(sdlkeys[i++][1], "%s", (hat + HWApplication::translate("binds (keys)", "(Right)")).toUtf8().constData());
       
   157         }
       
   158 
       
   159         // Register entries for all buttons of this joystick/gamepad
       
   160         for(int bid = 0; bid < SDL_JoystickNumButtons(joy) && i < 1022; bid++)
       
   161         {
       
   162             // Buttons
       
   163             sprintf(sdlkeys[i][0], "j%db%d", jid, bid);
       
   164             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());
       
   165         }
       
   166         // Close the game controller as we no longer need it
       
   167         SDL_JoystickClose(joy);
       
   168     }
       
   169 
       
   170     // Terminate the list
       
   171     sdlkeys[i][0][0] = '\0';
       
   172     sdlkeys[i][1][0] = '\0';
       
   173 }
       
   174 
       
   175 
       
   176 void SDLInteraction::SDLAudioInit()
       
   177 {
       
   178     // don't init again
       
   179     if (m_audioInitialized)
       
   180         return;
       
   181 
       
   182     SDL_Init(SDL_INIT_AUDIO);
       
   183     Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
       
   184     m_audioInitialized = true;
       
   185 }
       
   186 
       
   187 
       
   188 void SDLInteraction::playSoundFile(const QString & soundFile)
       
   189 {
       
   190     SDLAudioInit();
       
   191     if (!m_soundMap->contains(soundFile))
       
   192         m_soundMap->insert(soundFile, Mix_LoadWAV(soundFile.toLocal8Bit().constData()));
       
   193 
       
   194     Mix_PlayChannel(-1, m_soundMap->value(soundFile), 0);
       
   195 }
       
   196 
       
   197 
       
   198 void SDLInteraction::setMusicTrack(const QString & musicFile)
       
   199 {
       
   200     bool wasPlayingMusic = m_isPlayingMusic;
       
   201 
       
   202     stopMusic();
       
   203 
       
   204     if (m_music != NULL)
       
   205     {
       
   206         Mix_FreeMusic(m_music);
       
   207         m_music = NULL;
       
   208     }
       
   209 
       
   210     m_musicTrack = musicFile;
       
   211 
       
   212     if (wasPlayingMusic)
       
   213         startMusic();
       
   214 }
       
   215 
       
   216 
       
   217 void SDLInteraction::startMusic()
       
   218 {
       
   219     if (m_isPlayingMusic)
       
   220         return;
       
   221 
       
   222     m_isPlayingMusic = true;
       
   223 
       
   224     if (m_musicTrack.isEmpty())
       
   225         return;
       
   226 
       
   227     SDLAudioInit();
       
   228 
       
   229     if (m_music == NULL)
       
   230         m_music = Mix_LoadMUS(m_musicTrack.toLocal8Bit().constData());
       
   231 
       
   232     Mix_VolumeMusic(MIX_MAX_VOLUME - 28);
       
   233     Mix_FadeInMusic(m_music, -1, 1750);
       
   234 }
       
   235 
       
   236 
       
   237 void SDLInteraction::stopMusic()
       
   238 {
       
   239     if (m_isPlayingMusic && (m_music != NULL)) {
       
   240         // fade out music to finish 0,5 seconds from now
       
   241         while(!Mix_FadeOutMusic(1000) && Mix_PlayingMusic()) {
       
   242             SDL_Delay(100);
       
   243         }
       
   244     }
       
   245 
       
   246     m_isPlayingMusic = false;
       
   247 }
       
   248