2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
24 #include "FileItemHandler.h"
25 #include "PlaylistOperations.h"
26 #include "AudioLibrary.h"
27 #include "VideoLibrary.h"
28 #include "FileOperations.h"
29 #include "utils/URIUtils.h"
30 #include "utils/ISerializable.h"
31 #include "utils/Variant.h"
32 #include "video/VideoInfoTag.h"
33 #include "music/tags/MusicInfoTag.h"
34 #include "pictures/PictureInfoTag.h"
35 #include "video/VideoDatabase.h"
36 #include "filesystem/Directory.h"
37 #include "filesystem/File.h"
38 #include "TextureCache.h"
39 #include "video/VideoThumbLoader.h"
40 #include "music/MusicThumbLoader.h"
42 #include "pvr/channels/PVRChannel.h"
44 using namespace MUSIC_INFO;
45 using namespace JSONRPC;
46 using namespace XFILE;
48 bool CFileItemHandler::GetField(const std::string &field, const CVariant &info, const CFileItemPtr &item, CVariant &result, bool &fetchedArt, CThumbLoader *thumbLoader /* = NULL */)
50 if (result.isMember(field) && !result[field].empty())
53 if (info.isMember(field) && !info[field].isNull())
55 result[field] = info[field];
63 if (field == "albumlabel")
65 result[field] = item->GetProperty("album_label");
68 if (item->HasProperty("album_" + field + "_array"))
70 result[field] = item->GetProperty("album_" + field + "_array");
73 if (item->HasProperty("album_" + field))
75 result[field] = item->GetProperty("album_" + field);
80 if (item->HasProperty("artist_" + field + "_array"))
82 result[field] = item->GetProperty("artist_" + field + "_array");
85 if (item->HasProperty("artist_" + field))
87 result[field] = item->GetProperty("artist_" + field);
93 if (thumbLoader != NULL && item->GetArt().size() <= 0 && !fetchedArt &&
94 ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1)))
96 thumbLoader->FillLibraryArt(*item);
100 CGUIListItem::ArtMap artMap = item->GetArt();
101 CVariant artObj(CVariant::VariantTypeObject);
102 for (CGUIListItem::ArtMap::const_iterator artIt = artMap.begin(); artIt != artMap.end(); artIt++)
104 if (!artIt->second.empty())
105 artObj[artIt->first] = CTextureCache::GetWrappedImageURL(artIt->second);
108 result["art"] = artObj;
112 if (field == "thumbnail")
114 if (thumbLoader != NULL && !item->HasArt("thumb") && !fetchedArt &&
115 ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1)))
117 thumbLoader->FillLibraryArt(*item);
120 else if (item->HasPictureInfoTag() && !item->HasArt("thumb"))
121 item->SetArt("thumb", CTextureCache::GetWrappedThumbURL(item->GetPath()));
123 if (item->HasArt("thumb"))
124 result["thumbnail"] = CTextureCache::GetWrappedImageURL(item->GetArt("thumb"));
126 result["thumbnail"] = "";
131 if (field == "fanart")
133 if (thumbLoader != NULL && !item->HasArt("fanart") && !fetchedArt &&
134 ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1)))
136 thumbLoader->FillLibraryArt(*item);
140 if (item->HasArt("fanart"))
141 result["fanart"] = CTextureCache::GetWrappedImageURL(item->GetArt("fanart"));
143 result["fanart"] = "";
148 if (item->HasVideoInfoTag() && item->GetVideoContentType() == VIDEODB_CONTENT_TVSHOWS)
150 if (item->GetVideoInfoTag()->m_iSeason < 0 && field == "season")
152 result[field] = (int)item->GetProperty("totalseasons").asInteger();
155 if (field == "watchedepisodes")
157 result[field] = (int)item->GetProperty("watchedepisodes").asInteger();
162 if (field == "lastmodified" && item->m_dateTime.IsValid())
164 result[field] = item->m_dateTime.GetAsLocalizedDateTime();
168 if (item->HasProperty(field))
170 result[field] = item->GetProperty(field);
178 void CFileItemHandler::FillDetails(const ISerializable *info, const CFileItemPtr &item, std::set<std::string> &fields, CVariant &result, CThumbLoader *thumbLoader /* = NULL */)
180 if (info == NULL || fields.size() == 0)
183 CVariant serialization;
184 info->Serialize(serialization);
186 bool fetchedArt = false;
188 std::set<std::string> originalFields = fields;
190 for (std::set<std::string>::const_iterator fieldIt = originalFields.begin(); fieldIt != originalFields.end(); fieldIt++)
192 if (GetField(*fieldIt, serialization, item, result, fetchedArt, thumbLoader) && result.isMember(*fieldIt) && !result[*fieldIt].empty())
193 fields.erase(*fieldIt);
197 void CFileItemHandler::HandleFileItemList(const char *ID, bool allowFile, const char *resultname, CFileItemList &items, const CVariant ¶meterObject, CVariant &result, bool sortLimit /* = true */)
199 HandleFileItemList(ID, allowFile, resultname, items, parameterObject, result, items.Size(), sortLimit);
202 void CFileItemHandler::HandleFileItemList(const char *ID, bool allowFile, const char *resultname, CFileItemList &items, const CVariant ¶meterObject, CVariant &result, int size, bool sortLimit /* = true */)
205 HandleLimits(parameterObject, result, size, start, end);
208 Sort(items, parameterObject);
215 CThumbLoader *thumbLoader = NULL;
218 if (items.Get(start)->HasVideoInfoTag())
219 thumbLoader = new CVideoThumbLoader();
220 else if (items.Get(start)->HasMusicInfoTag())
221 thumbLoader = new CMusicThumbLoader();
223 if (thumbLoader != NULL)
224 thumbLoader->Initialize();
227 std::set<std::string> fields;
228 if (parameterObject.isMember("properties") && parameterObject["properties"].isArray())
230 for (CVariant::const_iterator_array field = parameterObject["properties"].begin_array(); field != parameterObject["properties"].end_array(); field++)
231 fields.insert(field->asString());
234 for (int i = start; i < end; i++)
236 CFileItemPtr item = items.Get(i);
237 HandleFileItem(ID, allowFile, resultname, item, parameterObject, fields, result, true, thumbLoader);
243 void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char *resultname, CFileItemPtr item, const CVariant ¶meterObject, const CVariant &validFields, CVariant &result, bool append /* = true */, CThumbLoader *thumbLoader /* = NULL */)
245 std::set<std::string> fields;
246 if (parameterObject.isMember("properties") && parameterObject["properties"].isArray())
248 for (CVariant::const_iterator_array field = parameterObject["properties"].begin_array(); field != parameterObject["properties"].end_array(); field++)
249 fields.insert(field->asString());
252 HandleFileItem(ID, allowFile, resultname, item, parameterObject, fields, result, append, thumbLoader);
255 void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char *resultname, CFileItemPtr item, const CVariant ¶meterObject, const std::set<std::string> &validFields, CVariant &result, bool append /* = true */, CThumbLoader *thumbLoader /* = NULL */)
258 std::set<std::string> fields(validFields.begin(), validFields.end());
262 std::set<std::string>::const_iterator fileField = fields.find("file");
263 if (fileField != fields.end())
267 if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->GetPath().IsEmpty())
268 object["file"] = item->GetVideoInfoTag()->GetPath().c_str();
269 if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetURL().IsEmpty())
270 object["file"] = item->GetMusicInfoTag()->GetURL().c_str();
272 if (!object.isMember("file"))
273 object["file"] = item->GetPath().c_str();
275 fields.erase(fileField);
280 if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag()->ChannelID() > 0)
281 object[ID] = item->GetPVRChannelInfoTag()->ChannelID();
282 else if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > 0)
283 object[ID] = (int)item->GetMusicInfoTag()->GetDatabaseId();
284 else if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > 0)
285 object[ID] = item->GetVideoInfoTag()->m_iDbId;
287 if (stricmp(ID, "id") == 0)
289 if (item->HasPVRChannelInfoTag())
290 object["type"] = "channel";
291 else if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetType().empty())
293 std::string type = item->GetMusicInfoTag()->GetType();
294 if (type == "album" || type == "song")
295 object["type"] = type;
297 else if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_type.empty())
299 std::string type = item->GetVideoInfoTag()->m_type;
300 if (type == "movie" || type == "tvshow" || type == "episode" || type == "musicvideo")
301 object["type"] = type;
303 else if (item->HasPictureInfoTag())
304 object["type"] = "picture";
306 if (!object.isMember("type"))
307 object["type"] = "unknown";
309 if (item->m_bIsFolder)
310 object["filetype"] = "directory";
312 object["filetype"] = "file";
316 bool deleteThumbloader = false;
317 if (thumbLoader == NULL)
319 if (item->HasVideoInfoTag())
320 thumbLoader = new CVideoThumbLoader();
321 else if (item->HasMusicInfoTag())
322 thumbLoader = new CMusicThumbLoader();
324 if (thumbLoader != NULL)
326 deleteThumbloader = true;
327 thumbLoader->Initialize();
331 if (item->HasPVRChannelInfoTag())
332 FillDetails(item->GetPVRChannelInfoTag(), item, fields, object, thumbLoader);
333 if (item->HasVideoInfoTag())
334 FillDetails(item->GetVideoInfoTag(), item, fields, object, thumbLoader);
335 if (item->HasMusicInfoTag())
336 FillDetails(item->GetMusicInfoTag(), item, fields, object, thumbLoader);
337 if (item->HasPictureInfoTag())
338 FillDetails(item->GetPictureInfoTag(), item, fields, object, thumbLoader);
340 FillDetails(item.get(), item, fields, object, thumbLoader);
342 if (deleteThumbloader)
345 object["label"] = item->GetLabel().c_str();
348 object = CVariant(CVariant::VariantTypeNull);
353 result[resultname].append(object);
355 result[resultname] = object;
359 bool CFileItemHandler::FillFileItemList(const CVariant ¶meterObject, CFileItemList &list)
361 CAudioLibrary::FillFileItemList(parameterObject, list);
362 CVideoLibrary::FillFileItemList(parameterObject, list);
363 CFileOperations::FillFileItemList(parameterObject, list);
365 CStdString file = parameterObject["file"].asString();
366 if (!file.empty() && (URIUtils::IsURL(file) || (CFile::Exists(file) && !CDirectory::Exists(file))))
369 for (int index = 0; index < list.Size(); index++)
371 if (list[index]->GetPath() == file)
380 CFileItemPtr item = CFileItemPtr(new CFileItem(file, false));
381 if (item->IsPicture())
383 CPictureInfoTag picture;
384 picture.Load(item->GetPath());
385 *item->GetPictureInfoTag() = picture;
387 if (item->GetLabel().IsEmpty())
388 item->SetLabel(CUtil::GetTitleFromPath(file, false));
393 return (list.Size() > 0);
396 void CFileItemHandler::Sort(CFileItemList &items, const CVariant ¶meterObject)
398 SortDescription sorting;
399 if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes))