From 9ab5223d352e330fb9e9362ad39e156e111d1cfb Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Tue, 27 Feb 2018 17:18:29 +0000 Subject: [PATCH 01/31] Revert "Use local game art ( image, marquee and video ) from romfolder/images if the gamelist didn't specify a path" This reverts commit cd2f2ee42b911711db6bd6e0276bea494a389e88. temporarily reverted for performance reasons - #381 --- es-app/src/FileData.cpp | 87 ++----------------- es-app/src/FileData.h | 7 +- .../views/gamelist/DetailedGameListView.cpp | 2 +- .../src/views/gamelist/VideoGameListView.cpp | 30 ++++++- 4 files changed, 39 insertions(+), 87 deletions(-) diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 0a26c21ac6..d60bfd62dd 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -50,32 +50,12 @@ std::string FileData::getCleanName() const return removeParenthesis(this->getDisplayName()); } -const std::string FileData::getThumbnailPath() const +const std::string& FileData::getThumbnailPath() const { - std::string thumbnail = metadata.get("thumbnail"); - - // no thumbnail, try image - if(thumbnail.empty()) - { - thumbnail = metadata.get("image"); - - // no image, try to use local image - if(thumbnail.empty()) - { - const char* extList[2] = { ".png", ".jpg" }; - for(int i = 0; i < 2; i++) - { - if(thumbnail.empty()) - { - std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-image" + extList[i]; - if(boost::filesystem::exists(path)) - thumbnail = path; - } - } - } - } - - return thumbnail; + if(!metadata.get("thumbnail").empty()) + return metadata.get("thumbnail"); + else + return metadata.get("image"); } const std::string& FileData::getName() @@ -103,63 +83,14 @@ const std::vector& FileData::getChildrenListToDisplay() { } } -const std::string FileData::getVideoPath() const -{ - std::string video = metadata.get("video"); - - // no video, try to use local video - if(video.empty()) - { - std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-video.mp4"; - if(boost::filesystem::exists(path)) - video = path; - } - - return video; -} - -const std::string FileData::getMarqueePath() const +const std::string& FileData::getVideoPath() const { - std::string marquee = metadata.get("marquee"); - - // no marquee, try to use local marquee - if(marquee.empty()) - { - const char* extList[2] = { ".png", ".jpg" }; - for(int i = 0; i < 2; i++) - { - if(marquee.empty()) - { - std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-marquee" + extList[i]; - if(boost::filesystem::exists(path)) - marquee = path; - } - } - } - - return marquee; + return metadata.get("video"); } -const std::string FileData::getImagePath() const +const std::string& FileData::getMarqueePath() const { - std::string image = metadata.get("image"); - - // no image, try to use local image - if(image.empty()) - { - const char* extList[2] = { ".png", ".jpg" }; - for(int i = 0; i < 2; i++) - { - if(image.empty()) - { - std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-image" + extList[i]; - if(boost::filesystem::exists(path)) - image = path; - } - } - } - - return image; + return metadata.get("marquee"); } std::vector FileData::getFilesRecursive(unsigned int typeMask, bool displayedOnly) const diff --git a/es-app/src/FileData.h b/es-app/src/FileData.h index 49c88630a4..f18e6c6bf6 100644 --- a/es-app/src/FileData.h +++ b/es-app/src/FileData.h @@ -44,10 +44,9 @@ class FileData inline const std::vector& getChildren() const { return mChildren; } inline SystemData* getSystem() const { return mSystem; } inline SystemEnvironmentData* getSystemEnvData() const { return mEnvData; } - virtual const std::string getThumbnailPath() const; - virtual const std::string getVideoPath() const; - virtual const std::string getMarqueePath() const; - virtual const std::string getImagePath() const; + virtual const std::string& getThumbnailPath() const; + virtual const std::string& getVideoPath() const; + virtual const std::string& getMarqueePath() const; const std::vector& getChildrenListToDisplay(); std::vector getFilesRecursive(unsigned int typeMask, bool displayedOnly = false) const; diff --git a/es-app/src/views/gamelist/DetailedGameListView.cpp b/es-app/src/views/gamelist/DetailedGameListView.cpp index e4b0203b04..b58ab5e0a7 100644 --- a/es-app/src/views/gamelist/DetailedGameListView.cpp +++ b/es-app/src/views/gamelist/DetailedGameListView.cpp @@ -190,7 +190,7 @@ void DetailedGameListView::updateInfoPanel() //mDescription.setText(""); fadingOut = true; }else{ - mImage.setImage(file->getImagePath()); + mImage.setImage(file->metadata.get("image")); mDescription.setText(file->metadata.get("desc")); mDescContainer.reset(); diff --git a/es-app/src/views/gamelist/VideoGameListView.cpp b/es-app/src/views/gamelist/VideoGameListView.cpp index a75df55f9a..4dd18fdadd 100644 --- a/es-app/src/views/gamelist/VideoGameListView.cpp +++ b/es-app/src/views/gamelist/VideoGameListView.cpp @@ -237,15 +237,37 @@ void VideoGameListView::updateInfoPanel() fadingOut = true; }else{ - if (!mVideo->setVideo(file->getVideoPath())) + std::string video_path; + std::string marquee_path; + std::string thumbnail_path; + video_path = file->getVideoPath(); + marquee_path = file->getMarqueePath(); + thumbnail_path = file->getThumbnailPath(); + + if (!video_path.empty() && (video_path[0] == '~')) + { + video_path.erase(0, 1); + video_path.insert(0, getHomePath()); + } + if (!marquee_path.empty() && (marquee_path[0] == '~')) + { + marquee_path.erase(0, 1); + marquee_path.insert(0, getHomePath()); + } + if (!thumbnail_path.empty() && (thumbnail_path[0] == '~')) + { + thumbnail_path.erase(0, 1); + thumbnail_path.insert(0, getHomePath()); + } + if (!mVideo->setVideo(video_path)) { mVideo->setDefaultVideo(); } mVideoPlaying = true; - mVideo->setImage(file->getThumbnailPath()); - mMarquee.setImage(file->getMarqueePath()); - mImage.setImage(file->getThumbnailPath()); + mVideo->setImage(thumbnail_path); + mMarquee.setImage(marquee_path); + mImage.setImage(thumbnail_path); mDescription.setText(file->metadata.get("desc")); mDescContainer.reset(); From 49ca22a2de073a85c20c1f15ec4420a36ec3c4eb Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Tue, 27 Feb 2018 17:19:37 +0000 Subject: [PATCH 02/31] bump version to v2.7.5 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 44d3247525..6ec1c57d70 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 7 -#define PROGRAM_VERSION_MAINTENANCE 4 -#define PROGRAM_VERSION_STRING "2.7.4rp" +#define PROGRAM_VERSION_MAINTENANCE 5 +#define PROGRAM_VERSION_STRING "2.7.5rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,7,4\0" +#define RESOURCE_VERSION_STRING "2,7,5\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 0330cfbda6cf928bf859e7221f6fdccd92355fab Mon Sep 17 00:00:00 2001 From: John Rassa Date: Wed, 23 May 2018 13:42:53 -0700 Subject: [PATCH 03/31] set curl to follow redirects to fix scraper error update to use legacy thegamesdb url --- es-app/src/scrapers/GamesDBScraper.cpp | 6 +++--- es-core/src/HttpReq.cpp | 27 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/es-app/src/scrapers/GamesDBScraper.cpp b/es-app/src/scrapers/GamesDBScraper.cpp index cc76d8903a..82b2020690 100644 --- a/es-app/src/scrapers/GamesDBScraper.cpp +++ b/es-app/src/scrapers/GamesDBScraper.cpp @@ -84,12 +84,12 @@ void thegamesdb_generate_scraper_requests(const ScraperSearchParams& params, std if (!cleanName.empty() && cleanName.substr(0,3) == "id:") { std::string gameID = cleanName.substr(3); - path = "thegamesdb.net/api/GetGame.php?id=" + HttpReq::urlEncode(gameID); + path = "legacy.thegamesdb.net/api/GetGame.php?id=" + HttpReq::urlEncode(gameID); usingGameID = true; }else{ if (cleanName.empty()) cleanName = params.game->getCleanName(); - path += "thegamesdb.net/api/GetGamesList.php?name=" + HttpReq::urlEncode(cleanName); + path += "legacy.thegamesdb.net/api/GetGamesList.php?name=" + HttpReq::urlEncode(cleanName); } if(usingGameID) @@ -204,7 +204,7 @@ void TheGamesDBRequest::processList(const pugi::xml_document& xmldoc, std::vecto for(int i = 0; game && i < MAX_SCRAPER_RESULTS; i++) { std::string id = game.child("id").text().get(); - std::string path = "thegamesdb.net/api/GetGame.php?id=" + id; + std::string path = "legacy.thegamesdb.net/api/GetGame.php?id=" + id; mRequestQueue->push(std::unique_ptr(new TheGamesDBRequest(results, path))); diff --git a/es-core/src/HttpReq.cpp b/es-core/src/HttpReq.cpp index f30d663c5f..b456fcf606 100644 --- a/es-core/src/HttpReq.cpp +++ b/es-core/src/HttpReq.cpp @@ -57,6 +57,33 @@ HttpReq::HttpReq(const std::string& url) return; } + //set curl to handle redirects + err = curl_easy_setopt(mHandle, CURLOPT_FOLLOWLOCATION, 1L); + if(err != CURLE_OK) + { + mStatus = REQ_IO_ERROR; + onError(curl_easy_strerror(err)); + return; + } + + //set curl max redirects + err = curl_easy_setopt(mHandle, CURLOPT_MAXREDIRS, 2L); + if(err != CURLE_OK) + { + mStatus = REQ_IO_ERROR; + onError(curl_easy_strerror(err)); + return; + } + + //set curl restrict redirect protocols + err = curl_easy_setopt(mHandle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + if(err != CURLE_OK) + { + mStatus = REQ_IO_ERROR; + onError(curl_easy_strerror(err)); + return; + } + //tell curl how to write the data err = curl_easy_setopt(mHandle, CURLOPT_WRITEFUNCTION, &HttpReq::write_content); if(err != CURLE_OK) From 920db2b620499574e1ba87c263f9bb88de4be8d5 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Wed, 11 Jul 2018 18:16:47 +0100 Subject: [PATCH 04/31] bump version to v2.7.6 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 6ec1c57d70..f54f34b638 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 7 -#define PROGRAM_VERSION_MAINTENANCE 5 -#define PROGRAM_VERSION_STRING "2.7.5rp" +#define PROGRAM_VERSION_MAINTENANCE 6 +#define PROGRAM_VERSION_STRING "2.7.6rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,7,5\0" +#define RESOURCE_VERSION_STRING "2,7,6\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 66853e5565ad4426ae4475e7daaf3c70789c4ac7 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sat, 9 Feb 2019 19:38:37 +0000 Subject: [PATCH 05/31] Revert "Revert "Use local game art ( image, marquee and video ) from romfolder/images if the gamelist didn't specify a path"" This reverts commit 9ab5223d352e330fb9e9362ad39e156e111d1cfb. --- es-app/src/FileData.cpp | 87 +++++++++++++++++-- es-app/src/FileData.h | 7 +- .../views/gamelist/DetailedGameListView.cpp | 2 +- .../src/views/gamelist/VideoGameListView.cpp | 30 +------ 4 files changed, 87 insertions(+), 39 deletions(-) diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index d60bfd62dd..0a26c21ac6 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -50,12 +50,32 @@ std::string FileData::getCleanName() const return removeParenthesis(this->getDisplayName()); } -const std::string& FileData::getThumbnailPath() const +const std::string FileData::getThumbnailPath() const { - if(!metadata.get("thumbnail").empty()) - return metadata.get("thumbnail"); - else - return metadata.get("image"); + std::string thumbnail = metadata.get("thumbnail"); + + // no thumbnail, try image + if(thumbnail.empty()) + { + thumbnail = metadata.get("image"); + + // no image, try to use local image + if(thumbnail.empty()) + { + const char* extList[2] = { ".png", ".jpg" }; + for(int i = 0; i < 2; i++) + { + if(thumbnail.empty()) + { + std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-image" + extList[i]; + if(boost::filesystem::exists(path)) + thumbnail = path; + } + } + } + } + + return thumbnail; } const std::string& FileData::getName() @@ -83,14 +103,63 @@ const std::vector& FileData::getChildrenListToDisplay() { } } -const std::string& FileData::getVideoPath() const +const std::string FileData::getVideoPath() const +{ + std::string video = metadata.get("video"); + + // no video, try to use local video + if(video.empty()) + { + std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-video.mp4"; + if(boost::filesystem::exists(path)) + video = path; + } + + return video; +} + +const std::string FileData::getMarqueePath() const { - return metadata.get("video"); + std::string marquee = metadata.get("marquee"); + + // no marquee, try to use local marquee + if(marquee.empty()) + { + const char* extList[2] = { ".png", ".jpg" }; + for(int i = 0; i < 2; i++) + { + if(marquee.empty()) + { + std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-marquee" + extList[i]; + if(boost::filesystem::exists(path)) + marquee = path; + } + } + } + + return marquee; } -const std::string& FileData::getMarqueePath() const +const std::string FileData::getImagePath() const { - return metadata.get("marquee"); + std::string image = metadata.get("image"); + + // no image, try to use local image + if(image.empty()) + { + const char* extList[2] = { ".png", ".jpg" }; + for(int i = 0; i < 2; i++) + { + if(image.empty()) + { + std::string path = mEnvData->mStartPath + "/images/" + getDisplayName() + "-image" + extList[i]; + if(boost::filesystem::exists(path)) + image = path; + } + } + } + + return image; } std::vector FileData::getFilesRecursive(unsigned int typeMask, bool displayedOnly) const diff --git a/es-app/src/FileData.h b/es-app/src/FileData.h index f18e6c6bf6..49c88630a4 100644 --- a/es-app/src/FileData.h +++ b/es-app/src/FileData.h @@ -44,9 +44,10 @@ class FileData inline const std::vector& getChildren() const { return mChildren; } inline SystemData* getSystem() const { return mSystem; } inline SystemEnvironmentData* getSystemEnvData() const { return mEnvData; } - virtual const std::string& getThumbnailPath() const; - virtual const std::string& getVideoPath() const; - virtual const std::string& getMarqueePath() const; + virtual const std::string getThumbnailPath() const; + virtual const std::string getVideoPath() const; + virtual const std::string getMarqueePath() const; + virtual const std::string getImagePath() const; const std::vector& getChildrenListToDisplay(); std::vector getFilesRecursive(unsigned int typeMask, bool displayedOnly = false) const; diff --git a/es-app/src/views/gamelist/DetailedGameListView.cpp b/es-app/src/views/gamelist/DetailedGameListView.cpp index b58ab5e0a7..e4b0203b04 100644 --- a/es-app/src/views/gamelist/DetailedGameListView.cpp +++ b/es-app/src/views/gamelist/DetailedGameListView.cpp @@ -190,7 +190,7 @@ void DetailedGameListView::updateInfoPanel() //mDescription.setText(""); fadingOut = true; }else{ - mImage.setImage(file->metadata.get("image")); + mImage.setImage(file->getImagePath()); mDescription.setText(file->metadata.get("desc")); mDescContainer.reset(); diff --git a/es-app/src/views/gamelist/VideoGameListView.cpp b/es-app/src/views/gamelist/VideoGameListView.cpp index 4dd18fdadd..a75df55f9a 100644 --- a/es-app/src/views/gamelist/VideoGameListView.cpp +++ b/es-app/src/views/gamelist/VideoGameListView.cpp @@ -237,37 +237,15 @@ void VideoGameListView::updateInfoPanel() fadingOut = true; }else{ - std::string video_path; - std::string marquee_path; - std::string thumbnail_path; - video_path = file->getVideoPath(); - marquee_path = file->getMarqueePath(); - thumbnail_path = file->getThumbnailPath(); - - if (!video_path.empty() && (video_path[0] == '~')) - { - video_path.erase(0, 1); - video_path.insert(0, getHomePath()); - } - if (!marquee_path.empty() && (marquee_path[0] == '~')) - { - marquee_path.erase(0, 1); - marquee_path.insert(0, getHomePath()); - } - if (!thumbnail_path.empty() && (thumbnail_path[0] == '~')) - { - thumbnail_path.erase(0, 1); - thumbnail_path.insert(0, getHomePath()); - } - if (!mVideo->setVideo(video_path)) + if (!mVideo->setVideo(file->getVideoPath())) { mVideo->setDefaultVideo(); } mVideoPlaying = true; - mVideo->setImage(thumbnail_path); - mMarquee.setImage(marquee_path); - mImage.setImage(thumbnail_path); + mVideo->setImage(file->getThumbnailPath()); + mMarquee.setImage(file->getMarqueePath()); + mImage.setImage(file->getThumbnailPath()); mDescription.setText(file->metadata.get("desc")); mDescContainer.reset(); From 2af2ec5f125bbacfb8a23a38cd3a1d049fd4cdf3 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sat, 9 Feb 2019 19:43:08 +0000 Subject: [PATCH 06/31] bump version to v2.8.0 --- es-app/src/EmulationStation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index f54f34b638..822d670db4 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -5,13 +5,13 @@ // These numbers and strings need to be manually updated for a new version. // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 -#define PROGRAM_VERSION_MINOR 7 -#define PROGRAM_VERSION_MAINTENANCE 6 -#define PROGRAM_VERSION_STRING "2.7.6rp" +#define PROGRAM_VERSION_MINOR 8 +#define PROGRAM_VERSION_MAINTENANCE 0 +#define PROGRAM_VERSION_STRING "2.8.0rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,7,6\0" +#define RESOURCE_VERSION_STRING "2,8,0\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 10ed2f21915f7ec5dbe1101229e5c1bfbff669de Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Tue, 12 Feb 2019 07:45:16 +0000 Subject: [PATCH 07/31] bump version to v2.8.1 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 822d670db4..b8bcb36554 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 8 -#define PROGRAM_VERSION_MAINTENANCE 0 -#define PROGRAM_VERSION_STRING "2.8.0rp" +#define PROGRAM_VERSION_MAINTENANCE 1 +#define PROGRAM_VERSION_STRING "2.8.1rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,8,0\0" +#define RESOURCE_VERSION_STRING "2,8,1\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 25ef0c8b77b7d4c1b5e84c330bef7472f432ab3a Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Mon, 4 Mar 2019 16:19:48 +0000 Subject: [PATCH 08/31] bump version to v2.8.2 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index b8bcb36554..1f0f65cc17 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 8 -#define PROGRAM_VERSION_MAINTENANCE 1 -#define PROGRAM_VERSION_STRING "2.8.1rp" +#define PROGRAM_VERSION_MAINTENANCE 2 +#define PROGRAM_VERSION_STRING "2.8.2rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,8,1\0" +#define RESOURCE_VERSION_STRING "2,8,2\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 5a4073439fb9dedc0f2858e5f3b3914498125105 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sat, 6 Apr 2019 02:33:16 +0100 Subject: [PATCH 09/31] Revert "InputManager: improve trigger axis calibration" --- es-core/src/InputManager.cpp | 24 +++++------------------- es-core/src/InputManager.h | 1 - 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/es-core/src/InputManager.cpp b/es-core/src/InputManager.cpp index dbf6e57882..08c16865ca 100644 --- a/es-core/src/InputManager.cpp +++ b/es-core/src/InputManager.cpp @@ -101,14 +101,7 @@ void InputManager::addJoystickByDeviceIndex(int id) // set up the prevAxisValues int numAxes = SDL_JoystickNumAxes(joy); mPrevAxisValues[joyId] = new int[numAxes]; - mInitAxisValues[joyId] = new int[numAxes]; - - int axis; - for (int i = 0; i< numAxes; i++) { - axis = SDL_JoystickGetAxis(joy, i); - mInitAxisValues[joyId][i] = axis; - mPrevAxisValues[joyId][i] = axis; - } + std::fill(mPrevAxisValues[joyId], mPrevAxisValues[joyId] + numAxes, 0); //initialize array to 0 } void InputManager::removeJoystickByJoystickID(SDL_JoystickID joyId) @@ -205,28 +198,21 @@ InputConfig* InputManager::getInputConfigByDevice(int device) bool InputManager::parseEvent(const SDL_Event& ev, Window* window) { bool causedEvent = false; - int axis; switch(ev.type) { case SDL_JOYAXISMOTION: - axis = ev.jaxis.value; - // Check for ABS_Z/ABS_RZ trigger axes which rest at -32768 - if ((ev.jaxis.axis == 2 || ev.jaxis.axis == 5) && mInitAxisValues[ev.jaxis.which][ev.jaxis.axis] == -32768) - { - // shift to 0 - 32767. - axis = axis / 2 + 16384; - } //if it switched boundaries - if((abs(axis) > DEADZONE) != (abs(mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis]) > DEADZONE)) + if((abs(ev.jaxis.value) > DEADZONE) != (abs(mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis]) > DEADZONE)) { int normValue; - if(abs(axis) <= DEADZONE) + if(abs(ev.jaxis.value) <= DEADZONE) normValue = 0; else - if(axis > 0) + if(ev.jaxis.value > 0) normValue = 1; else normValue = -1; + window->input(getInputConfigByDevice(ev.jaxis.which), Input(ev.jaxis.which, TYPE_AXIS, ev.jaxis.axis, normValue, false)); causedEvent = true; } diff --git a/es-core/src/InputManager.h b/es-core/src/InputManager.h index 74c4c3f866..fde96f0921 100644 --- a/es-core/src/InputManager.h +++ b/es-core/src/InputManager.h @@ -27,7 +27,6 @@ class InputManager InputConfig* mCECInputConfig; std::map mPrevAxisValues; - std::map mInitAxisValues; bool initialized() const; From 3a9297abbb84429138be4b4ee0f1e4c1d7726475 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sat, 6 Apr 2019 02:36:13 +0100 Subject: [PATCH 10/31] bump version to v2.8.3 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 1f0f65cc17..4133002dbf 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 8 -#define PROGRAM_VERSION_MAINTENANCE 2 -#define PROGRAM_VERSION_STRING "2.8.2rp" +#define PROGRAM_VERSION_MAINTENANCE 3 +#define PROGRAM_VERSION_STRING "2.8.3rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,8,2\0" +#define RESOURCE_VERSION_STRING "2,8,3\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 72b8644fc80e5c5b62684b0b6ee96c09389f9268 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Wed, 26 Jun 2019 05:16:33 +0100 Subject: [PATCH 11/31] bump version to v2.8.4 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 4133002dbf..76c83139ef 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 8 -#define PROGRAM_VERSION_MAINTENANCE 3 -#define PROGRAM_VERSION_STRING "2.8.3rp" +#define PROGRAM_VERSION_MAINTENANCE 4 +#define PROGRAM_VERSION_STRING "2.8.4rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,8,3\0" +#define RESOURCE_VERSION_STRING "2,8,4\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From a252ea2528883dc0893d72c67fa9c2f2c2317217 Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Fri, 26 Jul 2019 20:30:44 +0100 Subject: [PATCH 12/31] filterTrigger: filter negative trigger axis event after positive axis detection If filterTrigger detects a positive axis event on a common trigger axis while also configuring a trigger, the next input event will be a negative axis press (as the trigger needs to transition from >0 to rest at -32767). Filter this negative event or else the next item in the configuration dialog (typically "left thumb") will erroneously detect this as a separate event. --- es-core/src/guis/GuiInputConfig.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/es-core/src/guis/GuiInputConfig.cpp b/es-core/src/guis/GuiInputConfig.cpp index 29111a4841..d9c55ebbd4 100755 --- a/es-core/src/guis/GuiInputConfig.cpp +++ b/es-core/src/guis/GuiInputConfig.cpp @@ -346,16 +346,28 @@ bool GuiInputConfig::filterTrigger(Input input, InputConfig* config, int inputId && InputManager::getInstance()->getAxisCountByDevice(config->getDeviceId()) == 6) { // digital triggers are unwanted - if (input.type == TYPE_BUTTON && (input.id == 6 || input.id == 7)) + if(input.type == TYPE_BUTTON && (input.id == 6 || input.id == 7)) + { + mHoldingInput = false; return true; + } } // ignore negative pole for axes 2/5 only when triggers are being configured - if((mSkipAxis || strstr(GUI_INPUT_CONFIG_LIST[inputId].name, "Trigger") != NULL) \ - && input.type == TYPE_AXIS && (input.id == 2 || input.id == 5) && input.value < 0) + if(input.type == TYPE_AXIS && (input.id == 2 || input.id == 5)) { - mSkipAxis = true; - return true; + if(strstr(GUI_INPUT_CONFIG_LIST[inputId].name, "Trigger") != NULL) + { + if(input.value == 1) + mSkipAxis = true; + else if(input.value == -1) + return true; + } + else if(mSkipAxis) + { + mSkipAxis = false; + return true; + } } #endif From 7e6c2bf5a5383d419cf5a449144633aaa153ee81 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sun, 29 Dec 2019 21:18:14 +0000 Subject: [PATCH 13/31] bump version to v2.9.0 --- es-app/src/EmulationStation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 76c83139ef..3aadf8e0b8 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -5,13 +5,13 @@ // These numbers and strings need to be manually updated for a new version. // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 -#define PROGRAM_VERSION_MINOR 8 -#define PROGRAM_VERSION_MAINTENANCE 4 -#define PROGRAM_VERSION_STRING "2.8.4rp" +#define PROGRAM_VERSION_MINOR 9 +#define PROGRAM_VERSION_MAINTENANCE 0 +#define PROGRAM_VERSION_STRING "2.9.0rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,8,4\0" +#define RESOURCE_VERSION_STRING "2,9,0\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 49d440a59dbe95019b5ee21f85a71f48e2afcd8e Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sat, 11 Apr 2020 23:18:05 +0100 Subject: [PATCH 14/31] bump version to v2.9.1 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 3aadf8e0b8..01856abd74 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 9 -#define PROGRAM_VERSION_MAINTENANCE 0 -#define PROGRAM_VERSION_STRING "2.9.0rp" +#define PROGRAM_VERSION_MAINTENANCE 1 +#define PROGRAM_VERSION_STRING "2.9.1rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,9,0\0" +#define RESOURCE_VERSION_STRING "2,9,1\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From e56be5ec8ce695c1a841ed1074b83cb15d3a2b92 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Tue, 9 Jun 2020 01:27:01 +0100 Subject: [PATCH 15/31] bump version to v2.9.2 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 01856abd74..623fe030dc 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 9 -#define PROGRAM_VERSION_MAINTENANCE 1 -#define PROGRAM_VERSION_STRING "2.9.1rp" +#define PROGRAM_VERSION_MAINTENANCE 2 +#define PROGRAM_VERSION_STRING "2.9.2rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,9,1\0" +#define RESOURCE_VERSION_STRING "2,9,2\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 982f6ccb8d6fc5d541dc1c8981f2f8ac4bf84d0e Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Thu, 11 Jun 2020 04:18:36 +0100 Subject: [PATCH 16/31] bump version to v2.9.3 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 623fe030dc..ffc9b0fe92 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 9 -#define PROGRAM_VERSION_MAINTENANCE 2 -#define PROGRAM_VERSION_STRING "2.9.2rp" +#define PROGRAM_VERSION_MAINTENANCE 3 +#define PROGRAM_VERSION_STRING "2.9.3rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,9,2\0" +#define RESOURCE_VERSION_STRING "2,9,3\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From be9e0f323ba67b8b18161397a0c739345d4d1936 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sun, 1 Nov 2020 21:39:18 +0000 Subject: [PATCH 17/31] bump version to v2.9.4 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index ffc9b0fe92..8e058b51aa 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 9 -#define PROGRAM_VERSION_MAINTENANCE 3 -#define PROGRAM_VERSION_STRING "2.9.3rp" +#define PROGRAM_VERSION_MAINTENANCE 4 +#define PROGRAM_VERSION_STRING "2.9.4rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,9,3\0" +#define RESOURCE_VERSION_STRING "2,9,4\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 2d6e4252600a008a462207d240419eb7e4c32ed6 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Tue, 3 Nov 2020 20:08:17 +0000 Subject: [PATCH 18/31] bump version to v2.9.5 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 8e058b51aa..9c32d1d015 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 9 -#define PROGRAM_VERSION_MAINTENANCE 4 -#define PROGRAM_VERSION_STRING "2.9.4rp" +#define PROGRAM_VERSION_MAINTENANCE 5 +#define PROGRAM_VERSION_STRING "2.9.5rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,9,4\0" +#define RESOURCE_VERSION_STRING "2,9,5\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From be5dcaf228edd2bfd8d2d6a1e6874698bdbf95c0 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Wed, 4 Nov 2020 14:45:31 +0000 Subject: [PATCH 19/31] bump version to v2.9.6 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 9c32d1d015..e02cf74bca 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 9 -#define PROGRAM_VERSION_MAINTENANCE 5 -#define PROGRAM_VERSION_STRING "2.9.5rp" +#define PROGRAM_VERSION_MAINTENANCE 6 +#define PROGRAM_VERSION_STRING "2.9.6rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,9,5\0" +#define RESOURCE_VERSION_STRING "2,9,6\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From c8056701b61b15ac1081e2d01e586e3f48ba8d6a Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sun, 31 Oct 2021 18:36:38 +0000 Subject: [PATCH 20/31] bump version to v2.10.0 --- es-app/src/EmulationStation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index e02cf74bca..7a239fa82f 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -5,13 +5,13 @@ // These numbers and strings need to be manually updated for a new version. // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 -#define PROGRAM_VERSION_MINOR 9 -#define PROGRAM_VERSION_MAINTENANCE 6 -#define PROGRAM_VERSION_STRING "2.9.6rp" +#define PROGRAM_VERSION_MINOR 10 +#define PROGRAM_VERSION_MAINTENANCE 0 +#define PROGRAM_VERSION_STRING "2.10.0rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,9,6\0" +#define RESOURCE_VERSION_STRING "2,10,0\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 1d05ae4f927a255351f15041ed5f5fbe74b10572 Mon Sep 17 00:00:00 2001 From: pjft Date: Sun, 26 Dec 2021 09:13:43 +0000 Subject: [PATCH 21/31] Revert default ThreadedLoading option --- es-core/src/Settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 71317c979d..5ffefbcfc5 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -80,7 +80,7 @@ void Settings::setDefaults() mBoolMap["QuickSystemSelect"] = true; mBoolMap["MoveCarousel"] = true; - mBoolMap["ThreadedLoading"] = true; + mBoolMap["ThreadedLoading"] = false; mBoolMap["Debug"] = false; mBoolMap["DebugGrid"] = false; From c9d905c31acf4b92d0a76b76c5cdf49e2b266d43 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sun, 26 Dec 2021 15:38:57 +0000 Subject: [PATCH 22/31] bump version to v2.10.1 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 7a239fa82f..53a1b1cbe3 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 10 -#define PROGRAM_VERSION_MAINTENANCE 0 -#define PROGRAM_VERSION_STRING "2.10.0rp" +#define PROGRAM_VERSION_MAINTENANCE 1 +#define PROGRAM_VERSION_STRING "2.10.1rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,10,0\0" +#define RESOURCE_VERSION_STRING "2,10,1\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE #endif // ES_APP_EMULATION_STATION_H From 2dd5e6b67932e300e56bc8a18091d7a09bc5122b Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Mon, 7 Mar 2022 01:08:31 +0000 Subject: [PATCH 23/31] bump version to v2.10.2 --- es-app/src/EmulationStation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/es-app/src/EmulationStation.h b/es-app/src/EmulationStation.h index 06a07e4970..1e8f3e6587 100644 --- a/es-app/src/EmulationStation.h +++ b/es-app/src/EmulationStation.h @@ -6,12 +6,12 @@ // Do this version number update as the very last commit for the new release version. #define PROGRAM_VERSION_MAJOR 2 #define PROGRAM_VERSION_MINOR 10 -#define PROGRAM_VERSION_MAINTENANCE 1 -#define PROGRAM_VERSION_STRING "2.10.1rp" +#define PROGRAM_VERSION_MAINTENANCE 2 +#define PROGRAM_VERSION_STRING "2.10.2rp" #define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__ -#define RESOURCE_VERSION_STRING "2,10,1\0" +#define RESOURCE_VERSION_STRING "2,10,2\0" #define RESOURCE_VERSION PROGRAM_VERSION_MAJOR,PROGRAM_VERSION_MINOR,PROGRAM_VERSION_MAINTENANCE From 0091d04983cb7da40b0d46c45dd8abd1ff0f5a77 Mon Sep 17 00:00:00 2001 From: bluestang2006 Date: Mon, 7 Mar 2022 17:33:21 -0700 Subject: [PATCH 24/31] Background Music Player - Add a background music player using SDL2 mixer - Backport various fixes --- .github/workflows/ccpp.yml | 2 +- CMake/Packages/FindSDL2_mixer.cmake | 220 ++++++++++++++++++++++ CMakeLists.txt | 3 + es-app/CMakeLists.txt | 4 +- es-app/src/FileData.cpp | 3 + es-app/src/VolumeControl.cpp | 116 ++++++++---- es-app/src/VolumeControl.h | 6 +- es-app/src/guis/GuiMenu.cpp | 15 ++ es-app/src/main.cpp | 5 + es-core/src/AudioManager.cpp | 279 ++++++++++++++++++++-------- es-core/src/AudioManager.h | 25 ++- es-core/src/Settings.cpp | 53 +++++- es-core/src/Settings.h | 23 ++- es-core/src/Sound.cpp | 135 ++++---------- es-core/src/Sound.h | 15 +- 15 files changed, 657 insertions(+), 247 deletions(-) create mode 100644 CMake/Packages/FindSDL2_mixer.cmake diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index a020bef060..e31f33f308 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -13,7 +13,7 @@ jobs: - name: configure run: | sudo apt-get update - sudo apt-get install libsdl2-dev libfreeimage-dev libfreetype6-dev libcurl4-openssl-dev rapidjson-dev libasound2-dev libgl1-mesa-dev build-essential cmake fonts-droid-fallback libvlc-dev libvlccore-dev vlc-bin + sudo apt-get install libsdl2-dev libsdl2-mixer-dev libfreeimage-dev libfreetype6-dev libcurl4-openssl-dev rapidjson-dev libasound2-dev libgl1-mesa-dev build-essential cmake fonts-droid-fallback libvlc-dev libvlccore-dev vlc-bin shell: bash - name: make run: | diff --git a/CMake/Packages/FindSDL2_mixer.cmake b/CMake/Packages/FindSDL2_mixer.cmake new file mode 100644 index 0000000000..a71f26a83b --- /dev/null +++ b/CMake/Packages/FindSDL2_mixer.cmake @@ -0,0 +1,220 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Copyright 2019 Amine Ben Hassouna +# Copyright 2000-2019 Kitware, Inc. and Contributors +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: + +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. + +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. + +# * Neither the name of Kitware, Inc. nor the names of Contributors +# may be used to endorse or promote products derived from this +# software without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#[=======================================================================[.rst: +FindSDL2_mixer +-------------- + +Locate SDL2_mixer library + +This module defines the following 'IMPORTED' target: + +:: + + SDL2::Mixer + The SDL2_mixer library, if found. + Have SDL2::Core as a link dependency. + + + +This module will set the following variables in your project: + +:: + + SDL2_MIXER_LIBRARIES, the name of the library to link against + SDL2_MIXER_INCLUDE_DIRS, where to find the headers + SDL2_MIXER_FOUND, if false, do not try to link against + SDL2_MIXER_VERSION_STRING - human-readable string containing the + version of SDL2_mixer + +This module responds to the following cache variables: + +:: + + SDL2_MIXER_PATH + Set a custom SDL2_mixer Library path (default: empty) + + SDL2_MIXER_NO_DEFAULT_PATH + Disable search SDL2_mixer Library in default path. + If SDL2_MIXER_PATH (default: ON) + Else (default: OFF) + + SDL2_MIXER_INCLUDE_DIR + SDL2_mixer headers path. + + SDL2_MIXER_LIBRARY + SDL2_mixer Library (.dll, .so, .a, etc) path. + + +Additional Note: If you see an empty SDL2_MIXER_LIBRARY in your project +configuration, it means CMake did not find your SDL2_mixer library +(SDL2_mixer.dll, libsdl2_mixer.so, etc). Set SDL2_MIXER_LIBRARY to point +to your SDL2_mixer library, and configure again. This value is used to +generate the final SDL2_MIXER_LIBRARIES variable and the SDL2::Mixer target, +but when this value is unset, SDL2_MIXER_LIBRARIES and SDL2::Mixer does not +get created. + + +$SDL2MIXERDIR is an environment variable that would correspond to the +./configure --prefix=$SDL2MIXERDIR used in building SDL2_mixer. + +$SDL2DIR is an environment variable that would correspond to the +./configure --prefix=$SDL2DIR used in building SDL2. + + + +Created by Amine Ben Hassouna: + Adapt FindSDL_mixer.cmake to SDL2_mixer (FindSDL2_mixer.cmake). + Add cache variables for more flexibility: + SDL2_MIXER_PATH, SDL2_MIXER_NO_DEFAULT_PATH (for details, see doc above). + Add SDL2 as a required dependency. + Modernize the FindSDL2_mixer.cmake module by creating a specific target: + SDL2::Mixer (for details, see doc above). + +Original FindSDL_mixer.cmake module: + Created by Eric Wing. This was influenced by the FindSDL.cmake + module, but with modifications to recognize OS X frameworks and + additional Unix paths (FreeBSD, etc). +#]=======================================================================] + +# SDL2 Library required +find_package(SDL2 QUIET) +if(NOT SDL2_FOUND) + set(SDL2_MIXER_SDL2_NOT_FOUND "Could NOT find SDL2 (SDL2 is required by SDL2_mixer).") + if(SDL2_mixer_FIND_REQUIRED) + message(FATAL_ERROR ${SDL2_MIXER_SDL2_NOT_FOUND}) + else() + if(NOT SDL2_mixer_FIND_QUIETLY) + message(STATUS ${SDL2_MIXER_SDL2_NOT_FOUND}) + endif() + return() + endif() + unset(SDL2_MIXER_SDL2_NOT_FOUND) +endif() + + +# Define options for searching SDL2_mixer Library in a custom path + +set(SDL2_MIXER_PATH "" CACHE STRING "Custom SDL2_mixer Library path") + +set(_SDL2_MIXER_NO_DEFAULT_PATH OFF) +if(SDL2_MIXER_PATH) + set(_SDL2_MIXER_NO_DEFAULT_PATH ON) +endif() + +set(SDL2_MIXER_NO_DEFAULT_PATH ${_SDL2_MIXER_NO_DEFAULT_PATH} + CACHE BOOL "Disable search SDL2_mixer Library in default path") +unset(_SDL2_MIXER_NO_DEFAULT_PATH) + +set(SDL2_MIXER_NO_DEFAULT_PATH_CMD) +if(SDL2_MIXER_NO_DEFAULT_PATH) + set(SDL2_MIXER_NO_DEFAULT_PATH_CMD NO_DEFAULT_PATH) +endif() + +# Search for the SDL2_mixer include directory +find_path(SDL2_MIXER_INCLUDE_DIR SDL_mixer.h + HINTS + ENV SDL2MIXERDIR + ENV SDL2DIR + ${SDL2_MIXER_NO_DEFAULT_PATH_CMD} + PATH_SUFFIXES SDL2 + # path suffixes to search inside ENV{SDL2DIR} + # and ENV{SDL2MIXERDIR} + include/SDL2 include + PATHS ${SDL2_MIXER_PATH} + DOC "Where the SDL2_mixer headers can be found" +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(VC_LIB_PATH_SUFFIX lib/x64) +else() + set(VC_LIB_PATH_SUFFIX lib/x86) +endif() + +# Search for the SDL2_mixer library +find_library(SDL2_MIXER_LIBRARY + NAMES SDL2_mixer + HINTS + ENV SDL2MIXERDIR + ENV SDL2DIR + ${SDL2_MIXER_NO_DEFAULT_PATH_CMD} + PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} + PATHS ${SDL2_MIXER_PATH} + DOC "Where the SDL2_mixer Library can be found" +) + +# Read SDL2_mixer version +if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}") + set(SDL2_MIXER_VERSION_STRING ${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH}) + unset(SDL2_MIXER_VERSION_MAJOR_LINE) + unset(SDL2_MIXER_VERSION_MINOR_LINE) + unset(SDL2_MIXER_VERSION_PATCH_LINE) + unset(SDL2_MIXER_VERSION_MAJOR) + unset(SDL2_MIXER_VERSION_MINOR) + unset(SDL2_MIXER_VERSION_PATCH) +endif() + +set(SDL2_MIXER_LIBRARIES ${SDL2_MIXER_LIBRARY}) +set(SDL2_MIXER_INCLUDE_DIRS ${SDL2_MIXER_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_mixer + REQUIRED_VARS SDL2_MIXER_LIBRARIES SDL2_MIXER_INCLUDE_DIRS + VERSION_VAR SDL2_MIXER_VERSION_STRING) + + +mark_as_advanced(SDL2_MIXER_PATH + SDL2_MIXER_NO_DEFAULT_PATH + SDL2_MIXER_LIBRARY + SDL2_MIXER_INCLUDE_DIR) + + +if(SDL2_MIXER_FOUND) + + # SDL2::Mixer target + if(SDL2_MIXER_LIBRARY AND NOT TARGET SDL2::Mixer) + add_library(SDL2::Mixer UNKNOWN IMPORTED) + set_target_properties(SDL2::Mixer PROPERTIES + IMPORTED_LOCATION "${SDL2_MIXER_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${SDL2_MIXER_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES SDL2::Core) + endif() +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index eb9f403ccf..2a869ac66c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,7 @@ endif() find_package(Freetype REQUIRED) find_package(FreeImage REQUIRED) find_package(SDL2 REQUIRED) +find_package(SDL2_mixer REQUIRED) find_package(CURL REQUIRED) find_package(VLC REQUIRED) find_package(RapidJSON REQUIRED) @@ -160,6 +161,7 @@ set(COMMON_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIRS} ${FreeImage_INCLUDE_DIRS} ${SDL2_INCLUDE_DIR} + ${SDL2_MIXER_INCLUDE_DIR} ${CURL_INCLUDE_DIR} ${VLC_INCLUDE_DIR} ${RAPIDJSON_INCLUDE_DIRS} @@ -198,6 +200,7 @@ set(COMMON_LIBRARIES ${FREETYPE_LIBRARIES} ${FreeImage_LIBRARIES} ${SDL2_LIBRARY} + ${SDL2_MIXER_LIBRARY} ${CURL_LIBRARIES} ${VLC_LIBRARIES} pugixml diff --git a/es-app/CMakeLists.txt b/es-app/CMakeLists.txt index 4ff4fdcce9..b00dcc013f 100644 --- a/es-app/CMakeLists.txt +++ b/es-app/CMakeLists.txt @@ -158,8 +158,8 @@ SET(CPACK_RESOURCE_FILE README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Alec Lofquist ") SET(CPACK_DEBIAN_PACKAGE_SECTION "misc") SET(CPACK_DEBIAN_PACKAGE_PRIORITY "extra") -SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libsdl2-2.0-0, libfreeimage3, libfreetype6, libcurl3, libasound2") -SET(CPACK_DEBIAN_PACKAGE_BUILDS_DEPENDS "debhelper (>= 8.0.0), cmake, g++ (>= 4.8), libsdl2-dev, libfreeimage-dev, libfreetype6-dev, libcurl4-openssl-dev, libasound2-dev, libgl1-mesa-dev, rapidjson-dev") +SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libsdl2-2.0-0, libsdl2-mixer-2.0-0, libfreeimage3, libfreetype6, libcurl3, libasound2") +SET(CPACK_DEBIAN_PACKAGE_BUILDS_DEPENDS "debhelper (>= 8.0.0), cmake, g++ (>= 4.8), libsdl2-dev, libsdl2-mixer-dev, libfreeimage-dev, libfreetype6-dev, libcurl4-openssl-dev, libasound2-dev, libgl1-mesa-dev, rapidjson-dev") SET(CPACK_PACKAGE_VENDOR "emulationstation.org") SET(CPACK_PACKAGE_VERSION "2.0.0~rc1") diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 5d8d5fa0e0..f2d6b27136 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -299,6 +299,7 @@ void FileData::launchGame(Window* window) window->init(); VolumeControl::getInstance()->init(); + AudioManager::getInstance()->init(); window->normalizeNextUpdate(); //update number of times the game has been launched @@ -313,6 +314,8 @@ void FileData::launchGame(Window* window) CollectionSystemManager::get()->refreshCollectionSystems(gameToUpdate); gameToUpdate->mSystem->onMetaDataSavePoint(); + + AudioManager::getInstance()->playRandomMusic(); } CollectionFileData::CollectionFileData(FileData* file, SystemData* system) diff --git a/es-app/src/VolumeControl.cpp b/es-app/src/VolumeControl.cpp index 80d18dfdc0..8ee6d74865 100644 --- a/es-app/src/VolumeControl.cpp +++ b/es-app/src/VolumeControl.cpp @@ -8,12 +8,12 @@ #endif #if defined(__linux__) - #if defined(_RPI_) || defined(_VERO4K_) - const char * VolumeControl::mixerName = "PCM"; - #else - const char * VolumeControl::mixerName = "Master"; - #endif - const char * VolumeControl::mixerCard = "default"; +#if defined(_RPI_) || defined(_VERO4K_) + std::string VolumeControl::mixerName = "PCM"; +#else + std::string VolumeControl::mixerName = "Master"; +#endif + std::string VolumeControl::mixerCard = "default"; #endif std::weak_ptr VolumeControl::sInstance; @@ -87,19 +87,24 @@ void VolumeControl::init() if (mixerHandle == nullptr) { // Allow users to override the AudioCard and MixerName in es_settings.cfg - mixerCard = Settings::getInstance()->getString("AudioCard").c_str(); - mixerName = Settings::getInstance()->getString("AudioDevice").c_str(); + auto audioCard = Settings::getInstance()->getString("AudioCard"); + if (!audioCard.empty()) + mixerCard = audioCard; + + auto audioDevice = Settings::getInstance()->getString("AudioDevice"); + if (!audioDevice.empty()) + mixerName = audioDevice; snd_mixer_selem_id_alloca(&mixerSelemId); //sets simple-mixer index and name snd_mixer_selem_id_set_index(mixerSelemId, mixerIndex); - snd_mixer_selem_id_set_name(mixerSelemId, mixerName); + snd_mixer_selem_id_set_name(mixerSelemId, mixerName.c_str()); //open mixer if (snd_mixer_open(&mixerHandle, 0) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Opened ALSA mixer"; //ok. attach to defualt card - if (snd_mixer_attach(mixerHandle, mixerCard) >= 0) + if (snd_mixer_attach(mixerHandle, mixerCard.c_str()) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Attached to default card"; //ok. register simple element class @@ -119,9 +124,39 @@ void VolumeControl::init() } else { - LOG(LogError) << "VolumeControl::init() - Failed to find mixer elements!"; - snd_mixer_close(mixerHandle); - mixerHandle = nullptr; + LOG(LogInfo) << "VolumeControl::init() - Unable to find mixer " << mixerName << " -> Search for alternative mixer"; + + snd_mixer_selem_id_t *mxid = nullptr; + snd_mixer_selem_id_alloca(&mxid); + + for (snd_mixer_elem_t* mxe = snd_mixer_first_elem(mixerHandle); mxe != nullptr; mxe = snd_mixer_elem_next(mxe)) + { + if (snd_mixer_selem_has_playback_volume(mxe) != 0 && snd_mixer_selem_is_active(mxe) != 0) + { + snd_mixer_selem_get_id(mxe, mxid); + mixerName = snd_mixer_selem_id_get_name(mxid); + + LOG(LogInfo) << "mixername : " << mixerName; + + snd_mixer_selem_id_set_name(mixerSelemId, mixerName.c_str()); + mixerElem = snd_mixer_find_selem(mixerHandle, mixerSelemId); + if (mixerElem != nullptr) + { + //wohoo. good to go... + LOG(LogDebug) << "VolumeControl::init() - Mixer initialized"; + break; + } + else + LOG(LogDebug) << "VolumeControl::init() - Mixer not initialized"; + } + } + + if (mixerElem == nullptr) + { + LOG(LogError) << "VolumeControl::init() - Failed to find mixer elements!"; + snd_mixer_close(mixerHandle); + mixerHandle = nullptr; + } } } else @@ -232,7 +267,7 @@ void VolumeControl::deinit() #error TODO: Not implemented for MacOS yet!!! #elif defined(__linux__) if (mixerHandle != nullptr) { - snd_mixer_detach(mixerHandle, mixerCard); + snd_mixer_detach(mixerHandle, mixerCard.c_str()); snd_mixer_free(mixerHandle); snd_mixer_close(mixerHandle); mixerHandle = nullptr; @@ -260,6 +295,20 @@ int VolumeControl::getVolume() const #elif defined(__linux__) if (mixerElem != nullptr) { + if (mixerHandle != nullptr) + snd_mixer_handle_events(mixerHandle); + + /* Disabled see commit 38ce42faef8aae3f9c180560bfdedd9d1b954d28 + * https://github.com/batocera-linux/batocera-emulationstation/ + int mute_state; + if (snd_mixer_selem_has_playback_switch(mixerElem)) + { + snd_mixer_selem_get_playback_switch(mixerElem, SND_MIXER_SCHN_UNKNOWN, &mute_state); + if (!mute_state) // system Muted + return 0; + } + */ + //get volume range long minVolume; long maxVolume; @@ -275,7 +324,6 @@ int VolumeControl::getVolume() const { volume = (rawVolume * 100.0) / (maxVolume - minVolume) + 0.5; } - //else volume = 0; } else { @@ -300,39 +348,32 @@ int VolumeControl::getVolume() const mixerControlDetails.paDetails = &value; mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); if (mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) - { volume = (int)Math::round((value.dwValue * 100) / 65535.0f); - } - else - { - LOG(LogError) << "VolumeControl::getVolume() - Failed to get mixer volume!"; - } } else if (endpointVolume != nullptr) { //Windows Vista or above. use EndpointVolume API float floatVolume = 0.0f; //0-1 - if (endpointVolume->GetMasterVolumeLevelScalar(&floatVolume) == S_OK) - { - volume = (int)Math::round(floatVolume * 100.0f); - LOG(LogInfo) << " getting volume as " << volume << " ( from float " << floatVolume << ")"; - } - else + + BOOL mute = FALSE; + if (endpointVolume->GetMute(&mute) == S_OK) { - LOG(LogError) << "VolumeControl::getVolume() - Failed to get master volume!"; + if (mute) + return 0; } + if (endpointVolume->GetMasterVolumeLevelScalar(&floatVolume) == S_OK) + volume = (int)Math::round(floatVolume * 100.0f); } #endif + //clamp to 0-100 range if (volume < 0) - { volume = 0; - } + if (volume > 100) - { volume = 100; - } + return volume; } @@ -404,3 +445,14 @@ void VolumeControl::setVolume(int volume) } #endif } + +bool VolumeControl::isAvailable() +{ +#if defined (__APPLE__) + return false; +#elif defined(__linux__) + return mixerHandle != nullptr && mixerElem != nullptr; +#elif defined(WIN32) || defined(_WIN32) + return mixerHandle != nullptr || endpointVolume != nullptr; +#endif +} diff --git a/es-app/src/VolumeControl.h b/es-app/src/VolumeControl.h index a2e420e7e2..adae297de2 100644 --- a/es-app/src/VolumeControl.h +++ b/es-app/src/VolumeControl.h @@ -24,8 +24,8 @@ class VolumeControl #if defined (__APPLE__) #error TODO: Not implemented for MacOS yet!!! #elif defined(__linux__) - static const char * mixerName; - static const char * mixerCard; + static std::string mixerName; + static std::string mixerCard; int mixerIndex; snd_mixer_t* mixerHandle; snd_mixer_elem_t* mixerElem; @@ -51,6 +51,8 @@ class VolumeControl void init(); void deinit(); + bool isAvailable(); + int getVolume() const; void setVolume(int volume); diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 224e6511b5..b40a150138 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -11,6 +11,7 @@ #include "guis/GuiSettings.h" #include "views/UIModeController.h" #include "views/ViewController.h" +#include "AudioManager.h" #include "CollectionSystemManager.h" #include "EmulationStation.h" #include "Scripting.h" @@ -158,6 +159,20 @@ void GuiMenu::openSoundSettings() } Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); }); + + auto music_enabled = std::make_shared(mWindow); + music_enabled->setState(Settings::getInstance()->getBool("EnableMusic")); + s->addWithLabel("BACKGROUND MUSIC", music_enabled); + s->addSaveFunc([music_enabled] + { + if (Settings::getInstance()->setBool("EnableMusic", music_enabled->getState())) + { + if (music_enabled->getState()) + AudioManager::getInstance()->playRandomMusic(); + else + AudioManager::getInstance()->stopMusic(); + } + }); auto video_audio = std::make_shared(mWindow); video_audio->setState(Settings::getInstance()->getBool("VideoAudio")); diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 956d4aed01..8d64f77cad 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -6,6 +6,7 @@ #include "utils/FileSystemUtil.h" #include "utils/ProfilingUtil.h" #include "views/ViewController.h" +#include "AudioManager.h" #include "CollectionSystemManager.h" #include "EmulationStation.h" #include "InputManager.h" @@ -394,6 +395,10 @@ int main(int argc, char* argv[]) for(Uint32 ev_type: event_list) { SDL_FlushEvent(ev_type); } + + // RetroPie BGM + AudioManager::getInstance()->init(); + AudioManager::getInstance()->playRandomMusic(); int lastTime = SDL_GetTicks(); int ps_time = SDL_GetTicks(); diff --git a/es-core/src/AudioManager.cpp b/es-core/src/AudioManager.cpp index 1d0f8ac495..f9ea469617 100644 --- a/es-core/src/AudioManager.cpp +++ b/es-core/src/AudioManager.cpp @@ -4,54 +4,14 @@ #include "Settings.h" #include "Sound.h" #include +#include "utils/FileSystemUtil.h" +#include "utils/StringUtil.h" +#include +AudioManager* AudioManager::sInstance = NULL; std::vector> AudioManager::sSoundVector; -SDL_AudioSpec AudioManager::sAudioFormat; -std::shared_ptr AudioManager::sInstance; - -void AudioManager::mixAudio(void* /*unused*/, Uint8 *stream, int len) -{ - bool stillPlaying = false; - - //initialize the buffer to "silence" - SDL_memset(stream, 0, len); - - //iterate through all our samples - std::vector>::const_iterator soundIt = sSoundVector.cbegin(); - while (soundIt != sSoundVector.cend()) - { - std::shared_ptr sound = *soundIt; - if(sound->isPlaying()) - { - //calculate rest length of current sample - Uint32 restLength = (sound->getLength() - sound->getPosition()); - if (restLength > (Uint32)len) { - //if stream length is smaller than smaple lenght, clip it - restLength = len; - } - //mix sample into stream - SDL_MixAudio(stream, &(sound->getData()[sound->getPosition()]), restLength, SDL_MIX_MAXVOLUME); - if (sound->getPosition() + restLength < sound->getLength()) - { - //sample hasn't ended yet - stillPlaying = true; - } - //set new sound position. if this is at or beyond the end of the sample, it will stop automatically - sound->setPosition(sound->getPosition() + restLength); - } - //advance to next sound - ++soundIt; - } - - //we have processed all samples. check if some will still be playing - if (!stillPlaying) { - //no. pause audio till a Sound::play() wakes us up - SDL_PauseAudio(1); - } -} - -AudioManager::AudioManager() +AudioManager::AudioManager() : mInitialized(false), mCurrentMusic(nullptr) { init(); } @@ -61,54 +21,71 @@ AudioManager::~AudioManager() deinit(); } -std::shared_ptr & AudioManager::getInstance() +AudioManager* AudioManager::getInstance() { //check if an AudioManager instance is already created, if not create one - if (sInstance == nullptr && Settings::getInstance()->getBool("EnableSounds")) { - sInstance = std::shared_ptr(new AudioManager); - } + if(sInstance == nullptr) + sInstance = new AudioManager(); + return sInstance; } +bool AudioManager::isInitialized() +{ + if(sInstance == nullptr) + return false; + + return sInstance->mInitialized; +} + void AudioManager::init() { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) + if(mInitialized) + return; + + mMusicVolume = 0; + + if(SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) { LOG(LogError) << "Error initializing SDL audio!\n" << SDL_GetError(); return; } - //stop playing all Sounds - for(unsigned int i = 0; i < sSoundVector.size(); i++) + // Open the audio device and pause + if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096) < 0) + LOG(LogError) << "MUSIC Error - Unable to open SDLMixer audio: " << SDL_GetError() << std::endl; + else { - if(sSoundVector.at(i)->isPlaying()) - { - sSoundVector[i]->stop(); - } - } + LOG(LogInfo) << "SDL AUDIO Initialized"; + mInitialized = true; - //Set up format and callback. Play 16-bit stereo audio at 44.1Khz - sAudioFormat.freq = 44100; - sAudioFormat.format = AUDIO_S16; - sAudioFormat.channels = 2; - sAudioFormat.samples = 4096; - sAudioFormat.callback = mixAudio; - sAudioFormat.userdata = NULL; - - //Open the audio device and pause - if (SDL_OpenAudio(&sAudioFormat, NULL) < 0) { - LOG(LogError) << "AudioManager Error - Unable to open SDL audio: " << SDL_GetError() << std::endl; + // Reload known sounds + for(unsigned int i = 0; i < sSoundVector.size(); i++) + sSoundVector[i]->init(); } } void AudioManager::deinit() { + if(!mInitialized) + return; + + mInitialized = false; + //stop all playback stop(); + stopMusic(); + + // Free known sounds from memory + for(unsigned int i = 0; i < sSoundVector.size(); i++) + sSoundVector[i]->deinit(); + + Mix_HookMusicFinished(nullptr); + Mix_HaltMusic(); + //completely tear down SDL audio. else SDL hogs audio resources and emulators might fail to start... - SDL_CloseAudio(); + Mix_CloseAudio(); SDL_QuitSubSystem(SDL_INIT_AUDIO); - sInstance = NULL; } void AudioManager::registerSound(std::shared_ptr & sound) @@ -135,21 +112,169 @@ void AudioManager::unregisterSound(std::shared_ptr & sound) void AudioManager::play() { getInstance(); - - //unpause audio, the mixer will figure out if samples need to be played... - SDL_PauseAudio(0); } void AudioManager::stop() { //stop playing all Sounds for(unsigned int i = 0; i < sSoundVector.size(); i++) - { if(sSoundVector.at(i)->isPlaying()) - { sSoundVector[i]->stop(); +} + +void AudioManager::getMusicIn(const std::string &path, std::vector& all_matching_files) +{ + if(!Utils::FileSystem::isDirectory(path)) { + return; + } + auto dirContent = Utils::FileSystem::getDirContent(path); + for(auto it = dirContent.cbegin(); it != dirContent.cend(); ++it) + { + if(Utils::FileSystem::isDirectory(*it)) + { + if(*it == "." || *it == "..") + getMusicIn(*it, all_matching_files); + } + else + { + std::string extension = Utils::String::toLower(Utils::FileSystem::getExtension(*it)); + if(extension == ".mp3" || extension == ".ogg") + all_matching_files.push_back(*it); + } + } +} + +void AudioManager::playRandomMusic(bool continueIfPlaying) +{ + if(!Settings::getInstance()->getBool("EnableMusic")) + return; + + std::vector musics; + + // check in RetroPie music directory + if(musics.empty()) + getMusicIn(Utils::FileSystem::getHomePath() + "/RetroPie/roms/music", musics); + + // check in system sound directory + if(musics.empty()) + getMusicIn("/usr/share/RetroPie/music", musics); + + // check in .emulationstation/music directory + if(musics.empty()) + getMusicIn(Utils::FileSystem::getHomePath() + "/.emulationstation/music", musics); + + if(musics.empty()) + return; + +#if defined(WIN32) + srand(time(NULL) % getpid()); +#else + srand(time(NULL) % getpid() + getppid()); +#endif + + int randomIndex = rand() % musics.size(); + + // continue playing ? + if(mCurrentMusic != nullptr && continueIfPlaying) + return; + + playMusic(musics.at(randomIndex)); +} + +void AudioManager::playMusic(std::string path) +{ + if(!mInitialized) + return; + + // free the previous music + stopMusic(false); + + if(!Settings::getInstance()->getBool("EnableMusic")) + return; + + // load a new music + mCurrentMusic = Mix_LoadMUS(path.c_str()); + if(mCurrentMusic == NULL) + { + LOG(LogError) << Mix_GetError() << " for " << path; + return; } - //pause audio - SDL_PauseAudio(1); + + if(Mix_FadeInMusic(mCurrentMusic, 1, 1000) == -1) + { + stopMusic(); + return; + } + + Mix_HookMusicFinished(AudioManager::musicEnd_callback); +} + +void AudioManager::musicEnd_callback() +{ + if(!Settings::getInstance()->getBool("EnableMusic")) + return; + else + AudioManager::getInstance()->playRandomMusic(false); +} + +void AudioManager::stopMusic(bool fadeOut) +{ + if(mCurrentMusic == NULL) + return; + + Mix_HookMusicFinished(nullptr); + + if(fadeOut) + { + while(!Mix_FadeOutMusic(2000) && Mix_PlayingMusic()) + SDL_Delay(100); + } + + Mix_FreeMusic(mCurrentMusic); + mCurrentMusic = NULL; +} + +int AudioManager::getMaxMusicVolume() +{ + int ret = (Settings::getInstance()->getInt("MusicVolume") * MIX_MAX_VOLUME) / 100; + if(ret > MIX_MAX_VOLUME) + return MIX_MAX_VOLUME; + + if(ret < 0) + return 0; + + return ret; +} + +void AudioManager::update(int deltaTime) +{ + if(sInstance == nullptr || !sInstance->mInitialized || !Settings::getInstance()->getBool("EnableMusic")) + return; + + float deltaVol = deltaTime / 8.0f; + +// #define MINVOL 5 + + int maxVol = getMaxMusicVolume(); + int minVol = maxVol / 20; + if(maxVol > 0 && minVol == 0) + minVol = 1; + + /*if (sInstance->mMusicVolume > minVol) + { + sInstance->mMusicVolume -= deltaVol; + if (sInstance->mMusicVolume < minVol) + sInstance->mMusicVolume = minVol; + + Mix_VolumeMusic((int)sInstance->mMusicVolume); + } + else if (sInstance->mMusicVolume < maxVol) + { + sInstance->mMusicVolume += deltaVol; + if (sInstance->mMusicVolume > maxVol) + sInstance->mMusicVolume = maxVol; + + Mix_VolumeMusic((int)sInstance->mMusicVolume); + }*/ } diff --git a/es-core/src/AudioManager.h b/es-core/src/AudioManager.h index e27ce1dc2e..3eadb9243e 100644 --- a/es-core/src/AudioManager.h +++ b/es-core/src/AudioManager.h @@ -5,21 +5,30 @@ #include #include #include +#include "SDL_mixer.h" +#include +#include class Sound; class AudioManager { - static SDL_AudioSpec sAudioFormat; +private: + AudioManager(); + static std::vector> sSoundVector; - static std::shared_ptr sInstance; - - static void mixAudio(void *unused, Uint8 *stream, int len); + static AudioManager* sInstance; - AudioManager(); + Mix_Music* mCurrentMusic; + void getMusicIn(const std::string &path, std::vector& all_matching_files); + void playMusic(std::string path); + static void musicEnd_callback(); + + bool mInitialized; public: - static std::shared_ptr & getInstance(); + static AudioManager* getInstance(); + static bool isInitialized(); void init(); void deinit(); @@ -30,6 +39,10 @@ class AudioManager void play(); void stop(); + // RetroPie Mixer + void playRandomMusic(bool continueIfPlaying = true); + void stopMusic(bool fadeOut = true); + virtual ~AudioManager(); }; diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 2eab663bc4..ebd83f7c0e 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -9,6 +9,7 @@ #include Settings* Settings::sInstance = NULL; +static std::string mEmptyString = ""; // these values are NOT saved to es_settings.xml // since they're set through command-line arguments, and not the in-program settings menu @@ -72,6 +73,7 @@ void Settings::setDefaults() mBoolMap["VSync"] = true; mBoolMap["EnableSounds"] = true; + mBoolMap["EnableMusic"] = true; mBoolMap["ShowHelpPrompts"] = true; mBoolMap["DoublePressRemovesFromFavs"] = false; mBoolMap["ScrapeRatings"] = true; @@ -276,20 +278,55 @@ void Settings::processBackwardCompatibility() //Print a warning message if the setting we're trying to get doesn't already exist in the map, then return the value in the map. -#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName) type Settings::getMethodName(const std::string& name) \ +#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName, defaultValue) type Settings::getMethodName(const std::string& name) \ { \ if(mapName.find(name) == mapName.cend()) \ { \ - LOG(LogError) << "Tried to use unset setting " << name << "!"; \ + /* LOG(LogError) << "Tried to use unset setting " << name << "!"; */ \ + return defaultValue; \ } \ return mapName[name]; \ } \ -void Settings::setMethodName(const std::string& name, type value) \ +bool Settings::setMethodName(const std::string& name, type value) \ { \ - mapName[name] = value; \ + if(mapName.count(name) == 0 || mapName[name] != value) { \ + mapName[name] = value; \ +\ + if(std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), name) == settings_dont_save.cend()) \ + mWasChanged = true; \ +\ + return true; \ + } \ + return false; \ +} + +SETTINGS_GETSET(bool, mBoolMap, getBool, setBool, false); +SETTINGS_GETSET(int, mIntMap, getInt, setInt, 0); +SETTINGS_GETSET(float, mFloatMap, getFloat, setFloat, 0.0f); + + +std::string Settings::getString(const std::string& name) +{ + if(mStringMap.find(name) == mStringMap.cend()) + return mEmptyString; + + return mStringMap[name]; } -SETTINGS_GETSET(bool, mBoolMap, getBool, setBool); -SETTINGS_GETSET(int, mIntMap, getInt, setInt); -SETTINGS_GETSET(float, mFloatMap, getFloat, setFloat); -SETTINGS_GETSET(const std::string&, mStringMap, getString, setString); +bool Settings::setString(const std::string& name, const std::string& value) +{ + if(mStringMap.count(name) == 0 || mStringMap[name] != value) + { + if(value == "" && mStringMap.count(name) == 0) + return false; + + mStringMap[name] = value; + + if(std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), name) == settings_dont_save.cend()) + mWasChanged = true; + + return true; + } + + return false; +} diff --git a/es-core/src/Settings.h b/es-core/src/Settings.h index 51d19a798c..e5cbeaad5f 100644 --- a/es-core/src/Settings.h +++ b/es-core/src/Settings.h @@ -19,12 +19,18 @@ class Settings bool getBool(const std::string& name); int getInt(const std::string& name); float getFloat(const std::string& name); - const std::string& getString(const std::string& name); + std::string getString(const std::string& name); - void setBool(const std::string& name, bool value); - void setInt(const std::string& name, int value); - void setFloat(const std::string& name, float value); - void setString(const std::string& name, const std::string& value); + bool setBool(const std::string& name, bool value); + bool setInt(const std::string& name, int value); + bool setFloat(const std::string& name, float value); + bool setString(const std::string& name, const std::string& value); + + std::map& getStringMap() { return mStringMap; } + + static bool DebugText; + static bool DebugImage; + static bool DebugGrid; private: static Settings* sInstance; @@ -40,6 +46,13 @@ class Settings std::map mIntMap; std::map mFloatMap; std::map mStringMap; + + bool mWasChanged; + + std::map mDefaultBoolMap; + std::map mDefaultIntMap; + std::map mDefaultFloatMap; + std::map mDefaultStringMap; }; #endif // ES_CORE_SETTINGS_H diff --git a/es-core/src/Sound.cpp b/es-core/src/Sound.cpp index e3f46e279b..72be6b29f6 100644 --- a/es-core/src/Sound.cpp +++ b/es-core/src/Sound.cpp @@ -14,8 +14,13 @@ std::shared_ptr Sound::get(const std::string& path) return it->second; std::shared_ptr sound = std::shared_ptr(new Sound(path)); - AudioManager::getInstance()->registerSound(sound); - sMap[path] = sound; + + if(AudioManager::isInitialized()) + { + AudioManager::getInstance()->registerSound(sound); + sMap[path] = sound; + } + return sound; } @@ -33,7 +38,7 @@ std::shared_ptr Sound::getFromTheme(const std::shared_ptr& the return get(elem->get("path")); } -Sound::Sound(const std::string & path) : mSampleData(NULL), mSamplePos(0), mSampleLength(0), playing(false) +Sound::Sound(const std::string & path) : mSampleData(NULL), mPlayingChannel(-1) { loadFile(path); } @@ -51,131 +56,57 @@ void Sound::loadFile(const std::string & path) void Sound::init() { - if(mSampleData != NULL) - deinit(); + deinit(); + + if(!AudioManager::isInitialized()) + return; - if(mPath.empty()) + if(mPath.empty() || !Utils::FileSystem::exists(mPath)) + return; + + if(!Settings::getInstance()->getBool("EnableSounds")) return; //load wav file via SDL - SDL_AudioSpec wave; - Uint8 * data = NULL; - Uint32 dlen = 0; - if (SDL_LoadWAV(mPath.c_str(), &wave, &data, &dlen) == NULL) { + mSampleData = Mix_LoadWAV(mPath.c_str()); + if(mSampleData == nullptr) + { LOG(LogError) << "Error loading sound \"" << mPath << "\"!\n" << " " << SDL_GetError(); return; } - //build conversion buffer - SDL_AudioCVT cvt; - SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq, AUDIO_S16, 2, 44100); - //copy data to conversion buffer - cvt.len = dlen; - cvt.buf = new Uint8[cvt.len * cvt.len_mult]; - memcpy(cvt.buf, data, dlen); - //convert buffer to stereo, 16bit, 44.1kHz - if (SDL_ConvertAudio(&cvt) < 0) { - LOG(LogError) << "Error converting sound \"" << mPath << "\" to 44.1kHz, 16bit, stereo format!\n" << " " << SDL_GetError(); - delete[] cvt.buf; - } - else { - //worked. set up member data - SDL_LockAudio(); - mSampleData = cvt.buf; - mSampleLength = cvt.len_cvt; - mSamplePos = 0; - mSampleFormat.channels = 2; - mSampleFormat.freq = 44100; - mSampleFormat.format = AUDIO_S16; - SDL_UnlockAudio(); - } - //free wav data now - SDL_FreeWAV(data); } void Sound::deinit() { - playing = false; - - if(mSampleData != NULL) - { - SDL_LockAudio(); - delete[] mSampleData; - mSampleData = NULL; - mSampleLength = 0; - mSamplePos = 0; - SDL_UnlockAudio(); - } + if(mSampleData == nullptr) + return; + + stop(); + Mix_FreeChunk(mSampleData); + mSampleData = nullptr; } void Sound::play() { - if(mSampleData == NULL) + if(mSampleData == nullptr) return; - + if(!Settings::getInstance()->getBool("EnableSounds")) return; - AudioManager::getInstance(); - - SDL_LockAudio(); - if (playing) - { - //replay from start. rewind the sample to the beginning - mSamplePos = 0; - - } - else - { - //flag our sample as playing - playing = true; - } - SDL_UnlockAudio(); - //tell the AudioManager to start playing samples - AudioManager::getInstance()->play(); + mPlayingChannel = Mix_PlayChannel(-1, mSampleData, 0); } bool Sound::isPlaying() const { - return playing; + return (mPlayingChannel >= 0); } void Sound::stop() { - //flag our sample as playing and rewind its position - SDL_LockAudio(); - playing = false; - mSamplePos = 0; - SDL_UnlockAudio(); -} - -const Uint8 * Sound::getData() const -{ - return mSampleData; -} - -Uint32 Sound::getPosition() const -{ - return mSamplePos; -} - -void Sound::setPosition(Uint32 newPosition) -{ - mSamplePos = newPosition; - if (mSamplePos >= mSampleLength) { - //got to or beyond the end of the sample. stop playing - playing = false; - mSamplePos = 0; - } -} - -Uint32 Sound::getLength() const -{ - return mSampleLength; -} + if(mPlayingChannel < 0) + return; -Uint32 Sound::getLengthMS() const -{ - //44100 samples per second, 2 channels (stereo) - //I have no idea why the *0.75 is necessary, but otherwise it's inaccurate - return (Uint32)((mSampleLength / 44100.0f / 2.0f * 0.75f) * 1000); + //Mix_HaltChannel(mPlayingChannel); + mPlayingChannel = -1; } diff --git a/es-core/src/Sound.h b/es-core/src/Sound.h index 43e68453cc..4de9961702 100644 --- a/es-core/src/Sound.h +++ b/es-core/src/Sound.h @@ -2,7 +2,7 @@ #ifndef ES_CORE_SOUND_H #define ES_CORE_SOUND_H -#include "SDL_audio.h" +#include "SDL_mixer.h" #include #include #include @@ -12,11 +12,8 @@ class ThemeData; class Sound { std::string mPath; - SDL_AudioSpec mSampleFormat; - Uint8 * mSampleData; - Uint32 mSamplePos; - Uint32 mSampleLength; - bool playing; + Mix_Chunk* mSampleData; + int mPlayingChannel; public: static std::shared_ptr get(const std::string& path); @@ -33,12 +30,6 @@ class Sound bool isPlaying() const; void stop(); - const Uint8 * getData() const; - Uint32 getPosition() const; - void setPosition(Uint32 newPosition); - Uint32 getLength() const; - Uint32 getLengthMS() const; - private: Sound(const std::string & path = ""); static std::map< std::string, std::shared_ptr > sMap; From ff6117f025bc1c2a17fa98ee73622e7e3e3baa74 Mon Sep 17 00:00:00 2001 From: Bluestang Date: Sat, 6 Feb 2021 21:19:19 -0700 Subject: [PATCH 25/31] Improved volume slider - Volume updates as slider moves --- es-app/src/guis/GuiMenu.cpp | 12 ++++++++++-- es-core/src/AudioManager.cpp | 8 +++++--- es-core/src/AudioManager.h | 8 ++++++-- es-core/src/Settings.cpp | 1 + es-core/src/Window.cpp | 3 +++ es-core/src/components/SliderComponent.cpp | 10 ++++++++-- es-core/src/components/SliderComponent.h | 4 ++++ 7 files changed, 37 insertions(+), 9 deletions(-) diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index b40a150138..abedb605ee 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -91,8 +91,16 @@ void GuiMenu::openSoundSettings() // volume auto volume = std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); volume->setValue((float)VolumeControl::getInstance()->getVolume()); - s->addWithLabel("SYSTEM VOLUME", volume); - s->addSaveFunc([volume] { VolumeControl::getInstance()->setVolume((int)Math::round(volume->getValue())); }); + volume->setOnValueChanged([](const float &newVal) { VolumeControl::getInstance()->setVolume((int)Math::round(newVal)); }); + s->addWithLabel("AUDIO VOLUME", volume); + s->addSaveFunc([this, volume] { VolumeControl::getInstance()->setVolume((int)Math::round(volume->getValue())); }); + + /*TODO: This is a separate volume slider for the Music Player + auto musicVolume = std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); + musicVolume->setValue(Settings::getInstance()->getInt("MusicVolume")); + musicVolume->setOnValueChanged([](const float &newVal) { Settings::getInstance()->setInt("MusicVolume", (int)round(newVal)); }); + s->addWithLabel("MUSIC VOLUME", musicVolume); + */ if (UIModeController::getInstance()->isUIModeFull()) { diff --git a/es-core/src/AudioManager.cpp b/es-core/src/AudioManager.cpp index f9ea469617..e0fef1e4d1 100644 --- a/es-core/src/AudioManager.cpp +++ b/es-core/src/AudioManager.cpp @@ -11,7 +11,7 @@ AudioManager* AudioManager::sInstance = NULL; std::vector> AudioManager::sSoundVector; -AudioManager::AudioManager() : mInitialized(false), mCurrentMusic(nullptr) +AudioManager::AudioManager() : mInitialized(false), mCurrentMusic(nullptr), mMusicVolume(MIX_MAX_VOLUME) { init(); } @@ -42,7 +42,7 @@ void AudioManager::init() { if(mInitialized) return; - + mMusicVolume = 0; if(SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) @@ -261,7 +261,9 @@ void AudioManager::update(int deltaTime) if(maxVol > 0 && minVol == 0) minVol = 1; - /*if (sInstance->mMusicVolume > minVol) + /* TODO: This is part of unimplemented feature that would + * lower the music volume if a video snap was playing + * if (sInstance->mMusicVolume > minVol) { sInstance->mMusicVolume -= deltaVol; if (sInstance->mMusicVolume < minVol) diff --git a/es-core/src/AudioManager.h b/es-core/src/AudioManager.h index 3eadb9243e..797a81fcdd 100644 --- a/es-core/src/AudioManager.h +++ b/es-core/src/AudioManager.h @@ -15,7 +15,7 @@ class AudioManager { private: AudioManager(); - + static std::vector> sSoundVector; static AudioManager* sInstance; @@ -23,7 +23,7 @@ class AudioManager void getMusicIn(const std::string &path, std::vector& all_matching_files); void playMusic(std::string path); static void musicEnd_callback(); - + bool mInitialized; public: @@ -44,6 +44,10 @@ class AudioManager void stopMusic(bool fadeOut = true); virtual ~AudioManager(); + + float mMusicVolume; + static void update(int deltaTime); + static int getMaxMusicVolume(); }; #endif // ES_CORE_AUDIO_MANAGER_H diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index ebd83f7c0e..06095ecc06 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -74,6 +74,7 @@ void Settings::setDefaults() mBoolMap["EnableSounds"] = true; mBoolMap["EnableMusic"] = true; + mIntMap["MusicVolume"] = 128; mBoolMap["ShowHelpPrompts"] = true; mBoolMap["DoublePressRemovesFromFavs"] = false; mBoolMap["ScrapeRatings"] = true; diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 19acb32f4e..500b0cd3e0 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -4,6 +4,7 @@ #include "components/ImageComponent.h" #include "resources/Font.h" #include "resources/TextureResource.h" +#include "AudioManager.h" #include "InputManager.h" #include "Log.h" #include "Scripting.h" @@ -236,6 +237,8 @@ void Window::update(int deltaTime) // Update the screensaver if (mScreenSaver) mScreenSaver->update(deltaTime); + + AudioManager::update(deltaTime); } void Window::render() diff --git a/es-core/src/components/SliderComponent.cpp b/es-core/src/components/SliderComponent.cpp index aba8174c45..dc7a7004d4 100644 --- a/es-core/src/components/SliderComponent.cpp +++ b/es-core/src/components/SliderComponent.cpp @@ -28,7 +28,7 @@ bool SliderComponent::input(InputConfig* config, Input input) mMoveRate = input.value ? -mSingleIncrement : 0; mMoveAccumulator = -MOVE_REPEAT_DELAY; - return true; + return input.value; } if(config->isMappedLike("right", input)) { @@ -37,7 +37,7 @@ bool SliderComponent::input(InputConfig* config, Input input) mMoveRate = input.value ? mSingleIncrement : 0; mMoveAccumulator = -MOVE_REPEAT_DELAY; - return true; + return input.value; } return GuiComponent::input(config, input); @@ -81,6 +81,9 @@ void SliderComponent::render(const Transform4x4f& parentTrans) void SliderComponent::setValue(float value) { + if (mValue == value) + return; + mValue = value; if(mValue < mMin) mValue = mMin; @@ -88,6 +91,9 @@ void SliderComponent::setValue(float value) mValue = mMax; onValueChanged(); + + if (mValueChanged) + mValueChanged(mValue); } float SliderComponent::getValue() diff --git a/es-core/src/components/SliderComponent.h b/es-core/src/components/SliderComponent.h index f3ae181fce..cf0f108856 100644 --- a/es-core/src/components/SliderComponent.h +++ b/es-core/src/components/SliderComponent.h @@ -25,6 +25,8 @@ class SliderComponent : public GuiComponent void onSizeChanged() override; virtual std::vector getHelpPrompts() override; + + inline void setOnValueChanged(const std::function& callback) { mValueChanged = callback; } private: void onValueChanged(); @@ -40,6 +42,8 @@ class SliderComponent : public GuiComponent std::string mSuffix; std::shared_ptr mFont; std::shared_ptr mValueCache; + + std::function mValueChanged; }; #endif // ES_CORE_COMPONENTS_SLIDER_COMPONENT_H From adcfcb9ba53e7042a677cd033abc95e4bf969388 Mon Sep 17 00:00:00 2001 From: Bluestang Date: Sat, 6 Mar 2021 21:53:51 -0700 Subject: [PATCH 26/31] Add music volume slider - Separate slider that controls the music volume --- es-app/src/guis/GuiMenu.cpp | 4 ++-- es-core/src/AudioManager.cpp | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index abedb605ee..e06c289d6d 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -95,12 +95,12 @@ void GuiMenu::openSoundSettings() s->addWithLabel("AUDIO VOLUME", volume); s->addSaveFunc([this, volume] { VolumeControl::getInstance()->setVolume((int)Math::round(volume->getValue())); }); - /*TODO: This is a separate volume slider for the Music Player + // music volume auto musicVolume = std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); musicVolume->setValue(Settings::getInstance()->getInt("MusicVolume")); musicVolume->setOnValueChanged([](const float &newVal) { Settings::getInstance()->setInt("MusicVolume", (int)round(newVal)); }); s->addWithLabel("MUSIC VOLUME", musicVolume); - */ + s->addSaveFunc([this, musicVolume] { Settings::getInstance()->setInt("MusicVolume", (int)round(musicVolume->getValue())); }); if (UIModeController::getInstance()->isUIModeFull()) { diff --git a/es-core/src/AudioManager.cpp b/es-core/src/AudioManager.cpp index e0fef1e4d1..dd12734569 100644 --- a/es-core/src/AudioManager.cpp +++ b/es-core/src/AudioManager.cpp @@ -11,7 +11,7 @@ AudioManager* AudioManager::sInstance = NULL; std::vector> AudioManager::sSoundVector; -AudioManager::AudioManager() : mInitialized(false), mCurrentMusic(nullptr), mMusicVolume(MIX_MAX_VOLUME) +AudioManager::AudioManager() : mInitialized(false), mCurrentMusic(nullptr), mMusicVolume(Settings::getInstance()->getInt("MusicVolume")) { init(); } @@ -42,8 +42,6 @@ void AudioManager::init() { if(mInitialized) return; - - mMusicVolume = 0; if(SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) { @@ -252,18 +250,21 @@ void AudioManager::update(int deltaTime) if(sInstance == nullptr || !sInstance->mInitialized || !Settings::getInstance()->getBool("EnableMusic")) return; + Mix_VolumeMusic(Settings::getInstance()->getInt("MusicVolume")); + + /* TODO: This is part of unimplemented feature that would + * lower the music volume if a video snap was playing + float deltaVol = deltaTime / 8.0f; -// #define MINVOL 5 + // #define MINVOL 5 int maxVol = getMaxMusicVolume(); int minVol = maxVol / 20; if(maxVol > 0 && minVol == 0) minVol = 1; - /* TODO: This is part of unimplemented feature that would - * lower the music volume if a video snap was playing - * if (sInstance->mMusicVolume > minVol) + if (sInstance->mMusicVolume > minVol) { sInstance->mMusicVolume -= deltaVol; if (sInstance->mMusicVolume < minVol) @@ -278,5 +279,6 @@ void AudioManager::update(int deltaTime) sInstance->mMusicVolume = maxVol; Mix_VolumeMusic((int)sInstance->mMusicVolume); - }*/ -} + } + */ +} \ No newline at end of file From 70a120a53a4e028dad8cb9eba85ff29d9c989369 Mon Sep 17 00:00:00 2001 From: Bluestang2006 Date: Sat, 26 Mar 2022 12:37:56 -0600 Subject: [PATCH 27/31] Credits - Added original authors of the BGM player using SDL2-mixer (Backported by Bluestang2006) --- CREDITS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index babde810f5..ba8fc97b5d 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,6 +1,11 @@ Programming Alec "Aloshi" Lofquist - http://www.aloshi.com +BGM Player using SDL2-mixer + Nicolas Adenis-Lamarre - https://batocera.org + Fabrice Caruso - https://batocera.org + Andrew Falcon - bluestang2006@gmail.com (backported code) + UI Art & Design Nils Bonenberger From d67431f5136d490da1c85a8b09a716d73f9b0639 Mon Sep 17 00:00:00 2001 From: Bluestang2006 Date: Sat, 26 Mar 2022 09:18:27 -0600 Subject: [PATCH 28/31] Revert mixerName, mixerCard original code is fine to use as-is --- es-app/src/VolumeControl.cpp | 70 ++++++++++++++++++------------------ es-app/src/VolumeControl.h | 4 +-- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/es-app/src/VolumeControl.cpp b/es-app/src/VolumeControl.cpp index 8ee6d74865..edf5cba6ad 100644 --- a/es-app/src/VolumeControl.cpp +++ b/es-app/src/VolumeControl.cpp @@ -8,12 +8,12 @@ #endif #if defined(__linux__) -#if defined(_RPI_) || defined(_VERO4K_) - std::string VolumeControl::mixerName = "PCM"; -#else - std::string VolumeControl::mixerName = "Master"; -#endif - std::string VolumeControl::mixerCard = "default"; + #if defined(_RPI_) || defined(_VERO4K_) + const char * VolumeControl::mixerName = "PCM"; + #else + const char * VolumeControl::mixerName = "Master"; + #endif + const char * VolumeControl::mixerCard = "default"; #endif std::weak_ptr VolumeControl::sInstance; @@ -87,24 +87,19 @@ void VolumeControl::init() if (mixerHandle == nullptr) { // Allow users to override the AudioCard and MixerName in es_settings.cfg - auto audioCard = Settings::getInstance()->getString("AudioCard"); - if (!audioCard.empty()) - mixerCard = audioCard; - - auto audioDevice = Settings::getInstance()->getString("AudioDevice"); - if (!audioDevice.empty()) - mixerName = audioDevice; + mixerCard = Settings::getInstance()->getString("AudioCard").c_str(); + mixerName = Settings::getInstance()->getString("AudioDevice").c_str(); snd_mixer_selem_id_alloca(&mixerSelemId); //sets simple-mixer index and name snd_mixer_selem_id_set_index(mixerSelemId, mixerIndex); - snd_mixer_selem_id_set_name(mixerSelemId, mixerName.c_str()); + snd_mixer_selem_id_set_name(mixerSelemId, mixerName); //open mixer if (snd_mixer_open(&mixerHandle, 0) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Opened ALSA mixer"; //ok. attach to defualt card - if (snd_mixer_attach(mixerHandle, mixerCard.c_str()) >= 0) + if (snd_mixer_attach(mixerHandle, mixerCard) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Attached to default card"; //ok. register simple element class @@ -138,19 +133,19 @@ void VolumeControl::init() LOG(LogInfo) << "mixername : " << mixerName; - snd_mixer_selem_id_set_name(mixerSelemId, mixerName.c_str()); + snd_mixer_selem_id_set_name(mixerSelemId, mixerName); mixerElem = snd_mixer_find_selem(mixerHandle, mixerSelemId); if (mixerElem != nullptr) { - //wohoo. good to go... LOG(LogDebug) << "VolumeControl::init() - Mixer initialized"; break; } else + { LOG(LogDebug) << "VolumeControl::init() - Mixer not initialized"; + } } } - if (mixerElem == nullptr) { LOG(LogError) << "VolumeControl::init() - Failed to find mixer elements!"; @@ -267,7 +262,7 @@ void VolumeControl::deinit() #error TODO: Not implemented for MacOS yet!!! #elif defined(__linux__) if (mixerHandle != nullptr) { - snd_mixer_detach(mixerHandle, mixerCard.c_str()); + snd_mixer_detach(mixerHandle, mixerCard); snd_mixer_free(mixerHandle); snd_mixer_close(mixerHandle); mixerHandle = nullptr; @@ -296,19 +291,9 @@ int VolumeControl::getVolume() const if (mixerElem != nullptr) { if (mixerHandle != nullptr) - snd_mixer_handle_events(mixerHandle); - - /* Disabled see commit 38ce42faef8aae3f9c180560bfdedd9d1b954d28 - * https://github.com/batocera-linux/batocera-emulationstation/ - int mute_state; - if (snd_mixer_selem_has_playback_switch(mixerElem)) { - snd_mixer_selem_get_playback_switch(mixerElem, SND_MIXER_SCHN_UNKNOWN, &mute_state); - if (!mute_state) // system Muted - return 0; + snd_mixer_handle_events(mixerHandle); } - */ - //get volume range long minVolume; long maxVolume; @@ -324,6 +309,7 @@ int VolumeControl::getVolume() const { volume = (rawVolume * 100.0) / (maxVolume - minVolume) + 0.5; } + //else volume = 0; } else { @@ -348,32 +334,46 @@ int VolumeControl::getVolume() const mixerControlDetails.paDetails = &value; mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); if (mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) + { volume = (int)Math::round((value.dwValue * 100) / 65535.0f); + } + else + { + LOG(LogError) << "VolumeControl::getVolume() - Failed to get mixer volume!"; + } } else if (endpointVolume != nullptr) { //Windows Vista or above. use EndpointVolume API float floatVolume = 0.0f; //0-1 - BOOL mute = FALSE; if (endpointVolume->GetMute(&mute) == S_OK) { if (mute) + { return 0; + } } - if (endpointVolume->GetMasterVolumeLevelScalar(&floatVolume) == S_OK) + { volume = (int)Math::round(floatVolume * 100.0f); + LOG(LogInfo) << " getting volume as " << volume << " ( from float " << floatVolume << ")"; + } + else + { + LOG(LogError) << "VolumeControl::getVolume() - Failed to get master volume!"; + } } #endif - //clamp to 0-100 range if (volume < 0) + { volume = 0; - + } if (volume > 100) + { volume = 100; - + } return volume; } diff --git a/es-app/src/VolumeControl.h b/es-app/src/VolumeControl.h index adae297de2..ea2ef8c913 100644 --- a/es-app/src/VolumeControl.h +++ b/es-app/src/VolumeControl.h @@ -24,8 +24,8 @@ class VolumeControl #if defined (__APPLE__) #error TODO: Not implemented for MacOS yet!!! #elif defined(__linux__) - static std::string mixerName; - static std::string mixerCard; + static const char * mixerName; + static const char * mixerCard; int mixerIndex; snd_mixer_t* mixerHandle; snd_mixer_elem_t* mixerElem; From e5b5abd7a6fbc74a5649ff25457ac692aae10971 Mon Sep 17 00:00:00 2001 From: Bluestang2006 Date: Sat, 26 Mar 2022 09:32:13 -0600 Subject: [PATCH 29/31] Revert Settings.cpp, Settings.h original code is fine to use as-is --- es-core/src/Settings.cpp | 50 ++++++---------------------------------- es-core/src/Settings.h | 10 ++++---- 2 files changed, 12 insertions(+), 48 deletions(-) diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 06095ecc06..949461a73f 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -9,7 +9,6 @@ #include Settings* Settings::sInstance = NULL; -static std::string mEmptyString = ""; // these values are NOT saved to es_settings.xml // since they're set through command-line arguments, and not the in-program settings menu @@ -279,55 +278,20 @@ void Settings::processBackwardCompatibility() //Print a warning message if the setting we're trying to get doesn't already exist in the map, then return the value in the map. -#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName, defaultValue) type Settings::getMethodName(const std::string& name) \ +#define SETTINGS_GETSET(type, mapName, getMethodName, setMethodName) type Settings::getMethodName(const std::string& name) \ { \ if(mapName.find(name) == mapName.cend()) \ { \ - /* LOG(LogError) << "Tried to use unset setting " << name << "!"; */ \ - return defaultValue; \ + LOG(LogError) << "Tried to use unset setting " << name << "!"; \ } \ return mapName[name]; \ } \ -bool Settings::setMethodName(const std::string& name, type value) \ +void Settings::setMethodName(const std::string& name, type value) \ { \ - if(mapName.count(name) == 0 || mapName[name] != value) { \ mapName[name] = value; \ -\ - if(std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), name) == settings_dont_save.cend()) \ - mWasChanged = true; \ -\ - return true; \ - } \ - return false; \ -} - -SETTINGS_GETSET(bool, mBoolMap, getBool, setBool, false); -SETTINGS_GETSET(int, mIntMap, getInt, setInt, 0); -SETTINGS_GETSET(float, mFloatMap, getFloat, setFloat, 0.0f); - - -std::string Settings::getString(const std::string& name) -{ - if(mStringMap.find(name) == mStringMap.cend()) - return mEmptyString; - - return mStringMap[name]; } -bool Settings::setString(const std::string& name, const std::string& value) -{ - if(mStringMap.count(name) == 0 || mStringMap[name] != value) - { - if(value == "" && mStringMap.count(name) == 0) - return false; - - mStringMap[name] = value; - - if(std::find(settings_dont_save.cbegin(), settings_dont_save.cend(), name) == settings_dont_save.cend()) - mWasChanged = true; - - return true; - } - - return false; -} +SETTINGS_GETSET(bool, mBoolMap, getBool, setBool); +SETTINGS_GETSET(int, mIntMap, getInt, setInt); +SETTINGS_GETSET(float, mFloatMap, getFloat, setFloat); +SETTINGS_GETSET(const std::string&, mStringMap, getString, setString); diff --git a/es-core/src/Settings.h b/es-core/src/Settings.h index e5cbeaad5f..69b18f3e17 100644 --- a/es-core/src/Settings.h +++ b/es-core/src/Settings.h @@ -19,12 +19,12 @@ class Settings bool getBool(const std::string& name); int getInt(const std::string& name); float getFloat(const std::string& name); - std::string getString(const std::string& name); + const std::string& getString(const std::string& name); - bool setBool(const std::string& name, bool value); - bool setInt(const std::string& name, int value); - bool setFloat(const std::string& name, float value); - bool setString(const std::string& name, const std::string& value); + void setBool(const std::string& name, bool value); + void setInt(const std::string& name, int value); + void setFloat(const std::string& name, float value); + void setString(const std::string& name, const std::string& value); std::map& getStringMap() { return mStringMap; } From 6f6e9e96d68d746017557627f008816e08678fff Mon Sep 17 00:00:00 2001 From: Bluestang2006 Date: Sat, 26 Mar 2022 12:06:35 -0600 Subject: [PATCH 30/31] Fix GuiMenu.cpp Fix build error --- es-app/src/guis/GuiMenu.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index e06c289d6d..6bf6ba0673 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -171,15 +171,12 @@ void GuiMenu::openSoundSettings() auto music_enabled = std::make_shared(mWindow); music_enabled->setState(Settings::getInstance()->getBool("EnableMusic")); s->addWithLabel("BACKGROUND MUSIC", music_enabled); - s->addSaveFunc([music_enabled] - { - if (Settings::getInstance()->setBool("EnableMusic", music_enabled->getState())) - { - if (music_enabled->getState()) - AudioManager::getInstance()->playRandomMusic(); - else - AudioManager::getInstance()->stopMusic(); - } + s->addSaveFunc([music_enabled] { + Settings::getInstance()->setBool("EnableMusic", music_enabled->getState()); + if (music_enabled->getState()) + AudioManager::getInstance()->playRandomMusic(); + else + AudioManager::getInstance()->stopMusic(); }); auto video_audio = std::make_shared(mWindow); From f19383e2b1c880564a99a74f9f21d9d98aae4f4c Mon Sep 17 00:00:00 2001 From: Bluestang2006 Date: Sat, 26 Mar 2022 12:31:37 -0600 Subject: [PATCH 31/31] Set default folders where music files can be stored Let's use the correct default folders that RetroPie uses. --- es-core/src/AudioManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/es-core/src/AudioManager.cpp b/es-core/src/AudioManager.cpp index dd12734569..90b8da17ef 100644 --- a/es-core/src/AudioManager.cpp +++ b/es-core/src/AudioManager.cpp @@ -156,7 +156,7 @@ void AudioManager::playRandomMusic(bool continueIfPlaying) // check in system sound directory if(musics.empty()) - getMusicIn("/usr/share/RetroPie/music", musics); + getMusicIn("/opt/retropie/music", musics); // check in .emulationstation/music directory if(musics.empty()) @@ -281,4 +281,4 @@ void AudioManager::update(int deltaTime) Mix_VolumeMusic((int)sInstance->mMusicVolume); } */ -} \ No newline at end of file +}