Skip to content

Commit

Permalink
Set Game metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
NikosSiak committed Nov 8, 2021
1 parent 301eae7 commit 05f0c1b
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 41 deletions.
13 changes: 13 additions & 0 deletions xbmc/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2380,6 +2380,19 @@ void CApplication::OnApplicationMessage(ThreadMessage* pMsg)
}
break;

case TMSG_SET_PLAYER_ITEM:
{
CFileItem* item = static_cast<CFileItem*>(pMsg->lpVoid);
if (item == nullptr)
return;

*m_itemCurrentFile = *item;
CServiceBroker::GetGUI()->GetInfoManager().SetCurrentItem(*m_itemCurrentFile);

delete item;
}
break;

default:
CLog::Log(LOGERROR, "%s: Unhandled threadmessage sent, %u", __FUNCTION__, msg);
break;
Expand Down
9 changes: 9 additions & 0 deletions xbmc/GUIInfoManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "Util.h"
#include "cores/DataCacheCore.h"
#include "filesystem/File.h"
#include "games/tags/GameInfoTag.h"
#include "guilib/guiinfo/GUIInfo.h"
#include "guilib/guiinfo/GUIInfoHelper.h"
#include "guilib/guiinfo/GUIInfoLabels.h"
Expand Down Expand Up @@ -10964,6 +10965,14 @@ const CVideoInfoTag* CGUIInfoManager::GetCurrentMovieTag() const
return nullptr;
}

const KODI::GAME::CGameInfoTag* CGUIInfoManager::GetCurrentGameTag() const
{
if (m_currentFile->HasGameInfoTag())
return m_currentFile->GetGameInfoTag();

return nullptr;
}

int CGUIInfoManager::RegisterSkinVariableString(const CSkinVariableString* info)
{
if (!info)
Expand Down
11 changes: 11 additions & 0 deletions xbmc/GUIInfoManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ typedef std::shared_ptr<CGUIListItem> CGUIListItemPtr;

namespace KODI
{
namespace GAME
{
class CGameInfoTag;
}
namespace GUILIB
{
namespace GUIINFO
Expand Down Expand Up @@ -109,6 +113,10 @@ class CGUIInfoManager : public KODI::MESSAGING::IMessageTarget
bool GetItemInt(int &value, const CGUIListItem *item, int contextWindow, int info) const;
bool GetItemBool(const CGUIListItem *item, int contextWindow, int condition) const;

/*! \brief Get currently playing file item
*/
const CFileItem& GetCurrentItem() const { return *m_currentFile; }

/*! \brief Set currently playing file item
*/
void SetCurrentItem(const CFileItem &item);
Expand All @@ -122,6 +130,9 @@ class CGUIInfoManager : public KODI::MESSAGING::IMessageTarget
// Current video stuff
const CVideoInfoTag* GetCurrentMovieTag() const;

// Current game stuff
const KODI::GAME::CGameInfoTag* GetCurrentGameTag() const;

void UpdateAVInfo();

int RegisterSkinVariableString(const INFO::CSkinVariableString* info);
Expand Down
55 changes: 46 additions & 9 deletions xbmc/cores/RetroPlayer/RetroPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "RetroPlayer.h"

#include "FileItem.h"
#include "GUIInfoManager.h"
#include "RetroPlayerAutoSave.h"
#include "RetroPlayerInput.h"
#include "ServiceBroker.h"
Expand Down Expand Up @@ -40,6 +41,7 @@
#include "guilib/WindowIDs.h"
#include "input/actions/Action.h"
#include "input/actions/ActionIDs.h"
#include "interfaces/AnnouncementManager.h"
#include "messaging/ApplicationMessenger.h"
#include "settings/MediaSettings.h"
#include "threads/SingleLock.h"
Expand All @@ -54,37 +56,41 @@ using namespace GAME;
using namespace RETRO;

CRetroPlayer::CRetroPlayer(IPlayerCallback& callback)
: IPlayer(callback), m_gameServices(CServiceBroker::GetGameServices())
: IPlayer(callback),
m_gameServices(CServiceBroker::GetGameServices()),
m_fileItem(new CFileItem())
{
ResetPlayback();
CServiceBroker::GetWinSystem()->RegisterRenderLoop(this);
CServiceBroker::GetAnnouncementManager()->AddAnnouncer(this);
}

CRetroPlayer::~CRetroPlayer()
{
CServiceBroker::GetWinSystem()->UnregisterRenderLoop(this);
CServiceBroker::GetAnnouncementManager()->RemoveAnnouncer(this);
CloseFile();
}

bool CRetroPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options)
{
CFileItem fileCopy(file);
*m_fileItem = file;

std::string savestatePath;

// When playing a game, set the game client that we'll use to open the game.
// This will prompt the user to select a savestate if there are any.
// If there are no savestates, or the user wants to create a new savestate
// it will prompt the user to select a game client
if (!GAME::CGameUtils::FillInGameClient(fileCopy, savestatePath))
if (!GAME::CGameUtils::FillInGameClient(*m_fileItem, savestatePath))
{
CLog::Log(LOGINFO,
"RetroPlayer[PLAYER]: No compatible game client selected, aborting playback");
return false;
}

// Check if we should open in standalone mode
const bool bStandalone = fileCopy.GetPath().empty();
const bool bStandalone = m_fileItem->GetPath().empty();

m_processInfo.reset(CRPProcessInfo::CreateInstance());
if (!m_processInfo)
Expand All @@ -103,11 +109,11 @@ bool CRetroPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options
if (IsPlaying())
CloseFile();

PrintGameInfo(fileCopy);
PrintGameInfo(*m_fileItem);

bool bSuccess = false;

std::string gameClientId = fileCopy.GetGameInfoTag()->GetGameClient();
std::string gameClientId = m_fileItem->GetGameInfoTag()->GetGameClient();

ADDON::AddonPtr addon;
if (gameClientId.empty())
Expand All @@ -131,9 +137,9 @@ bool CRetroPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options

if (!bStandalone)
{
std::string redactedPath = CURL::GetRedacted(fileCopy.GetPath());
std::string redactedPath = CURL::GetRedacted(m_fileItem->GetPath());
CLog::Log(LOGINFO, "RetroPlayer[PLAYER]: Opening: %s", redactedPath.c_str());
bSuccess = m_gameClient->OpenFile(fileCopy, *m_streamManager, m_input.get());
bSuccess = m_gameClient->OpenFile(*m_fileItem, *m_streamManager, m_input.get());
}
else
{
Expand Down Expand Up @@ -182,11 +188,15 @@ bool CRetroPlayer::OpenFile(const CFileItem& file, const CPlayerOptions& options
// Switch to fullscreen
MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_SWITCHTOFULLSCREEN);

m_cheevos.reset(new CCheevos(m_gameClient.get(), m_gameServices.GameSettings().RAUsername(),
m_cheevos.reset(new CCheevos(m_gameClient.get(), *m_fileItem,
m_gameServices.GameSettings().RAUsername(),
m_gameServices.GameSettings().RAToken()));

m_cheevos->EnableRichPresence();

// Calls to external code could mutate file item, so make a copy
CFileItem fileCopy(*m_fileItem);

// Initialize gameplay
CreatePlayback(m_gameServices.GameSettings().AutosaveEnabled(), savestatePath);
RegisterWindowCallbacks();
Expand Down Expand Up @@ -570,6 +580,33 @@ std::string CRetroPlayer::CreateAutosave()
return m_playback->CreateSavestate(true);
}

void CRetroPlayer::Announce(ANNOUNCEMENT::AnnouncementFlag flag,
const std::string& sender,
const std::string& message,
const CVariant& data)
{
// Announce() is called at the end of a chain to update the currently-playing
// file.
//
// Updates to current file metadata should find their way to CApplication.
// This can be accomplished off-thread by sending a TMSG_SET_PLAYER_ITEM
// message via app messenger.
//
// When CApplication receives a file metadata update, it in turn updates
// the state of CGUIInfoManager.
//
// CGUIInfoManager fires an "OnChanged" event for the info update. Publishers
// of file item metadata should be subscribed to this event to receive info
// updates from other publishers, as well as info added by CApplication
// during the playback lifecycle.

if (flag == ANNOUNCEMENT::Info && message == "OnChanged")
{
const CGUIInfoManager& infoMgr = CServiceBroker::GetGUI()->GetInfoManager();
*m_fileItem = infoMgr.GetCurrentItem();
}
}

void CRetroPlayer::SetSpeedInternal(double speed)
{
OnSpeedChange(speed);
Expand Down
13 changes: 12 additions & 1 deletion xbmc/cores/RetroPlayer/RetroPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "cores/RetroPlayer/playback/IPlaybackControl.h"
#include "games/GameTypes.h"
#include "guilib/DispResource.h"
#include "interfaces/IAnnouncer.h"
#include "threads/CriticalSection.h"

#include <memory>
Expand All @@ -38,7 +39,8 @@ class CRetroPlayer : public IPlayer,
public IRenderLoop,
public IGameCallback,
public IPlaybackCallback,
public IAutoSaveCallback
public IAutoSaveCallback,
public ANNOUNCEMENT::IAnnouncer
{
public:
explicit CRetroPlayer(IPlayerCallback& callback);
Expand Down Expand Up @@ -84,6 +86,12 @@ class CRetroPlayer : public IPlayer,
bool IsAutoSaveEnabled() const override;
std::string CreateAutosave() override;

// Implementation of IAnnouncer
void Announce(ANNOUNCEMENT::AnnouncementFlag flag,
const std::string& sender,
const std::string& message,
const CVariant& data) override;

private:
void SetSpeedInternal(double speed);

Expand Down Expand Up @@ -136,6 +144,9 @@ class CRetroPlayer : public IPlayer,

// Synchronization parameters
CCriticalSection m_mutex;

// File metadata
std::shared_ptr<CFileItem> m_fileItem;
};
} // namespace RETRO
} // namespace KODI
34 changes: 25 additions & 9 deletions xbmc/cores/RetroPlayer/cheevos/Cheevos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@

#include "Cheevos.h"

#include "FileItem.h"
#include "URL.h"
#include "filesystem/CurlFile.h"
#include "filesystem/File.h"
#include "games/addons/GameClient.h"
#include "games/tags/GameInfoTag.h"
#include "messaging/ApplicationMessenger.h"
#include "utils/JSONVariantParser.h"
#include "utils/URIUtils.h"
#include "utils/Variant.h"
Expand Down Expand Up @@ -39,9 +42,13 @@ constexpr int URL_SIZE = 512;
constexpr int POST_DATA_SIZE = 1024;

CCheevos::CCheevos(GAME::CGameClient* gameClient,
const std::string userName,
const std::string loginToken)
: m_gameClient(gameClient), m_userName(userName), m_loginToken(loginToken)
CFileItem& fileItem,
std::string userName,
std::string loginToken)
: m_gameClient(gameClient),
m_fileItem(fileItem),
m_userName(std::move(userName)),
m_loginToken(std::move(loginToken))
{
}

Expand Down Expand Up @@ -116,12 +123,13 @@ bool CCheevos::LoadData()
m_richPresenceScript = data[PATCH_DATA][RICH_PRESENCE].asString();
m_richPresenceLoaded = true;

m_title = data[PATCH_DATA][GAME_TITLE].asString();
m_publisher = data[PATCH_DATA][PUBLISHER].asString();
m_developer = data[PATCH_DATA][DEVELOPER].asString();
m_genre = data[PATCH_DATA][GENRE].asString();
m_consoleName = data[PATCH_DATA][CONSOLE_NAME].asString();
m_released = data[PATCH_DATA][RELEASED].asString();
GAME::CGameInfoTag& tag = *m_fileItem.GetGameInfoTag();

tag.SetTitle(data[PATCH_DATA][GAME_TITLE].asString());
tag.SetPublisher(data[PATCH_DATA][PUBLISHER].asString());
tag.SetDeveloper(data[PATCH_DATA][DEVELOPER].asString());
tag.SetGenres({data[PATCH_DATA][GENRE].asString()});
tag.SetPlatform(data[PATCH_DATA][CONSOLE_NAME].asString());

return true;
}
Expand Down Expand Up @@ -151,6 +159,14 @@ bool CCheevos::GetRichPresenceEvaluation(char* evaluation, size_t size)

m_gameClient->GetRichPresenceEvaluation(evaluation, size);

GAME::CGameInfoTag& tag = *m_fileItem.GetGameInfoTag();

tag.SetCaption(evaluation);

CFileItem* file = new CFileItem(m_fileItem);
MESSAGING::CApplicationMessenger::GetInstance().PostMsg(TMSG_SET_PLAYER_ITEM, -1, -1,
static_cast<void*>(file));

char url[URL_SIZE];
char postData[POST_DATA_SIZE];
if (m_gameClient->RCPostRichPresenceUrl(url, URL_SIZE, postData, POST_DATA_SIZE,
Expand Down
36 changes: 15 additions & 21 deletions xbmc/cores/RetroPlayer/cheevos/Cheevos.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <map>
#include <string>

class CFileItem;

namespace KODI
{
namespace GAME
Expand All @@ -25,36 +27,28 @@ namespace RETRO
class CCheevos
{
public:
CCheevos(GAME::CGameClient* gameClient, const std::string userName, const std::string loginToken);
CCheevos(GAME::CGameClient* gameClient,
CFileItem& fileItem,
std::string userName,
std::string loginToken);
void ResetRuntime();
void EnableRichPresence();
bool GetRichPresenceEvaluation(char* evaluation, size_t size);

std::string GetTitle() { return m_title; }
std::string GetPublisher() { return m_publisher; }
std::string GetDeveloper() { return m_developer; }
std::string GetGenre() { return m_genre; }
std::string GetConsoleName() { return m_consoleName; }
std::string GetReleased() { return m_released; }

private:
bool LoadData();

// Construction parameters
GAME::CGameClient* const m_gameClient;
std::string m_userName;
std::string m_loginToken;
std::string m_romHash{};
std::string m_richPresenceScript{};
unsigned m_gameID{};
bool m_richPresenceLoaded{};
CFileItem& m_fileItem;
const std::string m_userName;
const std::string m_loginToken;

// Game metadata
std::string m_title;
std::string m_publisher;
std::string m_developer;
std::string m_genre;
std::string m_consoleName;
std::string m_released;
// Game parameters
std::string m_romHash;
std::string m_richPresenceScript;
unsigned m_gameID = 0;
bool m_richPresenceLoaded = false;

const std::map<std::string, int> m_extensionToConsole = {{".a26", RC_CONSOLE_ATARI_2600},
{".a78", RC_CONSOLE_ATARI_7800},
Expand Down
6 changes: 5 additions & 1 deletion xbmc/interfaces/legacy/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,11 @@ namespace XBMCAddon
if (!g_application.GetAppPlayer().IsPlayingGame())
throw PlayerException("XBMC is not playing any game file");

return new InfoTagGame(*g_application.CurrentFileItem().GetGameInfoTag());
const KODI::GAME::CGameInfoTag* game = CServiceBroker::GetGUI()->GetInfoManager().GetCurrentGameTag();
if (game != nullptr)
return new InfoTagGame(*game);

return new InfoTagGame();
}

InfoTagVideo* Player::getVideoInfoTag()
Expand Down
Loading

0 comments on commit 05f0c1b

Please sign in to comment.