aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Härer <markus.haerer@gmx.net>2024-04-26 18:18:33 +0200
committerGitHub <noreply@github.com>2024-04-26 18:18:33 +0200
commit4ee6643c16e8a92f494a41b592123ec926ad2216 (patch)
treeb8d112d29a61bfcb1f19bec86e4c2df684c2bf3d
parentc52e76babc8fe6977bb3855d9ff40bdc0adcad3a (diff)
parent54a63d02f1e63ebad0cd99dc06ca070c91ceb93c (diff)
downloadxbmc-4ee6643c16e8a92f494a41b592123ec926ad2216.tar.xz
Merge pull request #24720 from 78andyp/playlist
[Video] Improve user experience when playing movies/episodes from Bluray ISO/BDMV.
-rw-r--r--addons/resource.language.en_gb/resources/strings.po4
-rw-r--r--xbmc/FileItem.cpp25
-rw-r--r--xbmc/FileItem.h2
-rw-r--r--xbmc/PlayListPlayer.cpp11
-rw-r--r--xbmc/PlayListPlayer.h7
-rw-r--r--xbmc/application/Application.cpp9
-rw-r--r--xbmc/application/Application.h5
-rw-r--r--xbmc/dialogs/GUIDialogContextMenu.h1
-rw-r--r--xbmc/dialogs/GUIDialogSimpleMenu.cpp17
-rw-r--r--xbmc/dialogs/GUIDialogSimpleMenu.h2
-rw-r--r--xbmc/utils/SaveFileStateJob.cpp26
-rw-r--r--xbmc/video/VideoDatabase.cpp77
-rw-r--r--xbmc/video/VideoDatabase.h6
-rw-r--r--xbmc/video/VideoFileItemClassify.cpp5
-rw-r--r--xbmc/video/VideoFileItemClassify.h3
-rw-r--r--xbmc/video/windows/GUIWindowVideoBase.cpp12
-rw-r--r--xbmc/video/windows/GUIWindowVideoBase.h2
-rw-r--r--xbmc/windows/GUIMediaWindow.cpp59
18 files changed, 206 insertions, 67 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index cbf612389c..162bd67ca1 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -7289,7 +7289,9 @@ msgctxt "#13423"
msgid "Remember for this path"
msgstr ""
-#empty string with id 13424
+msgctxt "#13424"
+msgid "Choose playlist"
+msgstr ""
#: system/settings/settings.xml
msgctxt "#13425"
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index 558a5a2ad8..1029e0da61 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -1559,6 +1559,9 @@ bool CFileItem::IsSamePath(const CFileItem *item) const
{
if (item->HasProperty("item_start") || HasProperty("item_start"))
return (item->GetProperty("item_start") == GetProperty("item_start"));
+ // See if we have associated a bluray playlist
+ if (IsBlurayPlaylist(*this) || IsBlurayPlaylist(*item))
+ return (GetDynPath() == item->GetDynPath());
return true;
}
if (HasMusicInfoTag() && item->HasMusicInfoTag())
@@ -1958,6 +1961,22 @@ void CFileItem::SetDynPath(const std::string &path)
m_strDynPath = path;
}
+std::string CFileItem::GetBlurayPath() const
+{
+ if (IsBlurayPlaylist(*this))
+ {
+ CURL url(GetDynPath());
+ CURL url2(url.GetHostName()); // strip bluray://
+ if (url2.IsProtocol("udf"))
+ // ISO
+ return url2.GetHostName(); // strip udf://
+ else if (url.IsProtocol("bluray"))
+ // BDMV
+ return url2.Get() + "BDMV/index.bdmv";
+ }
+ return GetDynPath();
+}
+
void CFileItem::SetCueDocument(const CCueDocumentPtr& cuePtr)
{
m_cueDocument = cuePtr;
@@ -2472,7 +2491,11 @@ std::string CFileItem::GetLocalMetadataPath() const
if (m_bIsFolder && !IsFileFolder())
return m_strPath;
- std::string parent(URIUtils::GetParentPath(m_strPath));
+ std::string parent{};
+ if (IsBlurayPlaylist(*this))
+ parent = URIUtils::GetParentPath(GetBlurayPath());
+ else
+ parent = URIUtils::GetParentPath(m_strPath);
std::string parentFolder(parent);
URIUtils::RemoveSlashAtEnd(parentFolder);
parentFolder = URIUtils::GetFileName(parentFolder);
diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h
index 473c11c9d7..db0e8ed4be 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -142,6 +142,8 @@ public:
const std::string &GetDynPath() const;
void SetDynPath(const std::string &path);
+ std::string GetBlurayPath() const;
+
/*! \brief reset class to it's default values as per construction.
Free's all allocated memory.
\sa Initialize
diff --git a/xbmc/PlayListPlayer.cpp b/xbmc/PlayListPlayer.cpp
index feaa7f4fb4..23185d2d42 100644
--- a/xbmc/PlayListPlayer.cpp
+++ b/xbmc/PlayListPlayer.cpp
@@ -266,7 +266,9 @@ bool CPlayListPlayer::PlayItemIdx(int itemIdx)
return Play();
}
-bool CPlayListPlayer::Play(const CFileItemPtr& pItem, const std::string& player)
+bool CPlayListPlayer::Play(const CFileItemPtr& pItem,
+ const std::string& player,
+ bool forceSelection /* = false */)
{
Id playlistId;
bool isVideo{IsVideo(*pItem)};
@@ -304,13 +306,14 @@ bool CPlayListPlayer::Play(const CFileItemPtr& pItem, const std::string& player)
SetCurrentPlaylist(playlistId);
Add(playlistId, pItem);
- return Play(0, player);
+ return Play(0, player, false, false, forceSelection);
}
bool CPlayListPlayer::Play(int iSong,
const std::string& player,
bool bAutoPlay /* = false */,
- bool bPlayPrevious /* = false */)
+ bool bPlayPrevious /* = false */,
+ bool forceSelection /* = false */)
{
if (m_iCurrentPlayList == TYPE_NONE)
return false;
@@ -342,7 +345,7 @@ bool CPlayListPlayer::Play(int iSong,
m_bPlaybackStarted = false;
const auto playAttempt = std::chrono::steady_clock::now();
- bool ret = g_application.PlayFile(*item, player, bAutoPlay);
+ bool ret = g_application.PlayFile(*item, player, bAutoPlay, forceSelection);
if (!ret)
{
CLog::Log(LOGERROR, "Playlist Player: skipping unplayable item: {}, path [{}]", m_iCurrentSong,
diff --git a/xbmc/PlayListPlayer.h b/xbmc/PlayListPlayer.h
index 961aaf28d4..f17abf6280 100644
--- a/xbmc/PlayListPlayer.h
+++ b/xbmc/PlayListPlayer.h
@@ -55,19 +55,22 @@ public:
* \brief Creates a new playlist for an item and starts playing it
* \param pItem The item to play.
* \param player The player name.
+ * \param forceSelection for Blurays, force simple menu to change playlist (default to false)
* \return True if has success, otherwise false.
*/
- bool Play(const CFileItemPtr& pItem, const std::string& player);
+ bool Play(const CFileItemPtr& pItem, const std::string& player, bool forceSelection = false);
/*! \brief Start playing a particular entry in the current playlist
\param index the index of the item to play. This value is modified to ensure it lies within the current playlist.
\param replace whether this item should replace the currently playing item. See CApplication::PlayFile (defaults to false).
\param playPreviousOnFail whether to go back to the previous item if playback fails (default to false)
+ \param forceSelection for Blurays, force simple menu to change playlist (default to false)
*/
bool Play(int index,
const std::string& player,
bool replace = false,
- bool playPreviousOnFail = false);
+ bool playPreviousOnFail = false,
+ bool forceSelection = false);
/*! \brief Returns the index of the current item in active playlist.
\return Current item in the active playlist.
diff --git a/xbmc/application/Application.cpp b/xbmc/application/Application.cpp
index 6541a22759..9244fb2040 100644
--- a/xbmc/application/Application.cpp
+++ b/xbmc/application/Application.cpp
@@ -2286,7 +2286,10 @@ bool CApplication::PlayStack(CFileItem& item, bool bRestart)
return PlayFile(selectedStackPart, "", true);
}
-bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRestart)
+bool CApplication::PlayFile(CFileItem item,
+ const std::string& player,
+ bool bRestart /* = false */,
+ bool forceSelection /* = false */)
{
// Ensure the MIME type has been retrieved for http:// and shout:// streams
if (item.GetMimeType().empty())
@@ -2426,7 +2429,7 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes
// a disc image might be Blu-Ray disc
if (!(options.startpercent > 0.0 || options.starttime > 0.0) &&
- (IsBDFile(item) || item.IsDiscImage()))
+ (IsBDFile(item) || item.IsDiscImage() || (IsBlurayPlaylist(item) && forceSelection)))
{
// No video selection when using external or remote players (they handle it if supported)
const bool isSimpleMenuAllowed = [&]()
@@ -2444,7 +2447,7 @@ bool CApplication::PlayFile(CFileItem item, const std::string& player, bool bRes
if (isSimpleMenuAllowed)
{
// Check if we must show the simplified bd menu.
- if (!CGUIDialogSimpleMenu::ShowPlaySelection(item))
+ if (!CGUIDialogSimpleMenu::ShowPlaySelection(item, forceSelection))
return true;
}
}
diff --git a/xbmc/application/Application.h b/xbmc/application/Application.h
index e06df1cc26..d87ad975f9 100644
--- a/xbmc/application/Application.h
+++ b/xbmc/application/Application.h
@@ -125,7 +125,10 @@ public:
PLAYLIST::CPlayList& playlist,
PLAYLIST::Id playlistId,
int track = 0);
- bool PlayFile(CFileItem item, const std::string& player, bool bRestart = false);
+ bool PlayFile(CFileItem item,
+ const std::string& player,
+ bool bRestart = false,
+ bool forceSelection = false);
void StopPlaying();
void Restart(bool bSamePosition = true);
void DelayedPlayerRestart();
diff --git a/xbmc/dialogs/GUIDialogContextMenu.h b/xbmc/dialogs/GUIDialogContextMenu.h
index 9ca6b1f22b..10385bd20e 100644
--- a/xbmc/dialogs/GUIDialogContextMenu.h
+++ b/xbmc/dialogs/GUIDialogContextMenu.h
@@ -88,6 +88,7 @@ enum CONTEXT_BUTTON
CONTEXT_BUTTON_PLAY_NEXT,
CONTEXT_BUTTON_NAVIGATE,
CONTEXT_BUTTON_MANAGE_VIDEOVERSIONS,
+ CONTEXT_BUTTON_CHOOSE_PLAYLIST,
};
class CContextButtons : public std::vector< std::pair<size_t, std::string> >
diff --git a/xbmc/dialogs/GUIDialogSimpleMenu.cpp b/xbmc/dialogs/GUIDialogSimpleMenu.cpp
index 61016f477a..2049e2615c 100644
--- a/xbmc/dialogs/GUIDialogSimpleMenu.cpp
+++ b/xbmc/dialogs/GUIDialogSimpleMenu.cpp
@@ -29,6 +29,8 @@
#include "video/VideoFileItemClassify.h"
#include "video/VideoInfoTag.h"
+std::string m_savePath;
+
using namespace KODI;
namespace
@@ -52,12 +54,18 @@ protected:
};
}
-
-bool CGUIDialogSimpleMenu::ShowPlaySelection(CFileItem& item)
+bool CGUIDialogSimpleMenu::ShowPlaySelection(CFileItem& item, bool forceSelection /* = false */)
{
if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_DISC_PLAYBACK) != BD_PLAYBACK_SIMPLE_MENU)
return true;
+ m_savePath = "";
+ if (VIDEO::IsBlurayPlaylist(item) && forceSelection)
+ {
+ m_savePath = item.GetDynPath(); // save for screen refresh later
+ item.SetDynPath(item.GetBlurayPath());
+ }
+
if (VIDEO::IsBDFile(item))
{
std::string root = URIUtils::GetParentPath(item.GetDynPath());
@@ -127,10 +135,11 @@ bool CGUIDialogSimpleMenu::ShowPlaySelection(CFileItem& item, const std::string&
if (item_new->m_bIsFolder == false)
{
- std::string original_path = item.GetDynPath();
+ if (m_savePath.empty()) // If not set above (choose playlist selected)
+ m_savePath = item.GetDynPath();
item.SetDynPath(item_new->GetDynPath());
item.SetProperty("get_stream_details_from_player", true);
- item.SetProperty("original_listitem_url", original_path);
+ item.SetProperty("original_listitem_url", m_savePath);
return true;
}
diff --git a/xbmc/dialogs/GUIDialogSimpleMenu.h b/xbmc/dialogs/GUIDialogSimpleMenu.h
index ed476a4d92..bf7ccae980 100644
--- a/xbmc/dialogs/GUIDialogSimpleMenu.h
+++ b/xbmc/dialogs/GUIDialogSimpleMenu.h
@@ -20,7 +20,7 @@ class CGUIDialogSimpleMenu
public:
/*! \brief Show dialog allowing selection of wanted playback item */
- static bool ShowPlaySelection(CFileItem& item);
+ static bool ShowPlaySelection(CFileItem& item, bool forceSelection = false);
static bool ShowPlaySelection(CFileItem& item, const std::string& directory);
protected:
diff --git a/xbmc/utils/SaveFileStateJob.cpp b/xbmc/utils/SaveFileStateJob.cpp
index aeb479a4bb..d2886f640e 100644
--- a/xbmc/utils/SaveFileStateJob.cpp
+++ b/xbmc/utils/SaveFileStateJob.cpp
@@ -38,15 +38,24 @@ void CSaveFileState::DoWork(CFileItem& item,
{
std::string progressTrackingFile = item.GetPath();
- if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
- progressTrackingFile = item.GetVideoInfoTag()->m_strFileNameAndPath; // this variable contains removable:// suffixed by disc label+uniqueid or is empty if label not uniquely identified
+ if (item.HasVideoInfoTag() &&
+ StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
+ progressTrackingFile =
+ item.GetVideoInfoTag()
+ ->m_strFileNameAndPath; // this variable contains removable:// suffixed by disc label+uniqueid or is empty if label not uniquely identified
+ else if (IsBlurayPlaylist(item) && (item.GetVideoContentType() == VideoDbContentType::MOVIES ||
+ item.GetVideoContentType() == VideoDbContentType::EPISODES))
+ progressTrackingFile = item.GetDynPath();
else if (item.HasVideoInfoTag() && IsVideoDb(item))
- progressTrackingFile = item.GetVideoInfoTag()->m_strFileNameAndPath; // we need the file url of the video db item to create the bookmark
+ progressTrackingFile =
+ item.GetVideoInfoTag()
+ ->m_strFileNameAndPath; // we need the file url of the video db item to create the bookmark
else if (item.HasProperty("original_listitem_url"))
{
// only use original_listitem_url for Python, UPnP and Bluray sources
std::string original = item.GetProperty("original_listitem_url").asString();
- if (URIUtils::IsPlugin(original) || URIUtils::IsUPnP(original) || URIUtils::IsBluray(item.GetPath()))
+ if (URIUtils::IsPlugin(original) || URIUtils::IsUPnP(original) ||
+ URIUtils::IsBluray(item.GetPath()))
progressTrackingFile = original;
}
@@ -162,7 +171,14 @@ void CSaveFileState::DoWork(CFileItem& item,
if (!videodatabase.GetStreamDetails(dbItem) ||
dbItem.GetVideoInfoTag()->m_streamDetails != item.GetVideoInfoTag()->m_streamDetails)
{
- videodatabase.SetStreamDetailsForFile(item.GetVideoInfoTag()->m_streamDetails, progressTrackingFile);
+ const int idFile = videodatabase.SetStreamDetailsForFile(
+ item.GetVideoInfoTag()->m_streamDetails, item.GetDynPath());
+ if (item.GetVideoContentType() == VideoDbContentType::MOVIES)
+ videodatabase.SetFileForMovie(item.GetDynPath(), item.GetVideoInfoTag()->m_iDbId,
+ idFile);
+ else if (item.GetVideoContentType() == VideoDbContentType::EPISODES)
+ videodatabase.SetFileForEpisode(item.GetDynPath(), item.GetVideoInfoTag()->m_iDbId,
+ idFile);
updateListing = true;
}
}
diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp
index a40b707a3f..a0b05561db 100644
--- a/xbmc/video/VideoDatabase.cpp
+++ b/xbmc/video/VideoDatabase.cpp
@@ -3020,6 +3020,49 @@ int CVideoDatabase::SetDetailsForSeason(const CVideoInfoTag& details, const std:
return -1;
}
+bool CVideoDatabase::SetFileForEpisode(const std::string& fileAndPath, int idEpisode, int idFile)
+{
+ try
+ {
+ BeginTransaction();
+ std::string sql = PrepareSQL("UPDATE episode SET c18='%s', idFile=%i WHERE idEpisode=%i",
+ fileAndPath.c_str(), idFile, idEpisode);
+ m_pDS->exec(sql);
+ CommitTransaction();
+
+ return true;
+ }
+ catch (...)
+ {
+ CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, idEpisode);
+ }
+ RollbackTransaction();
+ return false;
+}
+
+bool CVideoDatabase::SetFileForMovie(const std::string& fileAndPath, int idMovie, int idFile)
+{
+ try
+ {
+ BeginTransaction();
+ std::string sql = PrepareSQL("UPDATE movie SET c22='%s', idFile=%i WHERE idMovie=%i",
+ fileAndPath.c_str(), idFile, idMovie);
+ m_pDS->exec(sql);
+ sql = PrepareSQL("UPDATE videoversion SET idFile=%i WHERE idMedia=%i AND media_type='movie'",
+ idFile, idMovie);
+ m_pDS->exec(sql);
+ CommitTransaction();
+
+ return true;
+ }
+ catch (...)
+ {
+ CLog::Log(LOGERROR, "{} ({}) failed", __FUNCTION__, idMovie);
+ }
+ RollbackTransaction();
+ return false;
+}
+
int CVideoDatabase::SetDetailsForEpisode(CVideoInfoTag& details,
const std::map<std::string, std::string>& artwork,
int idShow,
@@ -3209,13 +3252,15 @@ int CVideoDatabase::SetDetailsForMusicVideo(CVideoInfoTag& details,
return -1;
}
-void CVideoDatabase::SetStreamDetailsForFile(const CStreamDetails& details, const std::string &strFileNameAndPath)
+int CVideoDatabase::SetStreamDetailsForFile(const CStreamDetails& details,
+ const std::string& strFileNameAndPath)
{
// AddFile checks to make sure the file isn't already in the DB first
int idFile = AddFile(strFileNameAndPath);
if (idFile < 0)
- return;
+ return -1;
SetStreamDetailsForFileId(details, idFile);
+ return idFile;
}
void CVideoDatabase::SetStreamDetailsForFileId(const CStreamDetails& details, int idFile)
@@ -4175,7 +4220,6 @@ bool CVideoDatabase::GetStreamDetails(CFileItem& item)
if (item.HasVideoInfoTag())
fileId = item.GetVideoInfoTag()->m_iFileId;
-
if (fileId < 0)
fileId = GetFileId(item);
@@ -4187,9 +4231,17 @@ bool CVideoDatabase::GetStreamDetails(CFileItem& item)
return GetStreamDetails(*item.GetVideoInfoTag());
}
-bool CVideoDatabase::GetStreamDetails(CVideoInfoTag& tag) const
+bool CVideoDatabase::GetStreamDetails(CVideoInfoTag& tag)
{
- if (tag.m_iFileId < 0)
+
+ const std::string path = tag.m_strFileNameAndPath;
+ int fileId{-1};
+ if (URIUtils::GetExtension(path) == ".mpls")
+ fileId = GetFileId(path);
+ else
+ fileId = tag.m_iFileId;
+
+ if (fileId < 0)
return false;
bool retVal = false;
@@ -4200,7 +4252,7 @@ bool CVideoDatabase::GetStreamDetails(CVideoInfoTag& tag) const
std::unique_ptr<Dataset> pDS(m_pDB->CreateDataset());
try
{
- std::string strSQL = PrepareSQL("SELECT * FROM streamdetails WHERE idFile = %i", tag.m_iFileId);
+ std::string strSQL = PrepareSQL("SELECT * FROM streamdetails WHERE idFile = %i", fileId);
pDS->query(strSQL);
while (!pDS->eof())
@@ -6530,7 +6582,10 @@ int CVideoDatabase::GetPlayCount(const std::string& strFilenameAndPath)
int CVideoDatabase::GetPlayCount(const CFileItem &item)
{
- return GetPlayCount(GetFileId(item));
+ if (IsBlurayPlaylist(item))
+ return GetPlayCount(GetFileId(item.GetDynPath()));
+ else
+ return GetPlayCount(GetFileId(item));
}
CDateTime CVideoDatabase::GetLastPlayed(int iFileId)
@@ -6600,9 +6655,11 @@ void CVideoDatabase::UpdateFanart(const CFileItem& item, VideoDbContentType type
CDateTime CVideoDatabase::SetPlayCount(const CFileItem& item, int count, const CDateTime& date)
{
- int id;
- if (item.HasProperty("original_listitem_url") &&
- URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
+ int id{-1};
+ if (IsBlurayPlaylist(item))
+ id = AddFile(item.GetDynPath());
+ else if (item.HasProperty("original_listitem_url") &&
+ URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
{
CFileItem item2(item);
item2.SetPath(item.GetProperty("original_listitem_url").asString());
diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h
index aa0bee416d..a8b2bce51b 100644
--- a/xbmc/video/VideoDatabase.h
+++ b/xbmc/video/VideoDatabase.h
@@ -584,10 +584,12 @@ public:
const std::map<std::string, std::string>& artwork,
int idShow,
int idEpisode = -1);
+ bool SetFileForEpisode(const std::string& fileAndPath, int idEpisode, int idFile);
+ bool SetFileForMovie(const std::string& fileAndPath, int idMovie, int idFile);
int SetDetailsForMusicVideo(CVideoInfoTag& details,
const std::map<std::string, std::string>& artwork,
int idMVideo = -1);
- void SetStreamDetailsForFile(const CStreamDetails& details, const std::string &strFileNameAndPath);
+ int SetStreamDetailsForFile(const CStreamDetails& details, const std::string& strFileNameAndPath);
void SetStreamDetailsForFileId(const CStreamDetails& details, int idFile);
bool SetSingleValue(VideoDbContentType type, int dbId, int dbField, const std::string& strValue);
@@ -686,7 +688,7 @@ public:
void DeleteBookMarkForEpisode(const CVideoInfoTag& tag);
bool GetResumePoint(CVideoInfoTag& tag);
bool GetStreamDetails(CFileItem& item);
- bool GetStreamDetails(CVideoInfoTag& tag) const;
+ bool GetStreamDetails(CVideoInfoTag& tag);
bool GetDetailsByTypeAndId(CFileItem& item, VideoDbContentType type, int id);
CVideoInfoTag GetDetailsByTypeAndId(VideoDbContentType type, int id);
diff --git a/xbmc/video/VideoFileItemClassify.cpp b/xbmc/video/VideoFileItemClassify.cpp
index d57306013d..afeaafcb65 100644
--- a/xbmc/video/VideoFileItemClassify.cpp
+++ b/xbmc/video/VideoFileItemClassify.cpp
@@ -72,6 +72,11 @@ bool IsProtectedBlurayDisc(const CFileItem& item)
return CFileUtils::Exists(path);
}
+bool IsBlurayPlaylist(const CFileItem& item)
+{
+ return StringUtils::EqualsNoCase(URIUtils::GetExtension(item.GetDynPath()), ".mpls");
+}
+
bool IsSubtitle(const CFileItem& item)
{
return URIUtils::HasExtension(item.GetPath(),
diff --git a/xbmc/video/VideoFileItemClassify.h b/xbmc/video/VideoFileItemClassify.h
index 55e5aeded7..7a24113fde 100644
--- a/xbmc/video/VideoFileItemClassify.h
+++ b/xbmc/video/VideoFileItemClassify.h
@@ -25,6 +25,9 @@ bool IsDVDFile(const CFileItem& item, bool bVobs = true, bool bIfos = true);
//! \brief Checks whether item points to a protected blu-ray disc.
bool IsProtectedBlurayDisc(const CFileItem& item);
+//! \brief Checks whether item points to a blu-ray playlist (.mpls)
+bool IsBlurayPlaylist(const CFileItem& item);
+
//! \brief Check whether an item is a subtitle file.
bool IsSubtitle(const CFileItem& item);
diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp
index 13c1bd25d2..9a8fb77ff6 100644
--- a/xbmc/video/windows/GUIWindowVideoBase.cpp
+++ b/xbmc/video/windows/GUIWindowVideoBase.cpp
@@ -836,6 +836,8 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but
}
if (item->IsSmartPlayList() || m_vecItems->IsSmartPlayList())
buttons.Add(CONTEXT_BUTTON_EDIT_SMART_PLAYLIST, 586);
+ if (IsBlurayPlaylist(*item))
+ buttons.Add(CONTEXT_BUTTON_CHOOSE_PLAYLIST, 13424);
}
}
CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
@@ -892,6 +894,7 @@ bool CGUIWindowVideoBase::OnPlayStackPart(const std::shared_ptr<CFileItem>& item
bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
{
CFileItemPtr item;
+ m_forceSelection = false;
if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
item = m_vecItems->Get(itemNumber);
switch (button)
@@ -945,6 +948,11 @@ bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
return OnPlayAndQueueMedia(item);
case CONTEXT_BUTTON_PLAY_ONLY_THIS:
return OnPlayMedia(itemNumber);
+ case CONTEXT_BUTTON_CHOOSE_PLAYLIST:
+ {
+ m_forceSelection = true;
+ return OnPlayMedia(itemNumber);
+ }
default:
break;
}
@@ -982,7 +990,7 @@ bool CGUIWindowVideoBase::OnPlayMedia(const std::shared_ptr<CFileItem>& pItem,
if (m_thumbLoader.IsLoading())
m_thumbLoader.StopAsync();
- CServiceBroker::GetPlaylistPlayer().Play(itemCopy, player);
+ CServiceBroker::GetPlaylistPlayer().Play(itemCopy, player, m_forceSelection);
const auto& components = CServiceBroker::GetAppComponents();
const auto appPlayer = components.GetComponent<CApplicationPlayer>();
@@ -1118,6 +1126,8 @@ bool CGUIWindowVideoBase::PlayItem(const std::shared_ptr<CFileItem>& pItem,
return true;
}
+ m_forceSelection = false;
+
//! @todo get rid of "videos with versions as folder" hack!
if (pItem->m_bIsFolder && !pItem->IsPlugin() &&
!(pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->IsDefaultVideoVersion()))
diff --git a/xbmc/video/windows/GUIWindowVideoBase.h b/xbmc/video/windows/GUIWindowVideoBase.h
index 943db2bad4..acbd535cc1 100644
--- a/xbmc/video/windows/GUIWindowVideoBase.h
+++ b/xbmc/video/windows/GUIWindowVideoBase.h
@@ -143,4 +143,6 @@ private:
\return true: the information of the item was modified. false: no change.
*/
bool ShowInfo(const CFileItemPtr& item, const ADDON::ScraperPtr& content);
+
+ bool m_forceSelection;
};
diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp
index aab1d37e0c..4e6464e48e 100644
--- a/xbmc/windows/GUIMediaWindow.cpp
+++ b/xbmc/windows/GUIMediaWindow.cpp
@@ -61,6 +61,7 @@
#include "utils/Variant.h"
#include "utils/log.h"
#include "video/VideoFileItemClassify.h"
+#include "video/VideoInfoTag.h"
#include "view/GUIViewState.h"
#include <inttypes.h>
@@ -1528,40 +1529,34 @@ bool CGUIMediaWindow::OnPlayAndQueueMedia(const CFileItemPtr& item, const std::s
PLAYLIST::Id playlistId = m_guiState->GetPlaylist();
if (playlistId != PLAYLIST::TYPE_NONE)
{
+ // Remove ZIP, RAR files and folders
+ CFileItemList playlist;
+ playlist.Copy(*m_vecItems, true);
+ playlist.erase(std::remove_if(playlist.begin(), playlist.end(),
+ [](const std::shared_ptr<CFileItem>& i)
+ { return i->IsZIP() || i->IsRAR() || i->m_bIsFolder; }),
+ playlist.end());
+
+ // Remove duplicates (eg. ISO/VIDEO_TS)
+ playlist.erase(
+ std::unique(playlist.begin(), playlist.end(),
+ [](const std::shared_ptr<CFileItem>& i, const std::shared_ptr<CFileItem>& j) {
+ return i->GetVideoInfoTag()->m_basePath == j->GetVideoInfoTag()->m_basePath;
+ }),
+ playlist.end());
+
+ // Chosen item
+ int mediaToPlay =
+ std::distance(playlist.begin(), std::find_if(playlist.begin(), playlist.end(),
+ [&item](const std::shared_ptr<CFileItem>& i) {
+ return i->GetVideoInfoTag()->m_basePath ==
+ item->GetVideoInfoTag()->m_basePath;
+ }));
+
+ // Add to playlist
CServiceBroker::GetPlaylistPlayer().ClearPlaylist(playlistId);
CServiceBroker::GetPlaylistPlayer().Reset();
- int mediaToPlay = 0;
-
- // first try to find mainDVD file (VIDEO_TS.IFO).
- // If we find this we should not allow to queue VOB files
- std::string mainDVD;
- for (int i = 0; i < m_vecItems->Size(); i++)
- {
- std::string path = URIUtils::GetFileName(m_vecItems->Get(i)->GetDynPath());
- if (StringUtils::EqualsNoCase(path, "VIDEO_TS.IFO"))
- {
- mainDVD = path;
- break;
- }
- }
-
- // now queue...
- for ( int i = 0; i < m_vecItems->Size(); i++ )
- {
- CFileItemPtr nItem = m_vecItems->Get(i);
-
- if (nItem->m_bIsFolder)
- continue;
-
- if (!nItem->IsZIP() && !nItem->IsRAR() &&
- (!IsDVDFile(*nItem) || (URIUtils::GetFileName(nItem->GetDynPath()) == mainDVD)))
- CServiceBroker::GetPlaylistPlayer().Add(playlistId, nItem);
-
- if (item->IsSamePath(nItem.get()))
- { // item that was clicked
- mediaToPlay = CServiceBroker::GetPlaylistPlayer().GetPlaylist(playlistId).size() - 1;
- }
- }
+ CServiceBroker::GetPlaylistPlayer().Add(playlistId, playlist);
// Save current window and directory to know where the selected item was
if (m_guiState)