diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 12e87bc6df413..7824d0521850e 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -800,6 +800,7 @@ msgstr ""
#: xbmc/pvr/windows/GUIViewStatePVR.cpp
#: addons/skin.estuary/xml/Variables.xml
#: addons/skin.estuary/xml/View_51_Poster.xml
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: addons/skin.estuary/xml/DialogVideoInfo.xml
msgctxt "#180"
msgid "Duration"
@@ -1259,6 +1260,7 @@ msgstr ""
#: xbmc/pvr/dialogs/GUIDialogPVRGuideInfo.cpp
#: xbmc/pvr/windows/GUIWIndowPVRGuide.cpp
#: xbmc/pvr/PVRContextMenus.cpp
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: addons/skin.estuary/xml/Variables.xml
msgctxt "#264"
msgid "Record"
@@ -2593,6 +2595,7 @@ msgid "Name"
msgstr ""
#. generic "date" label used in different places
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: addons/skin.estuary/xml/Variables.xml
#: xbmc/pvr/windows/GUIViewStatePVR.cpp
msgctxt "#552"
@@ -2671,6 +2674,7 @@ msgstr ""
#: xbmc/playlists/SmartPlaylist.cpp
#: xbmc/music/MusicUtils.cpp
#: xbmc/video/dialogs/GUIDialogVideoInfo.cpp
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: addons/skin.estuary/xml/DialogVideoInfo.xml
#: addons/skin.estuary/xml/DialogFullScreenInfo.xml
msgctxt "#563"
@@ -2703,6 +2707,7 @@ msgstr ""
#. generic "last played" label used in different places
#: addons/skin.estuary/xml/Includes_MusicInfo.xml
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: xbmc/dialogs/GUIDialogMediaFilter.cpp
#: xbmc/playlists/SmartPlaylist.cpp
#: xbmc/pvr/windows/GUIViewStatePVR.cpp
@@ -2752,6 +2757,7 @@ msgctxt "#575"
msgid "In progress"
msgstr ""
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
msgctxt "#576"
msgid "Times played"
msgstr ""
@@ -9721,6 +9727,7 @@ msgid "or use phrases to find an exact match, like \"The wizard of Oz\"."
msgstr ""
#. Label of a context menu entry to find similar programs (matching a given epg event)
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: xbmc/pvr/PVRContextMenuItem.cpp
msgctxt "#19003"
msgid "Find similar"
@@ -9898,6 +9905,7 @@ msgstr ""
#. generic 'channel' label used in different places
#: addons/skin.estuary/xml/DialogFullScreenInfo.xml
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: xbmc/filesystem/PluginDirectory.cpp
#: xbmc/pvr/channels/PVRChannel.cpp
#: xbmc/pvr/guilib/PVRGUIActionsPlayback.cpp
@@ -12495,6 +12503,7 @@ msgid "Channel guide"
msgstr ""
#. Label for context menu entries, dialog heading, button to start playing a recording
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: xbmc/pvr/PVRContextMenus.cpp
#: xbmc/pvr/guilib/PVRGUIActionsPlayback.cpp
msgctxt "#19687"
@@ -15726,6 +15735,7 @@ msgctxt "#22030"
msgid "Font"
msgstr ""
+#: addons/skin.estuary/xml/DialogPVRInfo.xml
#: system/settings/settings.xml
msgctxt "#22031"
msgid "Size"
diff --git a/addons/skin.estuary/xml/DialogPVRInfo.xml b/addons/skin.estuary/xml/DialogPVRInfo.xml
index f66419cc39e8b..313bd199a415a 100644
--- a/addons/skin.estuary/xml/DialogPVRInfo.xml
+++ b/addons/skin.estuary/xml/DialogPVRInfo.xml
@@ -1,126 +1,372 @@
/// } +/// \table_row3{ `MusicPlayer.Genre(separator)`, +/// \anchor MusicPlayer_Genre_separator +/// _string_, +/// @return A list of genres of current song\, separated by given separator\, or if no +/// separator was given separated by the advanced settings value \“itemseparator\” for music. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `MusicPlayer.offset(number).Genre`, /// \anchor MusicPlayer_OffSet_Genre /// _string_, @@ -3162,6 +3172,16 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE }, /// @return The genre(s) of current movie\, if it's in the database. ///
/// } +/// \table_row3{ `VideoPlayer.Genre(separator)`, +/// \anchor VideoPlayer_Genre_separator +/// _string_, +/// @return A list of genres of current movie\, separated by given separator\, or if no +/// separator was given separated by the advanced settings value \“itemseparator\” for videos. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `VideoPlayer.offset(number).Genre`, /// \anchor VideoPlayer_Offset_Genre /// _string_, @@ -3187,6 +3207,17 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE }, /// also supports EPG. ///
/// } +/// \table_row3{ `VideoPlayer.Director(separator)`, +/// \anchor VideoPlayer_Director_separator +/// _string_, +/// @return A list of directors of the currently playing video\, separated by given separator\, +/// or if no separator was given separated by the advanced settings value \“itemseparator\” for +/// video items. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `VideoPlayer.offset(number).Director`, /// \anchor VideoPlayer_Offset_Director /// _string_, @@ -3488,6 +3519,16 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE }, /// also supports EPG. ///
/// } +/// \table_row3{ `VideoPlayer.Cast(separator)`, +/// \anchor VideoPlayer_Cast_separator +/// _string_, +/// @return A list of cast members of the currently playing video\, separated by given +/// separator\, or if no separator was given separated by carriage returns. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `VideoPlayer.CastAndRole`, /// \anchor VideoPlayer_CastAndRole /// _string_, @@ -3495,6 +3536,16 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE }, /// returns. Every cast/role combination is formatted 'cast' as 'role' where 'as' is localised. ///
/// } +/// \table_row3{ `VideoPlayer.CastAndRole(separator)`, +/// \anchor VideoPlayer_CastAndRole_separator +/// _string_, +/// @return A list of cast members and roles of the currently playing video\, pairs separated by +/// given separator\, or if no separator was given separated by carriage returns. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `VideoPlayer.Album`, /// \anchor VideoPlayer_Album /// _string_, @@ -3570,6 +3621,17 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE }, /// also supports EPG. ///
/// } +/// \table_row3{ `VideoPlayer.Writer(separator)`, +/// \anchor VideoPlayer_Writer_separator +/// _string_, +/// @return A list of writers of the currently playing video\, separated by given separator\, +/// or if no separator was given separated by the advanced settings value \“itemseparator\” for +/// video items. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `VideoPlayer.offset(number).Writer`, /// \anchor VideoPlayer_Offset_Writer /// _string_, @@ -3835,6 +3897,17 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE }, /// @return The genre of the programme that will be played next (PVR). ///
/// } +/// \table_row3{ `VideoPlayer.NextGenre(separator)`, +/// \anchor VideoPlayer_NextGenre_separator +/// _string_, +/// @return A list of genres of the programme that will be played next (PVR)\, separated by +/// given separator\, or if no separator was given separated by the advanced settings value +/// \“itemseparator\” for videos. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `VideoPlayer.NextPlot`, /// \anchor VideoPlayer_NextPlot /// _string_, @@ -5107,6 +5180,16 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// container. ///
/// } +/// \table_row3{ `ListItem.Genre(separator)`, +/// \anchor ListItem_Genre_separator +/// _string_, +/// @return A list of genres\, separated by given separator\, or if no separator was given +/// separated by the advanced settings value \“itemseparator\” for videos or music. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `ListItem.Contributors`, /// \anchor ListItem_Contributors /// _string_, @@ -5132,6 +5215,16 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// also supports EPG. ///
/// } +/// \table_row3{ `ListItem.Director(separator)`, +/// \anchor ListItem_Director_separator +/// _string_, +/// @return A list of directors\, separated by given separator\, or if no separator was given +/// separated by the advanced settings value \“itemseparator\” for video items. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `ListItem.Country`, /// \anchor ListItem_Country /// _string_, @@ -5967,6 +6060,16 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// also supports EPG. ///
/// } +/// \table_row3{ `ListItem.Cast(separator)`, +/// \anchor ListItem_Cast_separator +/// _string_, +/// @return A list of cast members\, separated by given separator\, or if no separator was +/// given separated by carriage returns. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `ListItem.CastAndRole`, /// \anchor ListItem_CastAndRole /// _string_, @@ -5974,6 +6077,16 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// returns. Every cast/role combination is formatted 'cast' as 'role' where 'as' is localised. ///
/// } +/// \table_row3{ `ListItem.CastAndRole(separator)`, +/// \anchor ListItem_CastAndRole_separator +/// _string_, +/// @return A list of cast members and roles\, separated by given separator\, or if no separator +/// was given separated by carriage returns. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `ListItem.Studio`, /// \anchor ListItem_Studio /// _string_, @@ -6003,6 +6116,16 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// also supports EPG. ///
/// } +/// \table_row3{ `ListItem.Writer(separator)`, +/// \anchor ListItem_Writer_separator +/// _string_, +/// @return A list of writers\, separated by given separator\, or if no separator was given +/// separated by the advanced settings value \“itemseparator\” for video items. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// } /// \table_row3{ `ListItem.Tag`, /// \anchor ListItem_Tag /// _string_, @@ -6316,6 +6439,17 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY }, /// @return The genre of the next item (PVR). ///
/// } +/// \table_row3{ `ListItem.NextGenre(separator)`, +/// \anchor ListItem_NextGenre_separator +/// _string_, +/// @return A list of genres of the the next item (PVR)\, separated by given separator\, or if +/// no separator was given separated by the advanced settings value \“itemseparator\” for +/// videos. +/// Possible values for separator: comma\, pipe\, slash\, cr\, dash\, colon\, semicolon\, fullstop +///
+/// }
/// \table_row3{ `ListItem.NextPlot`,
/// \anchor ListItem_NextPlot
/// _string_,
@@ -10220,6 +10354,34 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition)
return TranslateSingleString(strCondition, listItemDependent);
}
+namespace
+{
+std::string TranslateListSeparator(const std::string& param)
+{
+ if (StringUtils::EqualsNoCase(param, "comma"))
+ return ",";
+ else if (StringUtils::EqualsNoCase(param, "pipe"))
+ return "|";
+ else if (StringUtils::EqualsNoCase(param, "slash"))
+ return "/";
+ else if (StringUtils::EqualsNoCase(param, "cr"))
+ return "\n";
+ else if (StringUtils::EqualsNoCase(param, "dash"))
+ return "-";
+ else if (StringUtils::EqualsNoCase(param, "colon"))
+ return ":";
+ else if (StringUtils::EqualsNoCase(param, "semicolon"))
+ return ";";
+ else if (StringUtils::EqualsNoCase(param, "fullstop"))
+ return ".";
+ else
+ {
+ CLog::Log(LOGERROR, "unhandled separator param {}", param);
+ return {};
+ }
+}
+} // unnamed namespace
+
int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool &listItemDependent)
{
/* We need to disable caching in INFO::InfoBool::Get if either of the following are true:
@@ -10525,7 +10687,13 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool
return AddMultiInfo(CGUIInfo(player_time.val, TranslateTimeFormat(prop.param())));
}
if (prop.name == "content" && prop.num_params())
+ {
return AddMultiInfo(CGUIInfo(MUSICPLAYER_CONTENT, prop.param(), 0));
+ }
+ else if (prop.name == "genre" && prop.num_params() > 0)
+ {
+ return AddMultiInfo(CGUIInfo(MUSICPLAYER_GENRE, TranslateListSeparator(prop.param()), 0));
+ }
else if (prop.name == "property")
{
if (StringUtils::EqualsNoCase(prop.param(), "fanart_image"))
@@ -10557,6 +10725,33 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool
{
return AddMultiInfo(CGUIInfo(VIDEOPLAYER_ART, prop.param(), 0));
}
+ if (prop.name == "cast" && prop.num_params() > 0)
+ {
+ return AddMultiInfo(CGUIInfo(VIDEOPLAYER_CAST, TranslateListSeparator(prop.param()), 0));
+ }
+ if (prop.name == "castandrole" && prop.num_params() > 0)
+ {
+ return AddMultiInfo(
+ CGUIInfo(VIDEOPLAYER_CAST_AND_ROLE, TranslateListSeparator(prop.param()), 0));
+ }
+ if (prop.name == "writer" && prop.num_params() > 0)
+ {
+ return AddMultiInfo(CGUIInfo(VIDEOPLAYER_WRITER, TranslateListSeparator(prop.param()), 0));
+ }
+ if (prop.name == "director" && prop.num_params() > 0)
+ {
+ return AddMultiInfo(
+ CGUIInfo(VIDEOPLAYER_DIRECTOR, TranslateListSeparator(prop.param()), 0));
+ }
+ if (prop.name == "genre" && prop.num_params() > 0)
+ {
+ return AddMultiInfo(CGUIInfo(VIDEOPLAYER_GENRE, TranslateListSeparator(prop.param()), 0));
+ }
+ if (prop.name == "nextgenre" && prop.num_params() > 0)
+ {
+ return AddMultiInfo(
+ CGUIInfo(VIDEOPLAYER_NEXT_GENRE, TranslateListSeparator(prop.param()), 0));
+ }
return TranslateVideoPlayerString(prop.name);
}
else if (cat.name == "retroplayer")
@@ -10885,6 +11080,11 @@ int CGUIInfoManager::TranslateListItem(const Property& cat, const Property& prop
{
data3 = prop.param();
}
+ else if (prop.name == "cast" || prop.name == "castandrole" || prop.name == "director" ||
+ prop.name == "writer" || prop.name == "genre" || prop.name == "nextgenre")
+ {
+ data3 = TranslateListSeparator(prop.param());
+ }
else if (prop.name == "duration" || prop.name == "nextduration")
{
data4 = TranslateTimeFormat(prop.param());
diff --git a/xbmc/guilib/guiinfo/MusicGUIInfo.cpp b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp
index 79bd4b13b7161..54ce7ab508e9c 100644
--- a/xbmc/guilib/guiinfo/MusicGUIInfo.cpp
+++ b/xbmc/guilib/guiinfo/MusicGUIInfo.cpp
@@ -188,8 +188,14 @@ bool CMusicGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont
return true;
case MUSICPLAYER_GENRE:
case LISTITEM_GENRE:
- value = StringUtils::Join(tag->GetGenre(), CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_musicItemSeparator);
+ {
+ const std::string sep{info.GetData3().empty() ? CServiceBroker::GetSettingsComponent()
+ ->GetAdvancedSettings()
+ ->m_musicItemSeparator
+ : info.GetData3()};
+ value = StringUtils::Join(tag->GetGenre(), sep);
return true;
+ }
case MUSICPLAYER_LYRICS:
value = tag->GetLyrics();
return true;
diff --git a/xbmc/guilib/guiinfo/VideoGUIInfo.cpp b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp
index 5fd1e3cb9bede..c91715b5ea1a7 100644
--- a/xbmc/guilib/guiinfo/VideoGUIInfo.cpp
+++ b/xbmc/guilib/guiinfo/VideoGUIInfo.cpp
@@ -143,12 +143,24 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont
return true;
case VIDEOPLAYER_GENRE:
case LISTITEM_GENRE:
- value = StringUtils::Join(tag->m_genre, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
+ {
+ const std::string sep{info.GetData3().empty() ? CServiceBroker::GetSettingsComponent()
+ ->GetAdvancedSettings()
+ ->m_videoItemSeparator
+ : info.GetData3()};
+ value = StringUtils::Join(tag->m_genre, sep);
return true;
+ }
case VIDEOPLAYER_DIRECTOR:
case LISTITEM_DIRECTOR:
- value = StringUtils::Join(tag->m_director, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
+ {
+ const std::string sep{info.GetData3().empty() ? CServiceBroker::GetSettingsComponent()
+ ->GetAdvancedSettings()
+ ->m_videoItemSeparator
+ : info.GetData3()};
+ value = StringUtils::Join(tag->m_director, sep);
return true;
+ }
case VIDEOPLAYER_IMDBNUMBER:
case LISTITEM_IMDBNUMBER:
value = tag->GetUniqueID();
@@ -300,11 +312,11 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont
break;
case VIDEOPLAYER_CAST:
case LISTITEM_CAST:
- value = tag->GetCast();
+ value = tag->GetCast(info.GetData3());
return true;
case VIDEOPLAYER_CAST_AND_ROLE:
case LISTITEM_CAST_AND_ROLE:
- value = tag->GetCast(true);
+ value = tag->GetCast(info.GetData3(), true);
return true;
case VIDEOPLAYER_ARTIST:
case LISTITEM_ARTIST:
@@ -316,8 +328,14 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont
return true;
case VIDEOPLAYER_WRITER:
case LISTITEM_WRITER:
- value = StringUtils::Join(tag->m_writingCredits, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
+ {
+ const std::string sep{info.GetData3().empty() ? CServiceBroker::GetSettingsComponent()
+ ->GetAdvancedSettings()
+ ->m_videoItemSeparator
+ : info.GetData3()};
+ value = StringUtils::Join(tag->m_writingCredits, sep);
return true;
+ }
case VIDEOPLAYER_TAGLINE:
case LISTITEM_TAGLINE:
value = tag->m_strTagLine;
diff --git a/xbmc/interfaces/legacy/InfoTagVideo.cpp b/xbmc/interfaces/legacy/InfoTagVideo.cpp
index f81d3f69579ec..aa9834064ca1c 100644
--- a/xbmc/interfaces/legacy/InfoTagVideo.cpp
+++ b/xbmc/interfaces/legacy/InfoTagVideo.cpp
@@ -219,7 +219,7 @@ namespace XBMCAddon
String InfoTagVideo::getCast()
{
- return infoTag->GetCast(true);
+ return infoTag->GetCast("\n", true);
}
std::vector