rendered paste bodydiff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cppindex 5ad317d..ed7b9cf 100644--- a/xbmc/FileItem.cpp+++ b/xbmc/FileItem.cpp@@ -2215,7 +2215,13 @@ void CFileItemList::Stack() if (Get(stack[0])->IsRAR()) stackPath = Get(stack[0])->m_strPath; else- stackPath = dir.ConstructStackPath(*this, stack);+ {+ CStdString stackTitlePath, commonDir;+ commonDir = Get(stack[0])->m_strPath;+ CUtil::GetCommonPath(commonDir, Get(stack[1])->m_strPath);+ CUtil::AddFileToFolder(commonDir, stackName, stackTitlePath);+ stackPath = dir.ConstructStackPath(*this, stack, stackTitlePath);+ } item1->m_strPath = stackPath; // clean up list for (unsigned k = 1; k < stack.size(); k++)diff --git a/xbmc/FileSystem/StackDirectory.cpp b/xbmc/FileSystem/StackDirectory.cppindex f62c5c7..28f61fd 100644--- a/xbmc/FileSystem/StackDirectory.cpp+++ b/xbmc/FileSystem/StackDirectory.cpp@@ -25,9 +25,8 @@ #include "FileItem.h" #include "StringUtils.h" -#define PRE_2_1_STACK_COMPATIBILITY- using namespace std;+ namespace DIRECTORY { CStackDirectory::CStackDirectory()@@ -38,6 +37,20 @@ namespace DIRECTORY { } + bool CStackDirectory::GetDirectory(const CStdString& strPath, CFileItemList& items, CStdString& strStackTitlePath)+ {+ CStdStringArray files, tokens;+ StringUtils::SplitString(strPath, " ; ", tokens);+ if (tokens.size() > 1) // 4 capture algo+ {+ strStackTitlePath = tokens[1];+ CUtil::UrlDecode(strStackTitlePath);+ }+ else+ strStackTitlePath = GetStackedTitlePath(tokens[0]);+ return GetDirectory(strPath, items);+ }+ bool CStackDirectory::GetDirectory(const CStdString& strPath, CFileItemList& items) { items.Clear();@@ -47,55 +60,74 @@ namespace DIRECTORY //CStdString folder, file; //CUtil::Split(strPath, folder, file); // split files on the single comma- CStdStringArray files;- StringUtils::SplitString(strPath, " , ", files);- if (files.empty())- return false; // error in path- // remove "stack://" from the folder- for (unsigned int i = 0; i < files.size(); i++)+ CStdStringArray files, tokens;+ StringUtils::SplitString(strPath, " ; ", tokens);+ if (!tokens.empty()) {- CStdString file = files[i];- if (i == 0)- file = file.Mid(8);-#ifdef PRE_2_1_STACK_COMPATIBILITY- if (i > 0 && file.Find("\\") == -1 && file.Find('/') == -1)+ StringUtils::SplitString(tokens[0], " , ", files);+ if (files.empty())+ return false; // error in path+ // remove "stack://" from the folder+ for (unsigned int i = 0; i < files.size(); i++) {- CStdString strPath;- CUtil::GetDirectory(items[0]->m_strPath,strPath);- CStdString strFile = file;- CUtil::AddFileToFolder(strPath,strFile,file);+ CStdString file = files[i];+ if (i == 0)+ file = file.Mid(8);+ if (tokens.size() > 1) // 4 capture algo+ CUtil::UrlDecode(file);+ else // replace double comma's with single ones.+ file.Replace(",,", ",");+ CFileItemPtr item(new CFileItem(file));+ item->m_strPath = file;+ item->m_bIsFolder = false;+ items.Add(item); }-#endif- // replace double comma's with single ones.- file.Replace(",,", ",");- CFileItemPtr item(new CFileItem(file));- //CUtil::AddFileToFolder(folder, file, item->m_strPath);- item->m_strPath = file;- item->m_bIsFolder = false;- items.Add(item);+ return true; }- return true;+ return false; } CStdString CStackDirectory::GetStackedTitlePath(const CStdString &strPath) { CStdString path, file, folder;- int pos = strPath.Find(" , ");- // remove "stack://" from the folder- if (pos > 0)+ CStdStringArray tokens;+ StringUtils::SplitString(strPath, " ; ", tokens);+ if (tokens.size() > 1) // 4 capture stack algo appends the stackedTitlePath and url encodes everything {- CUtil::Split(strPath.Left(pos), folder, file);- file.Replace(",,", ",");- folder = folder.Mid(8);- CStdString title, volume;- CUtil::GetVolumeFromFileName(file, title, volume);- CUtil::AddFileToFolder(folder, title, path);+ path = tokens[1];+ CUtil::UrlDecode(path);+ }+ else+ {+ int pos = strPath.Find(" , ");+ // remove "stack://" from the folder+ if (pos > 0)+ {+ CUtil::Split(strPath.Left(pos), folder, file);+ file.Replace(",,", ",");+ folder = folder.Mid(8);+ CStdString title, volume;+ CUtil::GetVolumeFromFileName(file, title, volume);+ CUtil::AddFileToFolder(folder, title, path);+ } } return path; } CStdString CStackDirectory::GetFirstStackedFile(const CStdString &strPath) {+ CStdString strBikeShed;+ CStdStringArray tokens;+ StringUtils::SplitString(strPath, " ; ", tokens);++ if (tokens.size() > 1) // 4 capture stack algo+ {+ strBikeShed = tokens[0];+ CUtil::UrlDecode(strBikeShed);+ }+ else+ strBikeShed = strPath;+ // the stacked files are always in volume order, so just get up to the first filename // occurence of " , " CStdString path, file, folder;@@ -107,56 +139,51 @@ namespace DIRECTORY // remove "stack://" from the folder folder = folder.Mid(8);- file.Replace(",,", ",");+ if (tokens.size() <= 1) // Not 4 capture stack algo+ file.Replace(",,", ","); CUtil::AddFileToFolder(folder, file, path); return path; } - CStdString CStackDirectory::ConstructStackPath(const CFileItemList &items, const vector<int> &stack)+ CStdString CStackDirectory::ConstructStackPath(const CFileItemList &items, const vector<int> &stack, const CStdString& strStackedFilename) {- // no checks on the range of stack here.- // we replace all instances of comma's with double comma's, then separate- // the files using " , ".- CStdString stackedPath = "stack://";- CStdString folder, file;- CUtil::Split(items[stack[0]]->m_strPath, folder, file);- stackedPath += folder;- // double escape any occurence of commas- file.Replace(",", ",,");+ CStdString stackedPath("stack://");+ CStdString file(items[stack[0]]->m_strPath);+ CUtil::URLEncode(file); stackedPath += file; for (unsigned int i = 1; i < stack.size(); ++i) { stackedPath += " , "; file = items[stack[i]]->m_strPath;-- // double escape any occurence of commas- file.Replace(",", ",,");+ CUtil::URLEncode(file); stackedPath += file; }++ file = strStackedFilename;+ CUtil::URLEncode(file);+ stackedPath += " ; " + file; return stackedPath; } - bool CStackDirectory::ConstructStackPath(const vector<CStdString> &paths, CStdString& stackedPath)+ bool CStackDirectory::ConstructStackPath(const vector<CStdString> &paths, CStdString& stackedPath, const CStdString& strStackedFilename) { if (paths.size() < 2) return false; stackedPath = "stack://";- CStdString folder, file;- CUtil::Split(paths[0], folder, file);- stackedPath += folder;- // double escape any occurence of commas- file.Replace(",", ",,");+ CStdString file = paths[0];+ CUtil::URLEncode(file); stackedPath += file; for (unsigned int i = 1; i < paths.size(); ++i) { stackedPath += " , "; file = paths[i];-- // double escape any occurence of commas- file.Replace(",", ",,");+ CUtil::URLEncode(file); stackedPath += file; }+ file = strStackedFilename;+ CUtil::URLEncode(file);+ stackedPath += " ; " + file; return true; } }diff --git a/xbmc/FileSystem/StackDirectory.h b/xbmc/FileSystem/StackDirectory.hindex 63eefc9..8be9d15 100644--- a/xbmc/FileSystem/StackDirectory.h+++ b/xbmc/FileSystem/StackDirectory.h@@ -30,11 +30,12 @@ namespace DIRECTORY public: CStackDirectory(); ~CStackDirectory();+ virtual bool GetDirectory(const CStdString& strPath, CFileItemList& items, CStdString& strStackTitlePath); virtual bool GetDirectory(const CStdString& strPath, CFileItemList& items); virtual bool IsAllowed(const CStdString &strFile) const { return true; }; static CStdString GetStackedTitlePath(const CStdString &strPath); static CStdString GetFirstStackedFile(const CStdString &strPath);- CStdString ConstructStackPath(const CFileItemList& items, const std::vector<int> &stack);- bool ConstructStackPath(const std::vector<CStdString> &paths, CStdString &stackedPath);+ static CStdString ConstructStackPath(const CFileItemList& items, const std::vector<int> &stack, const CStdString& strStackTitlePath);+ static bool ConstructStackPath(const std::vector<CStdString> &paths, CStdString &stackedPath, const CStdString& strStackTitlePath); }; }diff --git a/xbmc/URL.cpp b/xbmc/URL.cppindex 765edf2..0bd83f6 100644--- a/xbmc/URL.cpp+++ b/xbmc/URL.cpp@@ -526,10 +526,11 @@ CStdString CURL::GetWithoutUserDetails() const if (m_strProtocol.Equals("stack")) { CFileItemList items;- CStdString strURL2;+ CStdString strURL2,+ stackedTitleName; strURL2 = Get(); DIRECTORY::CStackDirectory dir;- dir.GetDirectory(strURL2,items);+ dir.GetDirectory(strURL2,items, stackedTitleName); vector<CStdString> newItems; for (int i=0;i<items.Size();++i) {@@ -537,7 +538,7 @@ CStdString CURL::GetWithoutUserDetails() const items[i]->m_strPath = url.GetWithoutUserDetails(); newItems.push_back(items[i]->m_strPath); }- dir.ConstructStackPath(newItems,strURL);+ dir.ConstructStackPath(newItems,strURL,stackedTitleName); return strURL; } diff --git a/xbmc/Util.cpp b/xbmc/Util.cppindex 29b9c6a..3e557b5 100644--- a/xbmc/Util.cpp+++ b/xbmc/Util.cpp@@ -470,6 +470,13 @@ void CUtil::GetCommonPath(CStdString& strParent, const CStdString& strPath) } } +CStdString CUtil::GetParentPath(const CStdString& strPath)+{+ CStdString strReturn;+ GetParentPath(strPath, strReturn);+ return strReturn;+}+ bool CUtil::GetParentPath(const CStdString& strPath, CStdString& strParent) { strParent = "";diff --git a/xbmc/Util.h b/xbmc/Util.hindex 2a34380..7355310 100644--- a/xbmc/Util.h+++ b/xbmc/Util.h@@ -75,6 +75,7 @@ public: static void GetCommonPath(CStdString& strPath, const CStdString& strPath2); static bool IsDOSPath(const CStdString &path); static bool IsHD(const CStdString& strFileName);+ static CStdString GetParentPath(const CStdString& strPath); static bool GetParentPath(const CStdString& strPath, CStdString& strParent); static void GetQualifiedFilename(const CStdString &strBasePath, CStdString &strFilename); static void RunShortcut(const char* szPath);diff --git a/xbmc/VideoDatabase.cpp b/xbmc/VideoDatabase.cppindex 95538ae..6d3b37a 100644--- a/xbmc/VideoDatabase.cpp+++ b/xbmc/VideoDatabase.cpp@@ -49,7 +49,7 @@ using namespace XFILE; using namespace DIRECTORY; using namespace VIDEO; -#define VIDEO_DATABASE_VERSION 33+#define VIDEO_DATABASE_VERSION 34 #define VIDEO_DATABASE_OLD_VERSION 3.f #define VIDEO_DATABASE_NAME "MyVideos34.db" @@ -3717,6 +3717,113 @@ bool CVideoDatabase::UpdateOldVersion(int iVersion) m_pDS->exec("CREATE UNIQUE INDEX ix_setlinkmovie_1 ON setlinkmovie ( idSet, idMovie)\n"); m_pDS->exec("CREATE UNIQUE INDEX ix_setlinkmovie_2 ON setlinkmovie ( idMovie, idSet)\n"); }+ if (iVersion < 34)+ {+ // Load up our REs+ VECCREGEXP RegExps;+ CRegExp tempRE(true);+ const CStdStringArray& strRegExps = g_advancedSettings.m_videoStackRegExps;+ CStdStringArray::const_iterator itRegExp = strRegExps.begin();+ while (itRegExp != strRegExps.end())+ {+ tempRE.RegComp(*itRegExp);+ if (tempRE.GetCaptureTotal() == 4)+ RegExps.push_back(tempRE);+ else+ CLog::Log(LOGERROR, "Invalid video stack RE (%s). Must have exactly 4 captures.", itRegExp->c_str());+ itRegExp++;+ }++ // Grab all stack paths and their ID+ m_pDS->query("select idFile,strFilename from files where strFilename like 'stack://%'");+ while (!m_pDS->eof())+ {+ CStackDirectory stack;+ CFileItemList files;+ CStdString path(m_pDS->fv(1).get_asString());+ stack.GetDirectory(m_pDS->fv(1).get_asString(), files);++ if (files.Size() > 1)+ {+ CStdString Dir1, File1,+ Dir2, File2,+ CommonDir,+ StackFilename;+ std::pair<std::string::iterator, std::string::iterator> diffs;++ CUtil::Split(files[0]->GetAsUrl().GetWithoutUserDetails(), Dir1, File1);+ CUtil::Split(files[1]->GetAsUrl().GetWithoutUserDetails(), Dir2, File2);+ CommonDir = CUtil::GetParentPath(m_pDS->fv(1).get_asString());++ std::vector<CRegExp>::iterator itRegExp = RegExps.begin();+ size_t offset = 0;++ while (itRegExp != RegExps.end())+ {+ if (itRegExp->RegFind(File1, offset) != -1)+ {+ CStdString Title1 = itRegExp->GetMatch(1),+ Volume1 = itRegExp->GetMatch(2),+ Ignore1 = itRegExp->GetMatch(3),+ Extension1 = itRegExp->GetMatch(4);+ if (offset)+ Title1 = File1.substr(0, itRegExp->GetSubStart(2));+ if (itRegExp->RegFind(File2, offset) != -1)+ {+ CStdString Title2 = itRegExp->GetMatch(1),+ Volume2 = itRegExp->GetMatch(2),+ Ignore2 = itRegExp->GetMatch(3),+ Extension2 = itRegExp->GetMatch(4);+ if (offset)+ Title2 = File2.substr(0, itRegExp->GetSubStart(2));+ if (Title1.Equals(Title2))+ {+ if (!Volume1.Equals(Volume2))+ {+ if (Ignore1.Equals(Ignore2) && Extension1.Equals(Extension2))+ {+ // got it+ StackFilename = Title1 + Extension1;+ itRegExp = RegExps.end();+ break;+ }+ else // Invalid stack+ break;+ }+ else // Early match, retry with offset+ {+ if (0 < (offset = itRegExp->GetSubStart(3)))+ {+ offset = 0;+ itRegExp++;+ }+ continue;+ }+ }+ }+ }+ offset = 0;+ itRegExp++;+ }++ if (!StackFilename.empty() && !CommonDir.empty())+ {+ std::vector<int> stackIndicies;+ CStdString StackTitleName = CommonDir + StackFilename,+ StackPath;++ for (int i = 0; i < files.Size(); i++)+ stackIndicies.push_back(i);++ StackPath = CStackDirectory::ConstructStackPath(files, stackIndicies, StackTitleName);+ CStdString sqlCmd = FormatSQL("update files set strFilename='%s' where idFile=%i",+ StackPath.c_str(), m_pDS->fv(0).get_asInt());+ m_pDS2->exec(sqlCmd.c_str());+ }+ }+ m_pDS->next();+ }+ } } catch (...) {