strip added smb:// shares of their user/pass when adding, and instead store that...
[vuplus_xbmc] / xbmc / filesystem / VideoDatabaseDirectory / DirectoryNode.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "DirectoryNode.h"
23 #include "utils/URIUtils.h"
24 #include "QueryParams.h"
25 #include "DirectoryNodeRoot.h"
26 #include "DirectoryNodeOverview.h"
27 #include "DirectoryNodeGenre.h"
28 #include "DirectoryNodeCountry.h"
29 #include "DirectoryNodeSets.h"
30 #include "DirectoryNodeTitleMovies.h"
31 #include "DirectoryNodeTitleTvShows.h"
32 #include "DirectoryNodeYear.h"
33 #include "DirectoryNodeActor.h"
34 #include "DirectoryNodeDirector.h"
35 #include "DirectoryNodeMoviesOverview.h"
36 #include "DirectoryNodeTvShowsOverview.h"
37 #include "DirectoryNodeSeasons.h"
38 #include "DirectoryNodeEpisodes.h"
39 #include "DirectoryNodeRecentlyAddedMovies.h"
40 #include "DirectoryNodeRecentlyAddedEpisodes.h"
41 #include "DirectoryNodeStudio.h"
42 #include "DirectoryNodeMusicVideosOverview.h"
43 #include "DirectoryNodeRecentlyAddedMusicVideos.h"
44 #include "DirectoryNodeTitleMusicVideos.h"
45 #include "DirectoryNodeMusicVideoAlbum.h"
46 #include "video/VideoInfoTag.h"
47 #include "URL.h"
48 #include "settings/AdvancedSettings.h"
49 #include "FileItem.h"
50 #include "filesystem/File.h"
51 #include "utils/StringUtils.h"
52 #include "guilib/LocalizeStrings.h"
53 #include "utils/Variant.h"
54 #include "video/VideoDatabase.h"
55
56 using namespace std;
57 using namespace XFILE::VIDEODATABASEDIRECTORY;
58
59 //  Constructor is protected use ParseURL()
60 CDirectoryNode::CDirectoryNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent)
61 {
62   m_Type=Type;
63   m_strName=strName;
64   m_pParent=pParent;
65 }
66
67 CDirectoryNode::~CDirectoryNode()
68 {
69   delete m_pParent;
70 }
71
72 //  Parses a given path and returns the current node of the path
73 CDirectoryNode* CDirectoryNode::ParseURL(const CStdString& strPath)
74 {
75   CURL url(strPath);
76
77   CStdString strDirectory=url.GetFileName();
78   URIUtils::RemoveSlashAtEnd(strDirectory);
79
80   CStdStringArray Path;
81   StringUtils::SplitString(strDirectory, "/", Path);
82   if (!strDirectory.IsEmpty())
83     Path.insert(Path.begin(), "");
84
85   CDirectoryNode* pNode=NULL;
86   CDirectoryNode* pParent=NULL;
87   NODE_TYPE NodeType=NODE_TYPE_ROOT;
88
89   for (int i=0; i<(int)Path.size(); ++i)
90   {
91     pNode=CDirectoryNode::CreateNode(NodeType, Path[i], pParent);
92     NodeType= pNode ? pNode->GetChildType() : NODE_TYPE_NONE;
93     pParent=pNode;
94   }
95
96   return pNode;
97 }
98
99 //  returns the database ids of the path,
100 void CDirectoryNode::GetDatabaseInfo(const CStdString& strPath, CQueryParams& params)
101 {
102   auto_ptr<CDirectoryNode> pNode(CDirectoryNode::ParseURL(strPath));
103
104   if (!pNode.get())
105     return;
106
107   pNode->CollectQueryParams(params);
108 }
109
110 //  Create a node object
111 CDirectoryNode* CDirectoryNode::CreateNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent)
112 {
113   switch (Type)
114   {
115   case NODE_TYPE_ROOT:
116     return new CDirectoryNodeRoot(strName, pParent);
117   case NODE_TYPE_OVERVIEW:
118     return new CDirectoryNodeOverview(strName, pParent);
119   case NODE_TYPE_GENRE:
120     return new CDirectoryNodeGenre(strName, pParent);
121   case NODE_TYPE_COUNTRY:
122     return new CDirectoryNodeCountry(strName, pParent);
123   case NODE_TYPE_SETS:
124     return new CDirectoryNodeSets(strName, pParent);
125   case NODE_TYPE_YEAR:
126     return new CDirectoryNodeYear(strName, pParent);
127   case NODE_TYPE_ACTOR:
128     return new CDirectoryNodeActor(strName, pParent);
129   case NODE_TYPE_DIRECTOR:
130     return new CDirectoryNodeDirector(strName, pParent);
131   case NODE_TYPE_TITLE_MOVIES:
132     return new CDirectoryNodeTitleMovies(strName, pParent);
133   case NODE_TYPE_TITLE_TVSHOWS:
134     return new CDirectoryNodeTitleTvShows(strName, pParent);
135   case NODE_TYPE_MOVIES_OVERVIEW:
136     return new CDirectoryNodeMoviesOverview(strName, pParent);
137   case NODE_TYPE_TVSHOWS_OVERVIEW:
138     return new CDirectoryNodeTvShowsOverview(strName, pParent);
139   case NODE_TYPE_SEASONS:
140     return new CDirectoryNodeSeasons(strName, pParent);
141   case NODE_TYPE_EPISODES:
142     return new CDirectoryNodeEpisodes(strName, pParent);
143   case NODE_TYPE_RECENTLY_ADDED_MOVIES:
144     return new CDirectoryNodeRecentlyAddedMovies(strName,pParent);
145   case NODE_TYPE_RECENTLY_ADDED_EPISODES:
146     return new CDirectoryNodeRecentlyAddedEpisodes(strName,pParent);
147   case NODE_TYPE_STUDIO:
148     return new CDirectoryNodeStudio(strName,pParent);
149   case NODE_TYPE_MUSICVIDEOS_OVERVIEW:
150     return new CDirectoryNodeMusicVideosOverview(strName,pParent);
151   case NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS:
152     return new CDirectoryNodeRecentlyAddedMusicVideos(strName,pParent);
153   case NODE_TYPE_TITLE_MUSICVIDEOS:
154     return new CDirectoryNodeTitleMusicVideos(strName,pParent);
155   case NODE_TYPE_MUSICVIDEOS_ALBUM:
156     return new CDirectoryNodeMusicVideoAlbum(strName,pParent);
157   default:
158     break;
159   }
160
161   return NULL;
162 }
163
164 //  Current node name
165 const CStdString& CDirectoryNode::GetName() const
166 {
167   return m_strName;
168 }
169
170 int CDirectoryNode::GetID() const
171 {
172   return atoi(m_strName.c_str());
173 }
174
175 CStdString CDirectoryNode::GetLocalizedName() const
176 {
177   return "";
178 }
179
180 //  Current node type
181 NODE_TYPE CDirectoryNode::GetType() const
182 {
183   return m_Type;
184 }
185
186 //  Return the parent directory node or NULL, if there is no
187 CDirectoryNode* CDirectoryNode::GetParent() const
188 {
189   return m_pParent;
190 }
191
192 void CDirectoryNode::RemoveParent()
193 {
194   m_pParent=NULL;
195 }
196
197 //  should be overloaded by a derived class
198 //  to get the content of a node. Will be called
199 //  by GetChilds() of a parent node
200 bool CDirectoryNode::GetContent(CFileItemList& items) const
201 {
202   return false;
203 }
204
205 //  Creates a videodb url
206 CStdString CDirectoryNode::BuildPath() const
207 {
208   CStdStringArray array;
209
210   if (!m_strName.IsEmpty())
211     array.insert(array.begin(), m_strName);
212
213   CDirectoryNode* pParent=m_pParent;
214   while (pParent!=NULL)
215   {
216     const CStdString& strNodeName=pParent->GetName();
217     if (!strNodeName.IsEmpty())
218       array.insert(array.begin(), strNodeName);
219
220     pParent=pParent->GetParent();
221   }
222
223   CStdString strPath="videodb://";
224   for (int i=0; i<(int)array.size(); ++i)
225     strPath+=array[i]+"/";
226
227   return strPath;
228 }
229
230 //  Collects Query params from this and all parent nodes. If a NODE_TYPE can
231 //  be used as a database parameter, it will be added to the
232 //  params object.
233 void CDirectoryNode::CollectQueryParams(CQueryParams& params) const
234 {
235   params.SetQueryParam(m_Type, m_strName);
236
237   CDirectoryNode* pParent=m_pParent;
238   while (pParent!=NULL)
239   {
240     params.SetQueryParam(pParent->GetType(), pParent->GetName());
241     pParent=pParent->GetParent();
242   }
243 }
244
245 //  Should be overloaded by a derived class.
246 //  Returns the NODE_TYPE of the child nodes.
247 NODE_TYPE CDirectoryNode::GetChildType() const
248 {
249   return NODE_TYPE_NONE;
250 }
251
252 //  Get the child fileitems of this node
253 bool CDirectoryNode::GetChilds(CFileItemList& items)
254 {
255   if (CanCache() && items.Load())
256     return true;
257
258   auto_ptr<CDirectoryNode> pNode(CDirectoryNode::CreateNode(GetChildType(), "", this));
259
260   bool bSuccess=false;
261   if (pNode.get())
262   {
263     bSuccess=pNode->GetContent(items);
264     if (bSuccess)
265     {
266       AddQueuingFolder(items);
267       if (CanCache())
268         items.SetCacheToDisc(CFileItemList::CACHE_ALWAYS);
269     }
270     else
271       items.Clear();
272
273     pNode->RemoveParent();
274   }
275
276   return bSuccess;
277 }
278
279 //  Add an "* All ..." folder to the CFileItemList
280 //  depending on the child node
281 void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const
282 {
283   CFileItemPtr pItem;
284
285   // always hide "all" items
286   if (g_advancedSettings.m_bVideoLibraryHideAllItems)
287     return;
288
289   // no need for "all" item when only one item
290   if (items.GetObjectCount() <= 1)
291     return;
292
293   // hack - as the season node might return episodes
294   auto_ptr<CDirectoryNode> pNode(ParseURL(items.GetPath()));
295
296   switch (pNode->GetChildType())
297   {
298     case NODE_TYPE_SEASONS:
299       {
300         CStdString strLabel = g_localizeStrings.Get(20366);
301         pItem.reset(new CFileItem(strLabel));  // "All Seasons"
302         pItem->SetPath(BuildPath() + "-1/");
303         // set the number of watched and unwatched items accordingly
304         int watched = 0;
305         int unwatched = 0;
306         for (int i = 0; i < items.Size(); i++)
307         {
308           CFileItemPtr item = items[i];
309           watched += (int)item->GetProperty("watchedepisodes").asInteger();
310           unwatched += (int)item->GetProperty("unwatchedepisodes").asInteger();
311         }
312         pItem->SetProperty("totalepisodes", watched + unwatched);
313         pItem->SetProperty("numepisodes", watched + unwatched); // will be changed later to reflect watchmode setting
314         pItem->SetProperty("watchedepisodes", watched);
315         pItem->SetProperty("unwatchedepisodes", unwatched);
316         if (items.Size() && items[0]->GetVideoInfoTag())
317         {
318           *pItem->GetVideoInfoTag() = *items[0]->GetVideoInfoTag();
319           pItem->GetVideoInfoTag()->m_iSeason = -1;
320         }
321         pItem->GetVideoInfoTag()->m_strTitle = strLabel;
322         pItem->GetVideoInfoTag()->m_iEpisode = watched + unwatched;
323         pItem->GetVideoInfoTag()->m_playCount = (unwatched == 0) ? 1 : 0;
324         CVideoDatabase db;
325         if (db.Open())
326         {
327           pItem->GetVideoInfoTag()->m_iDbId = db.GetSeasonId(pItem->GetVideoInfoTag()->m_iIdShow, -1);
328           db.Close();
329         }
330         pItem->GetVideoInfoTag()->m_type = "season";
331       }
332       break;
333     default:
334       break;
335   }
336
337   if (pItem)
338   {
339     pItem->m_bIsFolder = true;
340     pItem->SetSpecialSort(g_advancedSettings.m_bVideoLibraryAllItemsOnBottom ? SortSpecialOnBottom : SortSpecialOnTop);
341     pItem->SetCanQueue(false);
342     items.Add(pItem);
343   }
344 }
345
346 bool CDirectoryNode::CanCache() const
347 {
348   //  Only cache the directorys in the root
349   //NODE_TYPE childnode=GetChildType();
350   //NODE_TYPE node=GetType();
351
352   // something should probably be cached
353   return true;//(childnode==NODE_TYPE_TITLE_MOVIES || childnode==NODE_TYPE_EPISODES || childnode == NODE_TYPE_SEASONS || childnode == NODE_TYPE_TITLE_TVSHOWS);
354 }