PlayerLink/src/main.cpp

157 lines
5.4 KiB
C++
Raw Normal View History

2024-11-01 14:10:00 +01:00
#include <discord-rpc/discord_rpc.h>
2024-11-02 17:17:12 +01:00
#include <wx/image.h>
#include <wx/mstream.h>
#include <wx/taskbar.h>
#include <wx/wx.h>
2024-11-01 14:10:00 +01:00
#include <chrono>
#include <fstream>
#include <iostream>
#include <thread>
#include "backend.hpp"
2024-11-02 17:17:12 +01:00
#include "rsrc.hpp"
2024-11-01 14:10:00 +01:00
#include "utils.hpp"
2024-11-01 14:10:00 +01:00
std::string lastPlayingSong = "";
std::string lastMediaSource = "";
void handleRPCTasks() {
while (true) {
DiscordEventHandlers discordHandler{};
Discord_Initialize(utils::getClientID(lastMediaSource).c_str(), &discordHandler);
if (Discord_IsConnected())
break;
}
while (true) {
Discord_RunCallbacks();
if (!Discord_IsConnected())
break;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
handleRPCTasks(); // this could theoretically cause a stack overflow if discord is restarted often enough
}
void handleMediaTasks() {
2024-11-01 14:10:00 +01:00
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
auto mediaInformation = backend::getMediaInformation();
if (!mediaInformation) {
Discord_ClearPresence(); // Nothing is playing rn, clear presence
continue;
}
if (mediaInformation->paused) {
lastPlayingSong = "";
2024-11-01 14:10:00 +01:00
Discord_ClearPresence(); // TODO: allow user to keep presence when paused(because for
// some reason some people want this)
continue;
}
2024-11-01 16:49:48 +01:00
std::string currentlyPlayingSong = mediaInformation->songTitle + mediaInformation->songArtist +
mediaInformation->songAlbum + std::to_string(mediaInformation->songDuration);
2024-11-01 14:10:00 +01:00
if (currentlyPlayingSong == lastPlayingSong)
continue;
lastPlayingSong = currentlyPlayingSong;
std::string currentMediaSource = mediaInformation->playbackSource;
2024-11-01 16:49:48 +01:00
if (currentMediaSource != lastMediaSource) {
lastMediaSource = currentMediaSource;
Discord_Shutdown();
} // reinitialize with new client id
2024-11-01 15:04:43 +01:00
std::string serviceName = utils::getAppName(lastMediaSource);
2024-11-01 16:49:48 +01:00
std::string activityState = "by " + mediaInformation->songArtist;
2024-11-01 15:04:43 +01:00
DiscordRichPresence activity{};
2024-11-01 14:10:00 +01:00
activity.type = ActivityType::LISTENING;
2024-11-01 15:04:43 +01:00
activity.details = mediaInformation->songTitle.c_str();
2024-11-01 16:49:48 +01:00
activity.state = activityState.c_str();
2024-11-01 15:04:43 +01:00
activity.smallImageText = serviceName.c_str();
std::string artworkURL = utils::getArtworkURL(mediaInformation->songTitle + " " + mediaInformation->songArtist +
" " + mediaInformation->songAlbum);
2024-11-01 14:10:00 +01:00
2024-11-01 16:49:48 +01:00
activity.smallImageKey = "appicon";
2024-11-01 15:04:43 +01:00
if (artworkURL == "") {
activity.smallImageKey = "";
2024-11-01 16:49:48 +01:00
activity.largeImageKey = "appicon";
2024-11-01 15:04:43 +01:00
} else {
activity.largeImageKey = artworkURL.c_str();
}
2024-11-01 16:49:48 +01:00
activity.largeImageText = mediaInformation->songAlbum.c_str();
2024-11-01 14:10:00 +01:00
2024-11-01 15:04:43 +01:00
if (mediaInformation->songDuration != 0) {
int64_t remainingTime = mediaInformation->songDuration - mediaInformation->songElapsedTime;
2024-11-01 16:49:48 +01:00
activity.startTimestamp = time(nullptr) - (mediaInformation->songElapsedTime / 1000);
activity.endTimestamp = time(nullptr) + (remainingTime / 1000);
2024-11-01 15:04:43 +01:00
}
std::string endpointURL = utils::getSearchEndpoint(lastMediaSource);
2024-11-01 14:10:00 +01:00
2024-11-01 16:49:48 +01:00
std::string searchQuery = mediaInformation->songTitle + " " + mediaInformation->songArtist;
std::string buttonName = "Search on " + serviceName;
std::string buttonText = endpointURL + utils::urlEncode(searchQuery);
2024-11-01 15:04:43 +01:00
if (endpointURL != "") {
2024-11-01 16:49:48 +01:00
activity.button1name = buttonName.c_str();
activity.button1link = buttonText.c_str();
2024-11-01 15:04:43 +01:00
}
2024-11-01 14:10:00 +01:00
2024-11-01 15:04:43 +01:00
Discord_UpdatePresence(&activity);
2024-11-01 14:10:00 +01:00
}
}
2024-11-02 17:17:12 +01:00
class MyTaskBarIcon : public wxTaskBarIcon {
public:
MyTaskBarIcon(wxFrame* mainFrame) : m_mainFrame(mainFrame) {}
void OnMenuOpen(wxCommandEvent& evt) { m_mainFrame->Show(true); }
void OnMenuExit(wxCommandEvent& evt) { m_mainFrame->Close(true); }
protected:
virtual wxMenu* CreatePopupMenu() override {
wxMenu* menu = new wxMenu;
menu->Append(10001, "Open");
menu->AppendSeparator();
menu->Append(10002, "Quit");
Bind(wxEVT_MENU, &MyTaskBarIcon::OnMenuOpen, this, 10001);
Bind(wxEVT_MENU, &MyTaskBarIcon::OnMenuExit, this, 10002);
return menu;
}
private:
wxFrame* m_mainFrame;
};
class MyApp : public wxApp {
public:
virtual bool OnInit() override {
2024-11-02 17:17:12 +01:00
wxInitAllImageHandlers();
wxFrame* frame = new wxFrame(nullptr, wxID_ANY, "Hello wxWidgets", wxDefaultPosition, wxSize(400, 300));
2024-11-02 17:17:12 +01:00
trayIcon = new MyTaskBarIcon(frame);
frame->Bind(wxEVT_CLOSE_WINDOW, [=](wxCloseEvent& event) {
trayIcon->RemoveIcon();
trayIcon->Destroy();
event.Skip();
});
wxIcon icon = utils::loadIconFromMemory(icon_png, icon_png_size);
trayIcon->SetIcon(icon, "My App");
wxStaticText* text = new wxStaticText(frame, wxID_ANY, "Hello World", wxPoint(150, 130));
frame->Show(true);
return true;
}
2024-11-02 17:17:12 +01:00
private:
MyTaskBarIcon* trayIcon;
};
wxIMPLEMENT_APP_NO_MAIN(MyApp);
int main(int argc, char** argv) {
std::thread rpcThread(handleRPCTasks);
rpcThread.detach();
std::thread mediaThread(handleMediaTasks);
mediaThread.detach();
return wxEntry(argc, argv);
2024-11-01 14:10:00 +01:00
}