PlayerLink/src/backends/windows.cpp

127 lines
4.5 KiB
C++
Raw Normal View History

2024-11-01 14:10:00 +01:00
#ifdef _WIN32
2024-11-04 18:29:25 +01:00
#define WIN32_LEAN_AND_MEAN
#include <objbase.h>
#include <shlobj.h>
#include <windows.h>
2024-11-01 14:10:00 +01:00
#include <winrt/windows.foundation.h>
2024-11-06 11:36:32 +01:00
#include <winrt/windows.foundation.metadata.h>
2024-11-01 14:10:00 +01:00
#include <winrt/windows.media.control.h>
#include <winrt/windows.storage.streams.h>
#include <chrono>
2024-11-04 15:32:46 +01:00
#include <codecvt>
2024-11-04 18:29:25 +01:00
#include <filesystem>
2024-11-01 14:10:00 +01:00
#include "../backend.hpp"
2024-11-01 16:49:48 +01:00
#include "../utils.hpp"
2024-11-01 14:10:00 +01:00
using namespace winrt;
using namespace Windows::Media::Control;
using namespace Windows::Storage::Streams;
2024-11-04 15:32:46 +01:00
#define EM_DASH "\xE2\x80\x94"
2024-11-04 18:29:25 +01:00
// codecvt is deprecated, but there is no good portable way to do this, I could technically use the winapi as this is
// the windows backend tho
2024-11-01 14:10:00 +01:00
std::string toStdString(winrt::hstring in) {
2024-11-04 15:32:46 +01:00
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(in.c_str());
2024-11-01 14:10:00 +01:00
}
2024-11-04 18:29:25 +01:00
bool CreateShortcut(std::string source, std::string target) {
CoInitialize(nullptr);
WCHAR src[MAX_PATH];
IShellLinkW* pShellLink = nullptr;
HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
reinterpret_cast<void**>(&pShellLink));
if (SUCCEEDED(hr) && pShellLink) {
MultiByteToWideChar(CP_ACP, 0, source.c_str(), -1, src, MAX_PATH);
pShellLink->SetPath(src);
IPersistFile* pPersistFile = nullptr;
hr = pShellLink->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&pPersistFile));
if (SUCCEEDED(hr) && pPersistFile) {
WCHAR dst[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, target.c_str(), -1, dst, MAX_PATH);
hr = pPersistFile->Save(dst, TRUE);
pPersistFile->Release();
}
pShellLink->Release();
}
CoUninitialize();
return SUCCEEDED(hr);
}
bool backend::toggleAutostart(bool enabled) {
std::filesystem::path shortcutPath = std::getenv("APPDATA");
shortcutPath = shortcutPath / "Microsoft" / "Windows" / "Start Menu" / "Programs" / "Startup" / "PlayerLink.lnk";
if (!enabled && std::filesystem::exists(shortcutPath)) {
std::filesystem::remove(shortcutPath);
return true;
}
char binaryPath[MAX_PATH]{};
GetModuleFileNameA(NULL, binaryPath, MAX_PATH);
bool result = CreateShortcut(binaryPath, shortcutPath.string());
return result;
}
2024-11-01 14:10:00 +01:00
std::shared_ptr<MediaInfo> backend::getMediaInformation() {
auto sessionManager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get();
auto currentSession = sessionManager.GetCurrentSession();
if (!currentSession)
return nullptr;
auto playbackInfo = currentSession.GetPlaybackInfo();
auto mediaProperties = currentSession.TryGetMediaPropertiesAsync().get();
auto timelineInformation = currentSession.GetTimelineProperties();
if (!mediaProperties)
return nullptr;
auto endTime = std::chrono::duration_cast<std::chrono::milliseconds>(timelineInformation.EndTime()).count();
auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(timelineInformation.Position()).count();
auto thumbnail = mediaProperties.Thumbnail();
std::string thumbnailData = "";
if (thumbnail) {
auto stream = thumbnail.OpenReadAsync().get();
size_t size = static_cast<size_t>(stream.Size());
DataReader reader(stream);
reader.LoadAsync(static_cast<uint32_t>(size)).get();
std::vector<uint8_t> buffer(size);
reader.ReadBytes(buffer);
2024-11-04 23:11:50 +01:00
reader.Close();
2024-11-06 11:36:32 +01:00
2024-11-01 14:10:00 +01:00
thumbnailData = std::string(buffer.begin(), buffer.end());
2024-11-01 16:49:48 +01:00
stream.Close();
2024-11-01 14:10:00 +01:00
}
std::string artist = toStdString(mediaProperties.Artist());
2024-11-01 16:49:48 +01:00
std::string albumName = toStdString(mediaProperties.AlbumTitle());
2024-11-01 14:10:00 +01:00
if (artist == "")
artist = toStdString(mediaProperties.AlbumArtist()); // Needed for some apps
2024-11-04 15:32:46 +01:00
if (artist.find(EM_DASH) != std::string::npos) {
albumName = artist.substr(artist.find(EM_DASH) + 3);
artist = artist.substr(0, artist.find(EM_DASH));
2024-11-01 16:49:48 +01:00
utils::trim(artist);
utils::trim(albumName);
}
2024-11-01 14:10:00 +01:00
return std::make_shared<MediaInfo>(
playbackInfo.PlaybackStatus() == GlobalSystemMediaTransportControlsSessionPlaybackStatus::Paused,
2024-11-01 16:49:48 +01:00
toStdString(mediaProperties.Title()), artist, albumName, toStdString(currentSession.SourceAppUserModelId()),
thumbnailData, endTime, elapsedTime);
2024-11-01 14:10:00 +01:00
}
2024-11-06 11:36:32 +01:00
bool backend::init() {
return winrt::Windows::Foundation::Metadata::ApiInformation::IsTypePresent(
L"Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager");
}
2024-11-04 15:32:46 +01:00
#undef EM_DASH
2024-11-01 14:10:00 +01:00
#endif