diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index eceeb590..d9a4800c 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -137,14 +137,22 @@ set(COCKATRICE_LIBS) # Qt4 stuff if(Qt4_FOUND) + if (NOT QT_QTMULTIMEDIA_FOUND) + FIND_PACKAGE(QtMobility REQUIRED) + endif() + SET(QT_USE_QTNETWORK TRUE) + SET(QT_USE_QTMULTIMEDIA TRUE) SET(QT_USE_QTSVG TRUE) # Include directories INCLUDE(${QT_USE_FILE}) INCLUDE_DIRECTORIES(${QT_INCLUDES}) + INCLUDE_DIRECTORIES(${QT_MOBILITY_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(${QT_MOBILITY_MULTIMEDIAKIT_INCLUDE_DIR}) LIST(APPEND COCKATRICE_LIBS ${QT_LIBRARIES}) LIST(APPEND COCKATRICE_LIBS ${QT_QTMAIN_LIBRARY}) + LIST(APPEND COCKATRICE_LIBS ${QT_MOBILITY_MULTIMEDIAKIT_LIBRARY}) # Let cmake chew Qt4's translations and resource files # Note: header files are MOC-ed automatically by cmake diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index f810c7d3..b8b64e7b 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -638,12 +638,16 @@ SoundSettingsPage::SoundSettingsPage() soundEnabledCheckBox.setChecked(settingsCache->getSoundEnabled()); connect(&soundEnabledCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setSoundEnabled(int))); - soundPathEdit = new QLineEdit(settingsCache->getSoundPath()); - soundPathEdit->setReadOnly(true); - QPushButton *soundPathClearButton = new QPushButton(QPixmap("theme:icons/delete"), QString()); - connect(soundPathClearButton, SIGNAL(clicked()), this, SLOT(soundPathClearButtonClicked())); - QPushButton *soundPathButton = new QPushButton("..."); - connect(soundPathButton, SIGNAL(clicked()), this, SLOT(soundPathButtonClicked())); + QString themeName = settingsCache->getSoundThemeName(); + + QStringList themeDirs = soundEngine->getAvailableThemes().keys(); + for (int i = 0; i < themeDirs.size(); i++) { + themeBox.addItem(themeDirs[i]); + if (themeDirs[i] == themeName) + themeBox.setCurrentIndex(i); + } + + connect(&themeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(themeBoxChanged(int))); connect(&soundTestButton, SIGNAL(clicked()), soundEngine, SLOT(testSound())); masterVolumeSlider = new QSlider(Qt::Horizontal); @@ -655,8 +659,6 @@ SoundSettingsPage::SoundSettingsPage() connect(masterVolumeSlider, SIGNAL(sliderReleased()), soundEngine, SLOT(testSound())); connect(masterVolumeSlider, SIGNAL(valueChanged(int)), settingsCache, SLOT(setMasterVolume(int))); - - masterVolumeSpinBox = new QSpinBox(); masterVolumeSpinBox->setMinimum(0); masterVolumeSpinBox->setMaximum(100); @@ -670,14 +672,12 @@ SoundSettingsPage::SoundSettingsPage() #endif QGridLayout *soundGrid = new QGridLayout; - soundGrid->addWidget(&soundEnabledCheckBox, 0, 0, 1, 4); + soundGrid->addWidget(&soundEnabledCheckBox, 0, 0, 1, 3); soundGrid->addWidget(&masterVolumeLabel, 1, 0); soundGrid->addWidget(masterVolumeSlider, 1, 1); soundGrid->addWidget(masterVolumeSpinBox, 1, 2); - soundGrid->addWidget(&soundPathLabel, 2, 0); - soundGrid->addWidget(soundPathEdit, 2, 1); - soundGrid->addWidget(soundPathClearButton, 2, 2); - soundGrid->addWidget(soundPathButton, 2, 3); + soundGrid->addWidget(&themeLabel, 2, 0); + soundGrid->addWidget(&themeBox, 2, 1); soundGrid->addWidget(&soundTestButton, 3, 1); soundGroupBox = new QGroupBox; @@ -689,29 +689,20 @@ SoundSettingsPage::SoundSettingsPage() setLayout(mainLayout); } +void SoundSettingsPage::themeBoxChanged(int index) +{ + QStringList themeDirs = soundEngine->getAvailableThemes().keys(); + if(index >= 0 && index < themeDirs.count()) + settingsCache->setSoundThemeName(themeDirs.at(index)); +} + void SoundSettingsPage::masterVolumeChanged(int value) { masterVolumeSlider->setToolTip(QString::number(value)); } -void SoundSettingsPage::soundPathClearButtonClicked() -{ - soundPathEdit->setText(QString()); - settingsCache->setSoundPath(QString()); -} - -void SoundSettingsPage::soundPathButtonClicked() -{ - QString path = QFileDialog::getExistingDirectory(this, tr("Choose path")); - if (path.isEmpty()) - return; - - soundPathEdit->setText(path); - settingsCache->setSoundPath(path); -} - void SoundSettingsPage::retranslateUi() { soundEnabledCheckBox.setText(tr("Enable &sounds")); - soundPathLabel.setText(tr("Path to sounds directory:")); + themeLabel.setText(tr("Current sounds theme:")); soundTestButton.setText(tr("Test system sound engine")); soundGroupBox->setTitle(tr("Sound settings")); #if QT_VERSION < 0x050000 diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index 45443c0b..741f2812 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -174,20 +174,17 @@ public: SoundSettingsPage(); void retranslateUi(); private: + QLabel themeLabel; + QComboBox themeBox; QGroupBox *soundGroupBox; QPushButton soundTestButton; QCheckBox soundEnabledCheckBox; - QLabel soundPathLabel; - QLineEdit *soundPathEdit; QLabel masterVolumeLabel; QSlider *masterVolumeSlider; QSpinBox *masterVolumeSpinBox; -signals: - void soundPathChanged(); private slots: void masterVolumeChanged(int value); - void soundPathClearButtonClicked(); - void soundPathButtonClicked(); + void themeBoxChanged(int index); }; class DlgSettings : public QDialog { diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index 7f1eb73e..c48787a6 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -190,20 +190,6 @@ int main(int argc, char *argv[]) qDebug() << "Could not create " + dataDir + "/customsets folder."; } - if(settingsCache->getSoundPath().isEmpty() || !QDir(settingsCache->getSoundPath()).exists()) - { - QDir tmpDir; - -#ifdef Q_OS_MAC - tmpDir = app.applicationDirPath() + "/../Resources/sounds"; -#elif defined(Q_OS_WIN) - tmpDir = app.applicationDirPath() + "/sounds"; -#else // linux - tmpDir = app.applicationDirPath() + "/../share/cockatrice/sounds/"; -#endif - settingsCache->setSoundPath(tmpDir.canonicalPath()); - } - if (!settingsValid() || db->getLoadStatus() != Ok) { qDebug("main(): invalid settings or load status"); DlgSettings dlgSettings; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 404a20e2..5af5f19f 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -137,7 +137,6 @@ SettingsCache::SettingsCache() setDeckPath(qApp->applicationDirPath() + "data/decks"); setReplaysPath(qApp->applicationDirPath() +"data/replays"); setPicsPath(qApp->applicationDirPath() + "data/pics"); - setSoundPath(qApp->applicationDirPath() +"data/sounds"); #endif notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool(); @@ -198,7 +197,7 @@ SettingsCache::SettingsCache() zoneViewPileView = settings->value("zoneview/pileview", true).toBool(); soundEnabled = settings->value("sound/enabled", false).toBool(); - soundPath = settings->value("sound/path").toString(); + soundThemeName = settings->value("sound/theme").toString(); priceTagFeature = settings->value("deckeditor/pricetags", false).toBool(); priceTagSource = settings->value("deckeditor/pricetagsource", 0).toInt(); @@ -482,11 +481,11 @@ void SettingsCache::setSoundEnabled(int _soundEnabled) emit soundEnabledChanged(); } -void SettingsCache::setSoundPath(const QString &_soundPath) +void SettingsCache::setSoundThemeName(const QString &_soundThemeName) { - soundPath = _soundPath; - settings->setValue("sound/path", soundPath); - emit soundPathChanged(); + soundThemeName = _soundThemeName; + settings->setValue("sound/theme", soundThemeName); + emit soundThemeChanged(); } void SettingsCache::setPriceTagFeature(int _priceTagFeature) diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 6ab03b79..7e374e86 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -39,7 +39,7 @@ signals: void invertVerticalCoordinateChanged(); void minPlayersForMultiColumnLayoutChanged(); void soundEnabledChanged(); - void soundPathChanged(); + void soundThemeChanged(); void priceTagFeatureChanged(int enabled); void ignoreUnregisteredUsersChanged(); void ignoreUnregisteredUserMessagesChanged(); @@ -81,7 +81,7 @@ private: bool chatHighlightForeground; bool zoneViewSortByName, zoneViewSortByType, zoneViewPileView; bool soundEnabled; - QString soundPath; + QString soundThemeName; bool priceTagFeature; int priceTagSource; bool ignoreUnregisteredUsers; @@ -153,7 +153,7 @@ public: */ bool getZoneViewPileView() const { return zoneViewPileView; } bool getSoundEnabled() const { return soundEnabled; } - QString getSoundPath() const { return soundPath; } + QString getSoundThemeName() const { return soundThemeName; } bool getPriceTagFeature() const { return false; /* #859; priceTagFeature;*/ } int getPriceTagSource() const { return priceTagSource; } bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; } @@ -223,7 +223,7 @@ public slots: void setZoneViewSortByType(int _zoneViewSortByType); void setZoneViewPileView(int _zoneViewPileView); void setSoundEnabled(int _soundEnabled); - void setSoundPath(const QString &_soundPath); + void setSoundThemeName(const QString &_soundThemeName); void setPriceTagFeature(int _priceTagFeature); void setPriceTagSource(int _priceTagSource); void setIgnoreUnregisteredUsers(int _ignoreUnregisteredUsers); diff --git a/cockatrice/src/soundengine.cpp b/cockatrice/src/soundengine.cpp index 324c8ba2..dcb41b7e 100644 --- a/cockatrice/src/soundengine.cpp +++ b/cockatrice/src/soundengine.cpp @@ -1,11 +1,164 @@ #include "soundengine.h" #include "settingscache.h" +#include +#include +#include +#include #include -#include +#include +#if QT_VERSION < 0x050000 + #include +#else + #include +#endif -/* - fileNames = QStringList() +#define DEFAULT_THEME_NAME "Default" +#define TEST_SOUND_FILENAME "player_join" + +SoundEngine::SoundEngine(QObject *parent) +: QObject(parent), player(0) +{ + inputBuffer = new QBuffer(this); + + ensureThemeDirectoryExists(); + connect(settingsCache, SIGNAL(soundThemeChanged()), this, SLOT(themeChangedSlot())); + connect(settingsCache, SIGNAL(soundEnabledChanged()), this, SLOT(soundEnabledChanged())); + + soundEnabledChanged(); + themeChangedSlot(); +} + +SoundEngine::~SoundEngine() +{ + if(player) + { + player->deleteLater(); + player = 0; + } + + inputBuffer->deleteLater(); +} + +void SoundEngine::soundEnabledChanged() +{ + if (settingsCache->getSoundEnabled()) { + qDebug("SoundEngine: enabling sound"); + if(!player) + { + QAudioFormat format; +#if QT_VERSION < 0x050000 + format.setFrequency(44100); + format.setChannels(1); + #else + format.setSampleRate(44100); + format.setChannelCount(1); + #endif + format.setSampleSize(16); + format.setCodec("audio/pcm"); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setSampleType(QAudioFormat::SignedInt); + player = new QAudioOutput(format, this); + } + } else { + qDebug("SoundEngine: disabling sound"); + if(player) + { + player->stop(); + player->deleteLater(); + player = 0; + } + } +} + +void SoundEngine::playSound(QString fileName) +{ + if(!player) + return; + + // still playing the previous sound? + if(player->state() == QAudio::ActiveState) + return; + + if(!audioData.contains(fileName)) + return; + + qDebug() << "playing" << fileName; + + inputBuffer->close(); + inputBuffer->setData(audioData[fileName]); + inputBuffer->open(QIODevice::ReadOnly); +#if QT_VERSION >= 0x050000 + player->setVolume(settingsCache->getMasterVolume()); +#endif + player->stop(); + player->start(inputBuffer); +} + +void SoundEngine::testSound() +{ + playSound(TEST_SOUND_FILENAME); +} + +void SoundEngine::ensureThemeDirectoryExists() +{ + if(settingsCache->getSoundThemeName().isEmpty() || + !getAvailableThemes().contains(settingsCache->getSoundThemeName())) + { + qDebug() << "Sounds theme name not set, setting default value"; + settingsCache->setSoundThemeName(DEFAULT_THEME_NAME); + } +} + +QStringMap & SoundEngine::getAvailableThemes() +{ + QDir dir; + availableThemes.clear(); + + // load themes from user profile dir + dir = +#ifdef PORTABLE_BUILD + qApp->applicationDirPath() + +#elif QT_VERSION < 0x050000 + QDesktopServices::storageLocation(QDesktopServices::DataLocation) + +#else + QStandardPaths::standardLocations(QStandardPaths::DataLocation).first() + +#endif + "/sounds"; + + foreach(QString themeName, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) + { + if(!availableThemes.contains(themeName)) + availableThemes.insert(themeName, dir.absoluteFilePath(themeName)); + } + + // load themes from cockatrice system dir +#ifdef Q_OS_MAC + dir = qApp->applicationDirPath() + "/../Resources/sounds"; +#elif defined(Q_OS_WIN) + dir = qApp->applicationDirPath() + "/sounds"; +#else // linux + dir = qApp->applicationDirPath() + "/../share/cockatrice/sounds"; +#endif + foreach(QString themeName, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) + { + if(!availableThemes.contains(themeName)) + availableThemes.insert(themeName, dir.absoluteFilePath(themeName)); + } + + return availableThemes; +} + +void SoundEngine::themeChangedSlot() +{ + QString themeName = settingsCache->getSoundThemeName(); + qDebug() << "Sound theme changed:" << themeName; + + QDir dir = getAvailableThemes().value(themeName); + + audioData.clear(); + + static const QStringList fileNames = QStringList() // Phases << "untap_step" << "upkeep_step" << "draw_step" << "main_1" << "start_combat" << "attack_step" << "block_step" << "damage_step" << "end_combat" @@ -18,56 +171,19 @@ // Spectator << "spectator_join" << "spectator_leave" // Chat & UI - << "chat_mention" << "all_mention" << "private_message"; -*/ + << "chat_mention" << "all_mention" << "private_message" + << "end_step" << "tap" << "player_joined" << "attack"; -#define TEST_SOUND_FILENAME "player_join" + for (int i = 0; i < fileNames.size(); ++i) { + if(!dir.exists(fileNames[i] + ".wav")) + continue; -SoundEngine::SoundEngine(QObject *parent) -: QObject(parent), enabled(false) -{ - connect(settingsCache, SIGNAL(soundEnabledChanged()), this, SLOT(soundEnabledChanged())); + QFile file(dir.filePath(fileNames[i] + ".wav")); + file.open(QIODevice::ReadOnly); + // 44 = length of wav header + audioData.insert(fileNames[i], file.readAll().mid(44)); + file.close(); + } soundEnabledChanged(); -} - -void SoundEngine::soundEnabledChanged() -{ - if (settingsCache->getSoundEnabled()) { -#if QT_VERSION < 0x050000 //QT4 - if(QSound::isAvailable()) - { - qDebug("SoundEngine: enabling sound"); - enabled = true; - } else { - qDebug("SoundEngine: sound not available"); - enabled = false; - } -#else - qDebug("SoundEngine: enabling sound"); - enabled = true; -#endif - } else { - qDebug("SoundEngine: disabling sound"); - enabled = false; - } -} - -#include -void SoundEngine::playSound(QString fileName) -{ - if(!enabled) - return; - - QFileInfo fi(settingsCache->getSoundPath() + "/" + fileName + ".wav"); - qDebug() << "playing" << fi.absoluteFilePath(); - if(!fi.exists()) - return; - - QSound::play(fi.absoluteFilePath()); -} - -void SoundEngine::testSound() -{ - playSound(TEST_SOUND_FILENAME); } \ No newline at end of file diff --git a/cockatrice/src/soundengine.h b/cockatrice/src/soundengine.h index 3ab2ed8f..ed15cbbf 100644 --- a/cockatrice/src/soundengine.h +++ b/cockatrice/src/soundengine.h @@ -2,16 +2,32 @@ #define SOUNDENGINE_H #include +#include +#include +#include + +class QAudioOutput; +class QBuffer; + +typedef QMap QStringMap; class SoundEngine : public QObject { Q_OBJECT -private: - bool enabled; -private slots: - void soundEnabledChanged(); public: SoundEngine(QObject *parent = 0); + ~SoundEngine(); void playSound(QString fileName); + QStringMap &getAvailableThemes(); +private: + QMap audioData; + QBuffer *inputBuffer; + QAudioOutput * player; + QStringMap availableThemes; +protected: + void ensureThemeDirectoryExists(); +private slots: + void soundEnabledChanged(); + void themeChangedSlot(); public slots: void testSound(); }; diff --git a/sounds/CMakeLists.txt b/sounds/CMakeLists.txt index 7712abb9..80babdc3 100644 --- a/sounds/CMakeLists.txt +++ b/sounds/CMakeLists.txt @@ -1,16 +1,19 @@ -# CMakeLists for sounds/ directory +# CMakeLists for sounds directory # -# Installs default sound files +# add sounds subfolders -FILE(GLOB sounds "${CMAKE_CURRENT_SOURCE_DIR}/*.wav") +SET(defsounds + Default + Legacy +) if(UNIX) if(APPLE) - INSTALL(FILES ${sounds} DESTINATION cockatrice.app/Contents/Resources/sounds/) + INSTALL(DIRECTORY ${defsounds} DESTINATION cockatrice.app/Contents/Resources/sounds/) else() # Assume linux - INSTALL(FILES ${sounds} DESTINATION share/cockatrice/sounds/) + INSTALL(DIRECTORY ${defsounds} DESTINATION share/cockatrice/sounds/) endif() elseif(WIN32) - INSTALL(FILES ${sounds} DESTINATION sounds/) -endif() \ No newline at end of file + INSTALL(DIRECTORY ${defsounds} DESTINATION sounds/) +endif() diff --git a/sounds/attack_step.wav b/sounds/Default/attack_step.wav similarity index 100% rename from sounds/attack_step.wav rename to sounds/Default/attack_step.wav diff --git a/sounds/end_step.wav b/sounds/Default/end_step.wav similarity index 100% rename from sounds/end_step.wav rename to sounds/Default/end_step.wav diff --git a/sounds/player_join.wav b/sounds/Default/player_join.wav similarity index 100% rename from sounds/player_join.wav rename to sounds/Default/player_join.wav diff --git a/sounds/start_combat.wav b/sounds/Default/start_combat.wav similarity index 100% rename from sounds/start_combat.wav rename to sounds/Default/start_combat.wav diff --git a/sounds/tap_card.wav b/sounds/Default/tap_card.wav similarity index 100% rename from sounds/tap_card.wav rename to sounds/Default/tap_card.wav diff --git a/sounds/Legacy/all_mention.wav b/sounds/Legacy/all_mention.wav new file mode 100644 index 00000000..6e8495cc Binary files /dev/null and b/sounds/Legacy/all_mention.wav differ diff --git a/sounds/Legacy/chat_mention.wav b/sounds/Legacy/chat_mention.wav new file mode 100644 index 00000000..6e8495cc Binary files /dev/null and b/sounds/Legacy/chat_mention.wav differ diff --git a/sounds/Legacy/draw_step.wav b/sounds/Legacy/draw_step.wav new file mode 100644 index 00000000..192c6b18 Binary files /dev/null and b/sounds/Legacy/draw_step.wav differ diff --git a/sounds/Legacy/play_card.wav b/sounds/Legacy/play_card.wav new file mode 100644 index 00000000..42436192 Binary files /dev/null and b/sounds/Legacy/play_card.wav differ diff --git a/sounds/Legacy/player_join.wav b/sounds/Legacy/player_join.wav new file mode 100644 index 00000000..58017929 Binary files /dev/null and b/sounds/Legacy/player_join.wav differ diff --git a/sounds/Legacy/private_message.wav b/sounds/Legacy/private_message.wav new file mode 100644 index 00000000..6e8495cc Binary files /dev/null and b/sounds/Legacy/private_message.wav differ diff --git a/sounds/Legacy/shuffle.wav b/sounds/Legacy/shuffle.wav new file mode 100644 index 00000000..b1402bca Binary files /dev/null and b/sounds/Legacy/shuffle.wav differ diff --git a/sounds/Legacy/tap_card.wav b/sounds/Legacy/tap_card.wav new file mode 100644 index 00000000..14f69853 Binary files /dev/null and b/sounds/Legacy/tap_card.wav differ diff --git a/sounds/Legacy/untap_card.wav b/sounds/Legacy/untap_card.wav new file mode 100644 index 00000000..2f669ef6 Binary files /dev/null and b/sounds/Legacy/untap_card.wav differ diff --git a/travis-dependencies.sh b/travis-dependencies.sh index cd86a892..63fdc24c 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -10,7 +10,7 @@ if [[ $TRAVIS_OS_NAME == "osx" ]] ; then else if (( QT4 )); then sudo apt-get update -qq - sudo apt-get install -y libprotobuf-dev protobuf-compiler libqt4-dev + sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev else sudo add-apt-repository -y ppa:beineri/opt-qt521 sudo add-apt-repository -y ppa:kalakris/cmake