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 "TextureDatabase.h"
39 #include "video/VideoThumbLoader.h"
40 #include "music/MusicThumbLoader.h"
42 #include "pvr/channels/PVRChannel.h"
44 #include "epg/EpgContainer.h"
46 using namespace MUSIC_INFO;
47 using namespace JSONRPC;
48 using namespace XFILE;
50 bool CFileItemHandler::GetField(const std::string &field, const CVariant &info, const CFileItemPtr &item, CVariant &result, bool &fetchedArt, CThumbLoader *thumbLoader /* = NULL */)
52 if (result.isMember(field) && !result[field].empty())
55 // overwrite serialized values
58 if (field == "mimetype" && item->GetMimeType().empty())
60 item->FillInMimeType(false);
61 result[field] = item->GetMimeType();
66 // check for serialized values
67 if (info.isMember(field) && !info[field].isNull())
69 result[field] = info[field];
73 // check if the field requires special handling
78 if (field == "albumlabel")
80 result[field] = item->GetProperty("album_label");
83 if (item->HasProperty("album_" + field + "_array"))
85 result[field] = item->GetProperty("album_" + field + "_array");
88 if (item->HasProperty("album_" + field))
90 result[field] = item->GetProperty("album_" + field);
95 if (item->HasProperty("artist_" + field + "_array"))
97 result[field] = item->GetProperty("artist_" + field + "_array");
100 if (item->HasProperty("artist_" + field))
102 result[field] = item->GetProperty("artist_" + field);
108 if (thumbLoader != NULL && item->GetArt().size() <= 0 && !fetchedArt &&
109 ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1)))
111 thumbLoader->FillLibraryArt(*item);
115 CGUIListItem::ArtMap artMap = item->GetArt();
116 CVariant artObj(CVariant::VariantTypeObject);
117 for (CGUIListItem::ArtMap::const_iterator artIt = artMap.begin(); artIt != artMap.end(); ++artIt)
119 if (!artIt->second.empty())
120 artObj[artIt->first] = CTextureUtils::GetWrappedImageURL(artIt->second);
123 result["art"] = artObj;
127 if (field == "thumbnail")
129 if (thumbLoader != NULL && !item->HasArt("thumb") && !fetchedArt &&
130 ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1)))
132 thumbLoader->FillLibraryArt(*item);
135 else if (item->HasPictureInfoTag() && !item->HasArt("thumb"))
136 item->SetArt("thumb", CTextureUtils::GetWrappedThumbURL(item->GetPath()));
138 if (item->HasArt("thumb"))
139 result["thumbnail"] = CTextureUtils::GetWrappedImageURL(item->GetArt("thumb"));
141 result["thumbnail"] = "";
146 if (field == "fanart")
148 if (thumbLoader != NULL && !item->HasArt("fanart") && !fetchedArt &&
149 ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1)))
151 thumbLoader->FillLibraryArt(*item);
155 if (item->HasArt("fanart"))
156 result["fanart"] = CTextureUtils::GetWrappedImageURL(item->GetArt("fanart"));
158 result["fanart"] = "";
163 if (item->HasVideoInfoTag() && item->GetVideoContentType() == VIDEODB_CONTENT_TVSHOWS)
165 if (item->GetVideoInfoTag()->m_iSeason < 0 && field == "season")
167 result[field] = (int)item->GetProperty("totalseasons").asInteger();
170 if (field == "watchedepisodes")
172 result[field] = (int)item->GetProperty("watchedepisodes").asInteger();
177 if (field == "lastmodified" && item->m_dateTime.IsValid())
179 result[field] = item->m_dateTime.GetAsLocalizedDateTime();
183 if (item->HasProperty(field))
185 result[field] = item->GetProperty(field);
193 void CFileItemHandler::FillDetails(const ISerializable *info, const CFileItemPtr &item, std::set<std::string> &fields, CVariant &result, CThumbLoader *thumbLoader /* = NULL */)
195 if (info == NULL || fields.size() == 0)
198 CVariant serialization;
199 info->Serialize(serialization);
201 bool fetchedArt = false;
203 std::set<std::string> originalFields = fields;
205 for (std::set<std::string>::const_iterator fieldIt = originalFields.begin(); fieldIt != originalFields.end(); ++fieldIt)
207 if (GetField(*fieldIt, serialization, item, result, fetchedArt, thumbLoader) && result.isMember(*fieldIt) && !result[*fieldIt].empty())
208 fields.erase(*fieldIt);
212 void CFileItemHandler::HandleFileItemList(const char *ID, bool allowFile, const char *resultname, CFileItemList &items, const CVariant ¶meterObject, CVariant &result, bool sortLimit /* = true */)
214 HandleFileItemList(ID, allowFile, resultname, items, parameterObject, result, items.Size(), sortLimit);
217 void CFileItemHandler::HandleFileItemList(const char *ID, bool allowFile, const char *resultname, CFileItemList &items, const CVariant ¶meterObject, CVariant &result, int size, bool sortLimit /* = true */)
220 HandleLimits(parameterObject, result, size, start, end);
223 Sort(items, parameterObject);
230 CThumbLoader *thumbLoader = NULL;
233 if (items.Get(start)->HasVideoInfoTag())
234 thumbLoader = new CVideoThumbLoader();
235 else if (items.Get(start)->HasMusicInfoTag())
236 thumbLoader = new CMusicThumbLoader();
238 if (thumbLoader != NULL)
239 thumbLoader->OnLoaderStart();
242 std::set<std::string> fields;
243 if (parameterObject.isMember("properties") && parameterObject["properties"].isArray())
245 for (CVariant::const_iterator_array field = parameterObject["properties"].begin_array(); field != parameterObject["properties"].end_array(); field++)
246 fields.insert(field->asString());
249 for (int i = start; i < end; i++)
251 CFileItemPtr item = items.Get(i);
252 HandleFileItem(ID, allowFile, resultname, item, parameterObject, fields, result, true, thumbLoader);
258 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 */)
260 std::set<std::string> fields;
261 if (parameterObject.isMember("properties") && parameterObject["properties"].isArray())
263 for (CVariant::const_iterator_array field = parameterObject["properties"].begin_array(); field != parameterObject["properties"].end_array(); field++)
264 fields.insert(field->asString());
267 HandleFileItem(ID, allowFile, resultname, item, parameterObject, fields, result, append, thumbLoader);
270 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 */)
273 std::set<std::string> fields(validFields.begin(), validFields.end());
277 std::set<std::string>::const_iterator fileField = fields.find("file");
278 if (fileField != fields.end())
282 if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->GetPath().IsEmpty())
283 object["file"] = item->GetVideoInfoTag()->GetPath().c_str();
284 if (item->HasMusicInfoTag() && !item->GetMusicInfoTag()->GetURL().IsEmpty())
285 object["file"] = item->GetMusicInfoTag()->GetURL().c_str();
287 if (!object.isMember("file"))
288 object["file"] = item->GetPath().c_str();
290 fields.erase(fileField);
295 if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag()->ChannelID() > 0)
296 object[ID] = item->GetPVRChannelInfoTag()->ChannelID();
297 else if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->UniqueBroadcastID() > 0)
298 object[ID] = item->GetEPGInfoTag()->UniqueBroadcastID();
299 else if (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > 0)
300 object[ID] = (int)item->GetMusicInfoTag()->GetDatabaseId();
301 else if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > 0)
302 object[ID] = item->GetVideoInfoTag()->m_iDbId;
304 if (stricmp(ID, "id") == 0)
306 if (item->HasPVRChannelInfoTag())
307 object["type"] = "channel";
308 else if (item->HasMusicInfoTag())
310 std::string type = item->GetMusicInfoTag()->GetType();
311 if (type == "album" || type == "song" || type == "artist")
312 object["type"] = type;
314 object["type"] = "song";
316 else if (item->HasVideoInfoTag() && !item->GetVideoInfoTag()->m_type.empty())
318 std::string type = item->GetVideoInfoTag()->m_type;
319 if (type == "movie" || type == "tvshow" || type == "episode" || type == "musicvideo")
320 object["type"] = type;
322 else if (item->HasPictureInfoTag())
323 object["type"] = "picture";
325 if (!object.isMember("type"))
326 object["type"] = "unknown";
328 if (fields.find("filetype") != fields.end())
330 if (item->m_bIsFolder)
331 object["filetype"] = "directory";
333 object["filetype"] = "file";
338 bool deleteThumbloader = false;
339 if (thumbLoader == NULL)
341 if (item->HasVideoInfoTag())
342 thumbLoader = new CVideoThumbLoader();
343 else if (item->HasMusicInfoTag())
344 thumbLoader = new CMusicThumbLoader();
346 if (thumbLoader != NULL)
348 deleteThumbloader = true;
349 thumbLoader->OnLoaderStart();
353 if (item->HasPVRChannelInfoTag())
354 FillDetails(item->GetPVRChannelInfoTag(), item, fields, object, thumbLoader);
355 if (item->HasEPGInfoTag())
356 FillDetails(item->GetEPGInfoTag(), item, fields, object, thumbLoader);
357 if (item->HasVideoInfoTag())
358 FillDetails(item->GetVideoInfoTag(), item, fields, object, thumbLoader);
359 if (item->HasMusicInfoTag())
360 FillDetails(item->GetMusicInfoTag(), item, fields, object, thumbLoader);
361 if (item->HasPictureInfoTag())
362 FillDetails(item->GetPictureInfoTag(), item, fields, object, thumbLoader);
364 FillDetails(item.get(), item, fields, object, thumbLoader);
366 if (deleteThumbloader)
369 object["label"] = item->GetLabel().c_str();
372 object = CVariant(CVariant::VariantTypeNull);
377 result[resultname].append(object);
379 result[resultname] = object;
383 bool CFileItemHandler::FillFileItemList(const CVariant ¶meterObject, CFileItemList &list)
385 CAudioLibrary::FillFileItemList(parameterObject, list);
386 CVideoLibrary::FillFileItemList(parameterObject, list);
387 CFileOperations::FillFileItemList(parameterObject, list);
389 CStdString file = parameterObject["file"].asString();
390 if (!file.empty() && (URIUtils::IsURL(file) || (CFile::Exists(file) && !CDirectory::Exists(file))))
393 for (int index = 0; index < list.Size(); index++)
395 if (list[index]->GetPath() == file)
404 CFileItemPtr item = CFileItemPtr(new CFileItem(file, false));
405 if (item->IsPicture())
407 CPictureInfoTag picture;
408 picture.Load(item->GetPath());
409 *item->GetPictureInfoTag() = picture;
411 if (item->GetLabel().empty())
413 item->SetLabel(CUtil::GetTitleFromPath(file, false));
414 if (item->GetLabel().empty())
415 item->SetLabel(URIUtils::GetFileName(file));
421 return (list.Size() > 0);
424 void CFileItemHandler::Sort(CFileItemList &items, const CVariant ¶meterObject)
426 SortDescription sorting;
427 if (!ParseSorting(parameterObject, sorting.sortBy, sorting.sortOrder, sorting.sortAttributes))