diff --git a/known.json b/known.json index 1a5c826..2d655c3 100644 --- a/known.json +++ b/known.json @@ -6,7 +6,23 @@ "AppleMusic.exe" ], "search_endpoint": "https://music.apple.com/search?term=", - "client_id": "1301881165984301106" + "client_id": "1245257240890310686" + }, + { + "name": "Spotify", + "process_names": [ + "Spotify.exe" + ], + "search_endpoint": "https://open.spotify.com/search/", + "client_id": "1245257414715113573" + }, + { + "name": "Tidal", + "process_names": [ + "TIDAL.exe" + ], + "search_endpoint": "https://listen.tidal.com/search?q=", + "client_id": "1245257493966225488" } ] } \ No newline at end of file diff --git a/rpc.exe b/rpc.exe index 6af8364..d155135 100644 Binary files a/rpc.exe and b/rpc.exe differ diff --git a/src/backends/windows.cpp b/src/backends/windows.cpp index 9577fab..248f070 100644 --- a/src/backends/windows.cpp +++ b/src/backends/windows.cpp @@ -6,6 +6,7 @@ #include #include "../backend.hpp" +#include "../utils.hpp" using namespace winrt; using namespace Windows::Media::Control; @@ -45,17 +46,25 @@ std::shared_ptr backend::getMediaInformation() { std::vector buffer(size); reader.ReadBytes(buffer); thumbnailData = std::string(buffer.begin(), buffer.end()); - stream.Close(); + stream.Close(); } std::string artist = toStdString(mediaProperties.Artist()); + std::string albumName = toStdString(mediaProperties.AlbumTitle()); if (artist == "") artist = toStdString(mediaProperties.AlbumArtist()); // Needed for some apps + if (artist.find("\x14") != std::string::npos) { + albumName = artist.substr(artist.find("\x14") + 1); + artist = artist.substr(0, artist.find("\x14")); + utils::trim(artist); + utils::trim(albumName); + } + return std::make_shared( playbackInfo.PlaybackStatus() == GlobalSystemMediaTransportControlsSessionPlaybackStatus::Paused, - toStdString(mediaProperties.Title()), artist, toStdString(mediaProperties.AlbumTitle()), - toStdString(currentSession.SourceAppUserModelId()), thumbnailData, endTime, elapsedTime); + toStdString(mediaProperties.Title()), artist, albumName, toStdString(currentSession.SourceAppUserModelId()), + thumbnailData, endTime, elapsedTime); } #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a5bdb34..19e64cf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,8 +44,8 @@ int main() { continue; } - std::string currentlyPlayingSong = - mediaInformation->songTitle + mediaInformation->songArtist + mediaInformation->songAlbum; + std::string currentlyPlayingSong = mediaInformation->songTitle + mediaInformation->songArtist + + mediaInformation->songAlbum + std::to_string(mediaInformation->songDuration); if (currentlyPlayingSong == lastPlayingSong) continue; @@ -53,42 +53,48 @@ int main() { lastPlayingSong = currentlyPlayingSong; std::string currentMediaSource = mediaInformation->playbackSource; - std::cout << currentMediaSource << std::endl; - if (currentMediaSource != lastMediaSource) - Discord_Shutdown(); // reinitialize with new client id + + if (currentMediaSource != lastMediaSource) { + lastMediaSource = currentMediaSource; + Discord_Shutdown(); + } // reinitialize with new client id std::string serviceName = utils::getAppName(lastMediaSource); + + std::string activityState = "by " + mediaInformation->songArtist; DiscordRichPresence activity{}; activity.type = ActivityType::LISTENING; activity.details = mediaInformation->songTitle.c_str(); - activity.state = std::string("by " + mediaInformation->songArtist).c_str(); + activity.state = activityState.c_str(); activity.smallImageText = serviceName.c_str(); std::string artworkURL = utils::getArtworkURL(mediaInformation->songTitle + " " + mediaInformation->songArtist + " " + mediaInformation->songAlbum); - activity.smallImageKey = "icon"; + activity.smallImageKey = "appicon"; if (artworkURL == "") { activity.smallImageKey = ""; - activity.largeImageText = "icon"; + activity.largeImageKey = "appicon"; } else { - activity.largeImageText = mediaInformation->songAlbum.c_str(); activity.largeImageKey = artworkURL.c_str(); } + activity.largeImageText = mediaInformation->songAlbum.c_str(); if (mediaInformation->songDuration != 0) { int64_t remainingTime = mediaInformation->songDuration - mediaInformation->songElapsedTime; - activity.startTimestamp = time(nullptr) - mediaInformation->songElapsedTime; - activity.endTimestamp = time(nullptr) + remainingTime; + activity.startTimestamp = time(nullptr) - (mediaInformation->songElapsedTime / 1000); + activity.endTimestamp = time(nullptr) + (remainingTime / 1000); } std::string endpointURL = utils::getSearchEndpoint(lastMediaSource); + std::string searchQuery = mediaInformation->songTitle + " " + mediaInformation->songArtist; + std::string buttonName = "Search on " + serviceName; + std::string buttonText = endpointURL + utils::urlEncode(searchQuery); + if (endpointURL != "") { - activity.button1name = std::string("Search on " + serviceName).c_str(); - std::string searchQuery = mediaInformation->songTitle + " " + mediaInformation->songArtist; - activity.button1link = std::string(endpointURL + utils::urlEncode(searchQuery)).c_str(); + activity.button1name = buttonName.c_str(); + activity.button1link = buttonText.c_str(); } - lastMediaSource = currentMediaSource; Discord_UpdatePresence(&activity); } } \ No newline at end of file diff --git a/src/utils.hpp b/src/utils.hpp index 472fd60..8e07a6f 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -13,6 +13,20 @@ #define CONFIG_FILENAME "known.json" namespace utils { + inline std::string ltrim(std::string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); + return s; + } + + inline std::string rtrim(std::string& s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); + return s; + } + inline std::string trim(std::string& s) { + ltrim(s); + rtrim(s); + return s; + } inline std::string urlEncode(std::string str) { std::string new_str = ""; char c; @@ -39,10 +53,12 @@ namespace utils { } return new_str; } + inline size_t curlWriteCallback(char* contents, size_t size, size_t nmemb, void* userp) { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb; } + inline std::string getRequest(std::string url) { CURL* curl; CURLcode res; @@ -52,6 +68,7 @@ namespace utils { if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf); res = curl_easy_perform(curl); curl_easy_cleanup(curl); @@ -59,6 +76,7 @@ namespace utils { curl_global_cleanup(); return buf; } + inline std::string getArtworkURL(std::string query) { std::string response = getRequest("https://itunes.apple.com/search?media=music&entity=song&term=" + urlEncode(query)); @@ -69,6 +87,7 @@ namespace utils { } return ""; } + inline nlohmann::json getApp(std::string processName) { std::ifstream i("known.json"); std::stringstream s; @@ -94,21 +113,21 @@ namespace utils { if (!std::filesystem::exists(CONFIG_FILENAME)) return DEFAULT_CLIENT_ID; auto app = getApp(processName); - return app["client_id"] == "" ? DEFAULT_CLIENT_ID : app["client_id"]; + return app.contains("client_id") ? app["client_id"].get() : DEFAULT_CLIENT_ID; } inline std::string getAppName(std::string processName) { if (!std::filesystem::exists(CONFIG_FILENAME)) return DEFAULT_APP_NAME; auto app = getApp(processName); - return app["name"] == "" ? DEFAULT_APP_NAME : app["name"]; + return app.contains("name") ? app["name"].get() : DEFAULT_APP_NAME; } inline std::string getSearchEndpoint(std::string processName) { if (!std::filesystem::exists(CONFIG_FILENAME)) return ""; auto app = getApp(processName); - return app["search_endpoint"] == "" ? "" : app["search_endpoint"]; + return app.contains("search_endpoint") ? app["search_endpoint"].get() : ""; } } // namespace utils diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index 81b4bdc..2b0a195 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory("discord-rpc") -SET(ENABLE_PROGRAMS OFF) -SET(ENABLE_TESTING OFF) +SET(ENABLE_PROGRAMS OFF FORCE) +SET(ENABLE_TESTING OFF FORCE) add_subdirectory("mbedtls") SET(CURL_USE_MBEDTLS ON) SET(CURL_USE_LIBPSL OFF)