ControlHandler.cs 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379
  1. using MediaBrowser.Common.Extensions;
  2. using MediaBrowser.Controller.Channels;
  3. using MediaBrowser.Controller.Configuration;
  4. using MediaBrowser.Controller.Drawing;
  5. using MediaBrowser.Controller.Entities;
  6. using MediaBrowser.Controller.Entities.Movies;
  7. using MediaBrowser.Controller.Entities.TV;
  8. using MediaBrowser.Controller.Library;
  9. using Emby.Dlna.Didl;
  10. using Emby.Dlna.Server;
  11. using Emby.Dlna.Service;
  12. using MediaBrowser.Model.Configuration;
  13. using MediaBrowser.Model.Dlna;
  14. using MediaBrowser.Model.Entities;
  15. using MediaBrowser.Model.Logging;
  16. using MediaBrowser.Model.Querying;
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Globalization;
  20. using System.IO;
  21. using System.Linq;
  22. using System.Text;
  23. using System.Threading;
  24. using System.Threading.Tasks;
  25. using System.Xml;
  26. using MediaBrowser.Controller.Dto;
  27. using MediaBrowser.Controller.Entities.Audio;
  28. using MediaBrowser.Controller.MediaEncoding;
  29. using MediaBrowser.Controller.Playlists;
  30. using MediaBrowser.Controller.TV;
  31. using MediaBrowser.Model.Globalization;
  32. using MediaBrowser.Model.Xml;
  33. using MediaBrowser.Model.Extensions;
  34. namespace Emby.Dlna.ContentDirectory
  35. {
  36. public class ControlHandler : BaseControlHandler
  37. {
  38. private readonly ILibraryManager _libraryManager;
  39. private readonly IChannelManager _channelManager;
  40. private readonly IUserDataManager _userDataManager;
  41. private readonly IServerConfigurationManager _config;
  42. private readonly User _user;
  43. private readonly IUserViewManager _userViewManager;
  44. private readonly ITVSeriesManager _tvSeriesManager;
  45. private const string NS_DC = "http://purl.org/dc/elements/1.1/";
  46. private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
  47. private const string NS_DLNA = "urn:schemas-dlna-org:metadata-1-0/";
  48. private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
  49. private readonly int _systemUpdateId;
  50. private readonly CultureInfo _usCulture = new CultureInfo("en-US");
  51. private readonly DidlBuilder _didlBuilder;
  52. private readonly DeviceProfile _profile;
  53. public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, IMediaEncoder mediaEncoder, IXmlReaderSettingsFactory xmlReaderSettingsFactory, ITVSeriesManager tvSeriesManager)
  54. : base(config, logger, xmlReaderSettingsFactory)
  55. {
  56. _libraryManager = libraryManager;
  57. _userDataManager = userDataManager;
  58. _user = user;
  59. _systemUpdateId = systemUpdateId;
  60. _channelManager = channelManager;
  61. _userViewManager = userViewManager;
  62. _tvSeriesManager = tvSeriesManager;
  63. _profile = profile;
  64. _config = config;
  65. _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager, mediaEncoder);
  66. }
  67. protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, IDictionary<string, string> methodParams)
  68. {
  69. var deviceId = "test";
  70. var user = _user;
  71. if (string.Equals(methodName, "GetSearchCapabilities", StringComparison.OrdinalIgnoreCase))
  72. return HandleGetSearchCapabilities();
  73. if (string.Equals(methodName, "GetSortCapabilities", StringComparison.OrdinalIgnoreCase))
  74. return HandleGetSortCapabilities();
  75. if (string.Equals(methodName, "GetSortExtensionCapabilities", StringComparison.OrdinalIgnoreCase))
  76. return HandleGetSortExtensionCapabilities();
  77. if (string.Equals(methodName, "GetSystemUpdateID", StringComparison.OrdinalIgnoreCase))
  78. return HandleGetSystemUpdateID();
  79. if (string.Equals(methodName, "Browse", StringComparison.OrdinalIgnoreCase))
  80. return HandleBrowse(methodParams, user, deviceId);
  81. if (string.Equals(methodName, "X_GetFeatureList", StringComparison.OrdinalIgnoreCase))
  82. return HandleXGetFeatureList();
  83. if (string.Equals(methodName, "GetFeatureList", StringComparison.OrdinalIgnoreCase))
  84. return HandleGetFeatureList();
  85. if (string.Equals(methodName, "X_SetBookmark", StringComparison.OrdinalIgnoreCase))
  86. return HandleXSetBookmark(methodParams, user);
  87. if (string.Equals(methodName, "Search", StringComparison.OrdinalIgnoreCase))
  88. return HandleSearch(methodParams, user, deviceId);
  89. if (string.Equals(methodName, "X_BrowseByLetter", StringComparison.OrdinalIgnoreCase))
  90. return HandleX_BrowseByLetter(methodParams, user, deviceId);
  91. throw new ResourceNotFoundException("Unexpected control request name: " + methodName);
  92. }
  93. private IEnumerable<KeyValuePair<string, string>> HandleXSetBookmark(IDictionary<string, string> sparams, User user)
  94. {
  95. var id = sparams["ObjectID"];
  96. var serverItem = GetItemFromObjectId(id, user);
  97. var item = serverItem.Item;
  98. var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
  99. var userdata = _userDataManager.GetUserData(user, item);
  100. userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;
  101. _userDataManager.SaveUserData(user.Id, item, userdata, UserDataSaveReason.TogglePlayed,
  102. CancellationToken.None);
  103. return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
  104. }
  105. private IEnumerable<KeyValuePair<string, string>> HandleGetSearchCapabilities()
  106. {
  107. return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
  108. {
  109. { "SearchCaps", "res@resolution,res@size,res@duration,dc:title,dc:creator,upnp:actor,upnp:artist,upnp:genre,upnp:album,dc:date,upnp:class,@id,@refID,@protocolInfo,upnp:author,dc:description,pv:avKeywords" }
  110. };
  111. }
  112. private IEnumerable<KeyValuePair<string, string>> HandleGetSortCapabilities()
  113. {
  114. return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
  115. {
  116. { "SortCaps", "res@duration,res@size,res@bitrate,dc:date,dc:title,dc:size,upnp:album,upnp:artist,upnp:albumArtist,upnp:episodeNumber,upnp:genre,upnp:originalTrackNumber,upnp:rating" }
  117. };
  118. }
  119. private IEnumerable<KeyValuePair<string, string>> HandleGetSortExtensionCapabilities()
  120. {
  121. return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
  122. {
  123. { "SortExtensionCaps", "res@duration,res@size,res@bitrate,dc:date,dc:title,dc:size,upnp:album,upnp:artist,upnp:albumArtist,upnp:episodeNumber,upnp:genre,upnp:originalTrackNumber,upnp:rating" }
  124. };
  125. }
  126. private IEnumerable<KeyValuePair<string, string>> HandleGetSystemUpdateID()
  127. {
  128. var headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
  129. headers.Add("Id", _systemUpdateId.ToString(_usCulture));
  130. return headers;
  131. }
  132. private IEnumerable<KeyValuePair<string, string>> HandleGetFeatureList()
  133. {
  134. return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
  135. {
  136. { "FeatureList", GetFeatureListXml() }
  137. };
  138. }
  139. private IEnumerable<KeyValuePair<string, string>> HandleXGetFeatureList()
  140. {
  141. return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
  142. {
  143. { "FeatureList", GetFeatureListXml() }
  144. };
  145. }
  146. private string GetFeatureListXml()
  147. {
  148. var builder = new StringBuilder();
  149. builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  150. builder.Append("<Features xmlns=\"urn:schemas-upnp-org:av:avs\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:schemas-upnp-org:av:avs http://www.upnp.org/schemas/av/avs.xsd\">");
  151. builder.Append("<Feature name=\"samsung.com_BASICVIEW\" version=\"1\">");
  152. builder.Append("<container id=\"I\" type=\"object.item.imageItem\"/>");
  153. builder.Append("<container id=\"A\" type=\"object.item.audioItem\"/>");
  154. builder.Append("<container id=\"V\" type=\"object.item.videoItem\"/>");
  155. builder.Append("</Feature>");
  156. builder.Append("</Features>");
  157. return builder.ToString();
  158. }
  159. public string GetValueOrDefault(IDictionary<string, string> sparams, string key, string defaultValue)
  160. {
  161. string val;
  162. if (sparams.TryGetValue(key, out val))
  163. {
  164. return val;
  165. }
  166. return defaultValue;
  167. }
  168. private IEnumerable<KeyValuePair<string, string>> HandleBrowse(IDictionary<string, string> sparams, User user, string deviceId)
  169. {
  170. var id = sparams["ObjectID"];
  171. var flag = sparams["BrowseFlag"];
  172. var filter = new Filter(GetValueOrDefault(sparams, "Filter", "*"));
  173. var sortCriteria = new SortCriteria(GetValueOrDefault(sparams, "SortCriteria", ""));
  174. var provided = 0;
  175. // Default to null instead of 0
  176. // Upnp inspector sends 0 as requestedCount when it wants everything
  177. int? requestedCount = null;
  178. int? start = 0;
  179. int requestedVal;
  180. if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
  181. {
  182. requestedCount = requestedVal;
  183. }
  184. int startVal;
  185. if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
  186. {
  187. start = startVal;
  188. }
  189. var settings = new XmlWriterSettings
  190. {
  191. Encoding = Encoding.UTF8,
  192. CloseOutput = false,
  193. OmitXmlDeclaration = true,
  194. ConformanceLevel = ConformanceLevel.Fragment
  195. };
  196. StringWriter builder = new StringWriterWithEncoding(Encoding.UTF8);
  197. int totalCount;
  198. using (XmlWriter writer = XmlWriter.Create(builder, settings))
  199. {
  200. //writer.WriteStartDocument();
  201. writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL);
  202. writer.WriteAttributeString("xmlns", "dc", null, NS_DC);
  203. writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA);
  204. writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP);
  205. //didl.SetAttribute("xmlns:sec", NS_SEC);
  206. DidlBuilder.WriteXmlRootAttributes(_profile, writer);
  207. var serverItem = GetItemFromObjectId(id, user);
  208. var item = serverItem.Item;
  209. if (string.Equals(flag, "BrowseMetadata"))
  210. {
  211. totalCount = 1;
  212. if (item.IsDisplayedAsFolder || serverItem.StubType.HasValue)
  213. {
  214. var childrenResult = (GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount));
  215. _didlBuilder.WriteFolderElement(writer, item, serverItem.StubType, null, childrenResult.TotalRecordCount, filter, id);
  216. }
  217. else
  218. {
  219. _didlBuilder.WriteItemElement(_config.GetDlnaConfiguration(), writer, item, user, null, null, deviceId, filter);
  220. }
  221. provided++;
  222. }
  223. else
  224. {
  225. var childrenResult = (GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount));
  226. totalCount = childrenResult.TotalRecordCount;
  227. provided = childrenResult.Items.Length;
  228. foreach (var i in childrenResult.Items)
  229. {
  230. var childItem = i.Item;
  231. var displayStubType = i.StubType;
  232. if (childItem.IsDisplayedAsFolder || displayStubType.HasValue)
  233. {
  234. var childCount = (GetUserItems(childItem, displayStubType, user, sortCriteria, null, 0))
  235. .TotalRecordCount;
  236. _didlBuilder.WriteFolderElement(writer, childItem, displayStubType, item, childCount, filter);
  237. }
  238. else
  239. {
  240. _didlBuilder.WriteItemElement(_config.GetDlnaConfiguration(), writer, childItem, user, item, serverItem.StubType, deviceId, filter);
  241. }
  242. }
  243. }
  244. writer.WriteFullEndElement();
  245. //writer.WriteEndDocument();
  246. }
  247. var resXML = builder.ToString();
  248. return new List<KeyValuePair<string, string>>
  249. {
  250. new KeyValuePair<string,string>("Result", resXML),
  251. new KeyValuePair<string,string>("NumberReturned", provided.ToString(_usCulture)),
  252. new KeyValuePair<string,string>("TotalMatches", totalCount.ToString(_usCulture)),
  253. new KeyValuePair<string,string>("UpdateID", _systemUpdateId.ToString(_usCulture))
  254. };
  255. }
  256. private IEnumerable<KeyValuePair<string, string>> HandleX_BrowseByLetter(IDictionary<string, string> sparams, User user, string deviceId)
  257. {
  258. // TODO: Implement this method
  259. return HandleSearch(sparams, user, deviceId);
  260. }
  261. private IEnumerable<KeyValuePair<string, string>> HandleSearch(IDictionary<string, string> sparams, User user, string deviceId)
  262. {
  263. var searchCriteria = new SearchCriteria(GetValueOrDefault(sparams, "SearchCriteria", ""));
  264. var sortCriteria = new SortCriteria(GetValueOrDefault(sparams, "SortCriteria", ""));
  265. var filter = new Filter(GetValueOrDefault(sparams, "Filter", "*"));
  266. // sort example: dc:title, dc:date
  267. // Default to null instead of 0
  268. // Upnp inspector sends 0 as requestedCount when it wants everything
  269. int? requestedCount = null;
  270. int? start = 0;
  271. int requestedVal;
  272. if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
  273. {
  274. requestedCount = requestedVal;
  275. }
  276. int startVal;
  277. if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
  278. {
  279. start = startVal;
  280. }
  281. var settings = new XmlWriterSettings
  282. {
  283. Encoding = Encoding.UTF8,
  284. CloseOutput = false,
  285. OmitXmlDeclaration = true,
  286. ConformanceLevel = ConformanceLevel.Fragment
  287. };
  288. StringWriter builder = new StringWriterWithEncoding(Encoding.UTF8);
  289. int totalCount = 0;
  290. int provided = 0;
  291. using (XmlWriter writer = XmlWriter.Create(builder, settings))
  292. {
  293. //writer.WriteStartDocument();
  294. writer.WriteStartElement(string.Empty, "DIDL-Lite", NS_DIDL);
  295. writer.WriteAttributeString("xmlns", "dc", null, NS_DC);
  296. writer.WriteAttributeString("xmlns", "dlna", null, NS_DLNA);
  297. writer.WriteAttributeString("xmlns", "upnp", null, NS_UPNP);
  298. //didl.SetAttribute("xmlns:sec", NS_SEC);
  299. DidlBuilder.WriteXmlRootAttributes(_profile, writer);
  300. var serverItem = GetItemFromObjectId(sparams["ContainerID"], user);
  301. var item = serverItem.Item;
  302. var childrenResult = (GetChildrenSorted(item, user, searchCriteria, sortCriteria, start, requestedCount));
  303. totalCount = childrenResult.TotalRecordCount;
  304. provided = childrenResult.Items.Length;
  305. foreach (var i in childrenResult.Items)
  306. {
  307. if (i.IsDisplayedAsFolder)
  308. {
  309. var childCount = (GetChildrenSorted(i, user, searchCriteria, sortCriteria, null, 0))
  310. .TotalRecordCount;
  311. _didlBuilder.WriteFolderElement(writer, i, null, item, childCount, filter);
  312. }
  313. else
  314. {
  315. _didlBuilder.WriteItemElement(_config.GetDlnaConfiguration(), writer, i, user, item, serverItem.StubType, deviceId, filter);
  316. }
  317. }
  318. writer.WriteFullEndElement();
  319. //writer.WriteEndDocument();
  320. }
  321. var resXML = builder.ToString();
  322. return new List<KeyValuePair<string, string>>
  323. {
  324. new KeyValuePair<string,string>("Result", resXML),
  325. new KeyValuePair<string,string>("NumberReturned", provided.ToString(_usCulture)),
  326. new KeyValuePair<string,string>("TotalMatches", totalCount.ToString(_usCulture)),
  327. new KeyValuePair<string,string>("UpdateID", _systemUpdateId.ToString(_usCulture))
  328. };
  329. }
  330. private QueryResult<BaseItem> GetChildrenSorted(BaseItem item, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
  331. {
  332. var folder = (Folder)item;
  333. var sortOrders = new List<string>();
  334. if (!folder.IsPreSorted)
  335. {
  336. sortOrders.Add(ItemSortBy.SortName);
  337. }
  338. var mediaTypes = new List<string>();
  339. bool? isFolder = null;
  340. if (search.SearchType == SearchType.Audio)
  341. {
  342. mediaTypes.Add(MediaType.Audio);
  343. isFolder = false;
  344. }
  345. else if (search.SearchType == SearchType.Video)
  346. {
  347. mediaTypes.Add(MediaType.Video);
  348. isFolder = false;
  349. }
  350. else if (search.SearchType == SearchType.Image)
  351. {
  352. mediaTypes.Add(MediaType.Photo);
  353. isFolder = false;
  354. }
  355. else if (search.SearchType == SearchType.Playlist)
  356. {
  357. //items = items.OfType<Playlist>();
  358. isFolder = true;
  359. }
  360. else if (search.SearchType == SearchType.MusicAlbum)
  361. {
  362. //items = items.OfType<MusicAlbum>();
  363. isFolder = true;
  364. }
  365. return folder.GetItems(new InternalItemsQuery
  366. {
  367. Limit = limit,
  368. StartIndex = startIndex,
  369. SortBy = sortOrders.ToArray(sortOrders.Count),
  370. SortOrder = sort.SortOrder,
  371. User = user,
  372. Recursive = true,
  373. IsMissing = false,
  374. ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
  375. IsFolder = isFolder,
  376. MediaTypes = mediaTypes.ToArray(mediaTypes.Count),
  377. DtoOptions = GetDtoOptions()
  378. });
  379. }
  380. private DtoOptions GetDtoOptions()
  381. {
  382. return new DtoOptions(true);
  383. }
  384. private QueryResult<ServerItem> GetUserItems(BaseItem item, StubType? stubType, User user, SortCriteria sort, int? startIndex, int? limit)
  385. {
  386. if (item is MusicGenre)
  387. {
  388. return GetMusicGenreItems(item, null, user, sort, startIndex, limit);
  389. }
  390. if (item is MusicArtist)
  391. {
  392. return GetMusicArtistItems(item, null, user, sort, startIndex, limit);
  393. }
  394. if (item is Genre)
  395. {
  396. return GetGenreItems(item, null, user, sort, startIndex, limit);
  397. }
  398. var collectionFolder = item as ICollectionFolder;
  399. if (collectionFolder != null && string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
  400. {
  401. return GetMusicFolders(item, user, stubType, sort, startIndex, limit);
  402. }
  403. if (collectionFolder != null && string.Equals(CollectionType.Movies, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
  404. {
  405. return GetMovieFolders(item, user, stubType, sort, startIndex, limit);
  406. }
  407. if (collectionFolder != null && string.Equals(CollectionType.TvShows, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
  408. {
  409. return GetTvFolders(item, user, stubType, sort, startIndex, limit);
  410. }
  411. if (stubType.HasValue)
  412. {
  413. if (stubType.Value == StubType.People)
  414. {
  415. var items = _libraryManager.GetPeopleItems(new InternalPeopleQuery
  416. {
  417. ItemId = item.Id
  418. });
  419. var result = new QueryResult<ServerItem>
  420. {
  421. Items = items.Select(i => new ServerItem(i)).ToArray(items.Count),
  422. TotalRecordCount = items.Count
  423. };
  424. return ApplyPaging(result, startIndex, limit);
  425. }
  426. var person = item as Person;
  427. if (person != null)
  428. {
  429. return GetItemsFromPerson(person, user, startIndex, limit);
  430. }
  431. return ApplyPaging(new QueryResult<ServerItem>(), startIndex, limit);
  432. }
  433. var folder = (Folder)item;
  434. var query = new InternalItemsQuery
  435. {
  436. Limit = limit,
  437. StartIndex = startIndex,
  438. User = user,
  439. IsVirtualItem = false,
  440. PresetViews = new string[] { },
  441. ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
  442. IsPlaceHolder = false,
  443. DtoOptions = GetDtoOptions()
  444. };
  445. SetSorting(query, sort, folder.IsPreSorted);
  446. var queryResult = folder.GetItems(query);
  447. return ToResult(queryResult);
  448. }
  449. private QueryResult<ServerItem> GetMusicFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
  450. {
  451. var query = new InternalItemsQuery(user)
  452. {
  453. StartIndex = startIndex,
  454. Limit = limit
  455. };
  456. SetSorting(query, sort, false);
  457. if (stubType.HasValue && stubType.Value == StubType.Latest)
  458. {
  459. return GetMusicLatest(item, user, query);
  460. }
  461. if (stubType.HasValue && stubType.Value == StubType.Playlists)
  462. {
  463. return GetMusicPlaylists(item, user, query);
  464. }
  465. if (stubType.HasValue && stubType.Value == StubType.Albums)
  466. {
  467. return GetMusicAlbums(item, user, query);
  468. }
  469. if (stubType.HasValue && stubType.Value == StubType.Artists)
  470. {
  471. return GetMusicArtists(item, user, query);
  472. }
  473. if (stubType.HasValue && stubType.Value == StubType.AlbumArtists)
  474. {
  475. return GetMusicAlbumArtists(item, user, query);
  476. }
  477. if (stubType.HasValue && stubType.Value == StubType.FavoriteAlbums)
  478. {
  479. return GetFavoriteAlbums(item, user, query);
  480. }
  481. if (stubType.HasValue && stubType.Value == StubType.FavoriteArtists)
  482. {
  483. return GetFavoriteArtists(item, user, query);
  484. }
  485. if (stubType.HasValue && stubType.Value == StubType.FavoriteSongs)
  486. {
  487. return GetFavoriteSongs(item, user, query);
  488. }
  489. if (stubType.HasValue && stubType.Value == StubType.Songs)
  490. {
  491. return GetMusicSongs(item, user, query);
  492. }
  493. if (stubType.HasValue && stubType.Value == StubType.Genres)
  494. {
  495. return GetMusicGenres(item, user, query);
  496. }
  497. var list = new List<ServerItem>();
  498. list.Add(new ServerItem(item)
  499. {
  500. StubType = StubType.Latest
  501. });
  502. list.Add(new ServerItem(item)
  503. {
  504. StubType = StubType.Playlists
  505. });
  506. list.Add(new ServerItem(item)
  507. {
  508. StubType = StubType.Albums
  509. });
  510. list.Add(new ServerItem(item)
  511. {
  512. StubType = StubType.AlbumArtists
  513. });
  514. list.Add(new ServerItem(item)
  515. {
  516. StubType = StubType.Artists
  517. });
  518. list.Add(new ServerItem(item)
  519. {
  520. StubType = StubType.Songs
  521. });
  522. list.Add(new ServerItem(item)
  523. {
  524. StubType = StubType.Genres
  525. });
  526. list.Add(new ServerItem(item)
  527. {
  528. StubType = StubType.FavoriteArtists
  529. });
  530. list.Add(new ServerItem(item)
  531. {
  532. StubType = StubType.FavoriteAlbums
  533. });
  534. list.Add(new ServerItem(item)
  535. {
  536. StubType = StubType.FavoriteSongs
  537. });
  538. return new QueryResult<ServerItem>
  539. {
  540. Items = list.ToArray(list.Count),
  541. TotalRecordCount = list.Count
  542. };
  543. }
  544. private QueryResult<ServerItem> GetMovieFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
  545. {
  546. var query = new InternalItemsQuery(user)
  547. {
  548. StartIndex = startIndex,
  549. Limit = limit
  550. };
  551. SetSorting(query, sort, false);
  552. if (stubType.HasValue && stubType.Value == StubType.ContinueWatching)
  553. {
  554. return GetMovieContinueWatching(item, user, query);
  555. }
  556. if (stubType.HasValue && stubType.Value == StubType.Latest)
  557. {
  558. return GetMovieLatest(item, user, query);
  559. }
  560. if (stubType.HasValue && stubType.Value == StubType.Movies)
  561. {
  562. return GetMovieMovies(item, user, query);
  563. }
  564. if (stubType.HasValue && stubType.Value == StubType.Collections)
  565. {
  566. return GetMovieCollections(item, user, query);
  567. }
  568. if (stubType.HasValue && stubType.Value == StubType.Favorites)
  569. {
  570. return GetMovieFavorites(item, user, query);
  571. }
  572. if (stubType.HasValue && stubType.Value == StubType.Genres)
  573. {
  574. return GetGenres(item, user, query);
  575. }
  576. var list = new List<ServerItem>();
  577. list.Add(new ServerItem(item)
  578. {
  579. StubType = StubType.ContinueWatching
  580. });
  581. list.Add(new ServerItem(item)
  582. {
  583. StubType = StubType.Latest
  584. });
  585. list.Add(new ServerItem(item)
  586. {
  587. StubType = StubType.Movies
  588. });
  589. list.Add(new ServerItem(item)
  590. {
  591. StubType = StubType.Collections
  592. });
  593. list.Add(new ServerItem(item)
  594. {
  595. StubType = StubType.Favorites
  596. });
  597. list.Add(new ServerItem(item)
  598. {
  599. StubType = StubType.Genres
  600. });
  601. return new QueryResult<ServerItem>
  602. {
  603. Items = list.ToArray(list.Count),
  604. TotalRecordCount = list.Count
  605. };
  606. }
  607. private QueryResult<ServerItem> GetTvFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit)
  608. {
  609. var query = new InternalItemsQuery(user)
  610. {
  611. StartIndex = startIndex,
  612. Limit = limit
  613. };
  614. SetSorting(query, sort, false);
  615. if (stubType.HasValue && stubType.Value == StubType.ContinueWatching)
  616. {
  617. return GetMovieContinueWatching(item, user, query);
  618. }
  619. if (stubType.HasValue && stubType.Value == StubType.NextUp)
  620. {
  621. return GetNextUp(item, user, query);
  622. }
  623. if (stubType.HasValue && stubType.Value == StubType.Latest)
  624. {
  625. return GetTvLatest(item, user, query);
  626. }
  627. if (stubType.HasValue && stubType.Value == StubType.Series)
  628. {
  629. return GetSeries(item, user, query);
  630. }
  631. if (stubType.HasValue && stubType.Value == StubType.FavoriteSeries)
  632. {
  633. return GetFavoriteSeries(item, user, query);
  634. }
  635. if (stubType.HasValue && stubType.Value == StubType.FavoriteEpisodes)
  636. {
  637. return GetFavoriteEpisodes(item, user, query);
  638. }
  639. if (stubType.HasValue && stubType.Value == StubType.Genres)
  640. {
  641. return GetGenres(item, user, query);
  642. }
  643. var list = new List<ServerItem>();
  644. list.Add(new ServerItem(item)
  645. {
  646. StubType = StubType.ContinueWatching
  647. });
  648. list.Add(new ServerItem(item)
  649. {
  650. StubType = StubType.NextUp
  651. });
  652. list.Add(new ServerItem(item)
  653. {
  654. StubType = StubType.Latest
  655. });
  656. list.Add(new ServerItem(item)
  657. {
  658. StubType = StubType.Series
  659. });
  660. list.Add(new ServerItem(item)
  661. {
  662. StubType = StubType.FavoriteSeries
  663. });
  664. list.Add(new ServerItem(item)
  665. {
  666. StubType = StubType.FavoriteEpisodes
  667. });
  668. list.Add(new ServerItem(item)
  669. {
  670. StubType = StubType.Genres
  671. });
  672. return new QueryResult<ServerItem>
  673. {
  674. Items = list.ToArray(list.Count),
  675. TotalRecordCount = list.Count
  676. };
  677. }
  678. private QueryResult<ServerItem> GetMovieContinueWatching(BaseItem parent, User user, InternalItemsQuery query)
  679. {
  680. query.Recursive = true;
  681. query.Parent = parent;
  682. query.SetUser(user);
  683. query.OrderBy = new List<Tuple<string, SortOrder>>
  684. {
  685. new Tuple<string, SortOrder> (ItemSortBy.DatePlayed, SortOrder.Descending),
  686. new Tuple<string, SortOrder> (ItemSortBy.SortName, SortOrder.Ascending)
  687. };
  688. query.IsResumable = true;
  689. query.Limit = 10;
  690. var result = _libraryManager.GetItemsResult(query);
  691. return ToResult(result);
  692. }
  693. private QueryResult<ServerItem> GetSeries(BaseItem parent, User user, InternalItemsQuery query)
  694. {
  695. query.Recursive = true;
  696. query.Parent = parent;
  697. query.SetUser(user);
  698. query.IncludeItemTypes = new[] { typeof(Series).Name };
  699. var result = _libraryManager.GetItemsResult(query);
  700. return ToResult(result);
  701. }
  702. private QueryResult<ServerItem> GetMovieMovies(BaseItem parent, User user, InternalItemsQuery query)
  703. {
  704. query.Recursive = true;
  705. query.Parent = parent;
  706. query.SetUser(user);
  707. query.IncludeItemTypes = new[] { typeof(Movie).Name };
  708. var result = _libraryManager.GetItemsResult(query);
  709. return ToResult(result);
  710. }
  711. private QueryResult<ServerItem> GetMovieCollections(BaseItem parent, User user, InternalItemsQuery query)
  712. {
  713. query.Recursive = true;
  714. //query.Parent = parent;
  715. query.SetUser(user);
  716. query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
  717. var result = _libraryManager.GetItemsResult(query);
  718. return ToResult(result);
  719. }
  720. private QueryResult<ServerItem> GetMusicAlbums(BaseItem parent, User user, InternalItemsQuery query)
  721. {
  722. query.Recursive = true;
  723. query.Parent = parent;
  724. query.SetUser(user);
  725. query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name };
  726. var result = _libraryManager.GetItemsResult(query);
  727. return ToResult(result);
  728. }
  729. private QueryResult<ServerItem> GetMusicSongs(BaseItem parent, User user, InternalItemsQuery query)
  730. {
  731. query.Recursive = true;
  732. query.Parent = parent;
  733. query.SetUser(user);
  734. query.IncludeItemTypes = new[] { typeof(Audio).Name };
  735. var result = _libraryManager.GetItemsResult(query);
  736. return ToResult(result);
  737. }
  738. private QueryResult<ServerItem> GetFavoriteSongs(BaseItem parent, User user, InternalItemsQuery query)
  739. {
  740. query.Recursive = true;
  741. query.Parent = parent;
  742. query.SetUser(user);
  743. query.IsFavorite = true;
  744. query.IncludeItemTypes = new[] { typeof(Audio).Name };
  745. var result = _libraryManager.GetItemsResult(query);
  746. return ToResult(result);
  747. }
  748. private QueryResult<ServerItem> GetFavoriteSeries(BaseItem parent, User user, InternalItemsQuery query)
  749. {
  750. query.Recursive = true;
  751. query.Parent = parent;
  752. query.SetUser(user);
  753. query.IsFavorite = true;
  754. query.IncludeItemTypes = new[] { typeof(Series).Name };
  755. var result = _libraryManager.GetItemsResult(query);
  756. return ToResult(result);
  757. }
  758. private QueryResult<ServerItem> GetFavoriteEpisodes(BaseItem parent, User user, InternalItemsQuery query)
  759. {
  760. query.Recursive = true;
  761. query.Parent = parent;
  762. query.SetUser(user);
  763. query.IsFavorite = true;
  764. query.IncludeItemTypes = new[] { typeof(Episode).Name };
  765. var result = _libraryManager.GetItemsResult(query);
  766. return ToResult(result);
  767. }
  768. private QueryResult<ServerItem> GetMovieFavorites(BaseItem parent, User user, InternalItemsQuery query)
  769. {
  770. query.Recursive = true;
  771. query.Parent = parent;
  772. query.SetUser(user);
  773. query.IsFavorite = true;
  774. query.IncludeItemTypes = new[] { typeof(Movie).Name };
  775. var result = _libraryManager.GetItemsResult(query);
  776. return ToResult(result);
  777. }
  778. private QueryResult<ServerItem> GetFavoriteAlbums(BaseItem parent, User user, InternalItemsQuery query)
  779. {
  780. query.Recursive = true;
  781. query.Parent = parent;
  782. query.SetUser(user);
  783. query.IsFavorite = true;
  784. query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name };
  785. var result = _libraryManager.GetItemsResult(query);
  786. return ToResult(result);
  787. }
  788. private QueryResult<ServerItem> GetGenres(BaseItem parent, User user, InternalItemsQuery query)
  789. {
  790. var genresResult = _libraryManager.GetGenres(new InternalItemsQuery(user)
  791. {
  792. AncestorIds = new[] { parent.Id.ToString("N") },
  793. StartIndex = query.StartIndex,
  794. Limit = query.Limit
  795. });
  796. var result = new QueryResult<BaseItem>
  797. {
  798. TotalRecordCount = genresResult.TotalRecordCount,
  799. Items = genresResult.Items.Select(i => i.Item1).ToArray(genresResult.Items.Length)
  800. };
  801. return ToResult(result);
  802. }
  803. private QueryResult<ServerItem> GetMusicGenres(BaseItem parent, User user, InternalItemsQuery query)
  804. {
  805. var genresResult = _libraryManager.GetMusicGenres(new InternalItemsQuery(user)
  806. {
  807. AncestorIds = new[] { parent.Id.ToString("N") },
  808. StartIndex = query.StartIndex,
  809. Limit = query.Limit
  810. });
  811. var result = new QueryResult<BaseItem>
  812. {
  813. TotalRecordCount = genresResult.TotalRecordCount,
  814. Items = genresResult.Items.Select(i => i.Item1).ToArray(genresResult.Items.Length)
  815. };
  816. return ToResult(result);
  817. }
  818. private QueryResult<ServerItem> GetMusicAlbumArtists(BaseItem parent, User user, InternalItemsQuery query)
  819. {
  820. var artists = _libraryManager.GetAlbumArtists(new InternalItemsQuery(user)
  821. {
  822. AncestorIds = new[] { parent.Id.ToString("N") },
  823. StartIndex = query.StartIndex,
  824. Limit = query.Limit
  825. });
  826. var result = new QueryResult<BaseItem>
  827. {
  828. TotalRecordCount = artists.TotalRecordCount,
  829. Items = artists.Items.Select(i => i.Item1).ToArray(artists.Items.Length)
  830. };
  831. return ToResult(result);
  832. }
  833. private QueryResult<ServerItem> GetMusicArtists(BaseItem parent, User user, InternalItemsQuery query)
  834. {
  835. var artists = _libraryManager.GetArtists(new InternalItemsQuery(user)
  836. {
  837. AncestorIds = new[] { parent.Id.ToString("N") },
  838. StartIndex = query.StartIndex,
  839. Limit = query.Limit
  840. });
  841. var result = new QueryResult<BaseItem>
  842. {
  843. TotalRecordCount = artists.TotalRecordCount,
  844. Items = artists.Items.Select(i => i.Item1).ToArray(artists.Items.Length)
  845. };
  846. return ToResult(result);
  847. }
  848. private QueryResult<ServerItem> GetFavoriteArtists(BaseItem parent, User user, InternalItemsQuery query)
  849. {
  850. var artists = _libraryManager.GetArtists(new InternalItemsQuery(user)
  851. {
  852. AncestorIds = new[] { parent.Id.ToString("N") },
  853. StartIndex = query.StartIndex,
  854. Limit = query.Limit,
  855. IsFavorite = true
  856. });
  857. var result = new QueryResult<BaseItem>
  858. {
  859. TotalRecordCount = artists.TotalRecordCount,
  860. Items = artists.Items.Select(i => i.Item1).ToArray(artists.Items.Length)
  861. };
  862. return ToResult(result);
  863. }
  864. private QueryResult<ServerItem> GetMusicPlaylists(BaseItem parent, User user, InternalItemsQuery query)
  865. {
  866. query.Parent = null;
  867. query.IncludeItemTypes = new[] { typeof(Playlist).Name };
  868. query.SetUser(user);
  869. query.Recursive = true;
  870. var result = _libraryManager.GetItemsResult(query);
  871. return ToResult(result);
  872. }
  873. private QueryResult<ServerItem> GetMusicLatest(BaseItem parent, User user, InternalItemsQuery query)
  874. {
  875. query.SortBy = new string[] { };
  876. var items = _userViewManager.GetLatestItems(new LatestItemsQuery
  877. {
  878. UserId = user.Id.ToString("N"),
  879. Limit = 50,
  880. IncludeItemTypes = new[] { typeof(Audio).Name },
  881. ParentId = parent == null ? null : parent.Id.ToString("N"),
  882. GroupItems = true
  883. }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToList();
  884. return ToResult(items);
  885. }
  886. private QueryResult<ServerItem> GetNextUp(BaseItem parent, User user, InternalItemsQuery query)
  887. {
  888. query.SortBy = new string[] { };
  889. var result = _tvSeriesManager.GetNextUp(new NextUpQuery
  890. {
  891. Limit = query.Limit,
  892. StartIndex = query.StartIndex,
  893. UserId = query.User.Id.ToString("N")
  894. }, new List<Folder> { (Folder)parent }, query.DtoOptions);
  895. return ToResult(result);
  896. }
  897. private QueryResult<ServerItem> GetTvLatest(BaseItem parent, User user, InternalItemsQuery query)
  898. {
  899. query.SortBy = new string[] { };
  900. var items = _userViewManager.GetLatestItems(new LatestItemsQuery
  901. {
  902. UserId = user.Id.ToString("N"),
  903. Limit = 50,
  904. IncludeItemTypes = new[] { typeof(Episode).Name },
  905. ParentId = parent == null ? null : parent.Id.ToString("N"),
  906. GroupItems = false
  907. }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToList();
  908. return ToResult(items);
  909. }
  910. private QueryResult<ServerItem> GetMovieLatest(BaseItem parent, User user, InternalItemsQuery query)
  911. {
  912. query.SortBy = new string[] { };
  913. var items = _userViewManager.GetLatestItems(new LatestItemsQuery
  914. {
  915. UserId = user.Id.ToString("N"),
  916. Limit = 50,
  917. IncludeItemTypes = new[] { typeof(Movie).Name },
  918. ParentId = parent == null ? null : parent.Id.ToString("N"),
  919. GroupItems = true
  920. }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToList();
  921. return ToResult(items);
  922. }
  923. private QueryResult<ServerItem> GetMusicArtistItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
  924. {
  925. var query = new InternalItemsQuery(user)
  926. {
  927. Recursive = true,
  928. ParentId = parentId,
  929. ArtistIds = new[] { item.Id.ToString("N") },
  930. IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
  931. Limit = limit,
  932. StartIndex = startIndex,
  933. DtoOptions = GetDtoOptions()
  934. };
  935. SetSorting(query, sort, false);
  936. var result = _libraryManager.GetItemsResult(query);
  937. return ToResult(result);
  938. }
  939. private QueryResult<ServerItem> GetGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
  940. {
  941. var query = new InternalItemsQuery(user)
  942. {
  943. Recursive = true,
  944. ParentId = parentId,
  945. GenreIds = new[] { item.Id.ToString("N") },
  946. IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name },
  947. Limit = limit,
  948. StartIndex = startIndex,
  949. DtoOptions = GetDtoOptions()
  950. };
  951. SetSorting(query, sort, false);
  952. var result = _libraryManager.GetItemsResult(query);
  953. return ToResult(result);
  954. }
  955. private QueryResult<ServerItem> GetMusicGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
  956. {
  957. var query = new InternalItemsQuery(user)
  958. {
  959. Recursive = true,
  960. ParentId = parentId,
  961. GenreIds = new[] { item.Id.ToString("N") },
  962. IncludeItemTypes = new[] { typeof(MusicAlbum).Name },
  963. Limit = limit,
  964. StartIndex = startIndex,
  965. DtoOptions = GetDtoOptions()
  966. };
  967. SetSorting(query, sort, false);
  968. var result = _libraryManager.GetItemsResult(query);
  969. return ToResult(result);
  970. }
  971. private QueryResult<ServerItem> ToResult(List<BaseItem> result)
  972. {
  973. var serverItems = result
  974. .Select(i => new ServerItem(i))
  975. .ToArray(result.Count);
  976. return new QueryResult<ServerItem>
  977. {
  978. TotalRecordCount = result.Count,
  979. Items = serverItems
  980. };
  981. }
  982. private QueryResult<ServerItem> ToResult(QueryResult<BaseItem> result)
  983. {
  984. var serverItems = result
  985. .Items
  986. .Select(i => new ServerItem(i))
  987. .ToArray(result.Items.Length);
  988. return new QueryResult<ServerItem>
  989. {
  990. TotalRecordCount = result.TotalRecordCount,
  991. Items = serverItems
  992. };
  993. }
  994. private void SetSorting(InternalItemsQuery query, SortCriteria sort, bool isPreSorted)
  995. {
  996. var sortOrders = new List<string>();
  997. if (!isPreSorted)
  998. {
  999. sortOrders.Add(ItemSortBy.SortName);
  1000. }
  1001. query.SortBy = sortOrders.ToArray(sortOrders.Count);
  1002. query.SortOrder = sort.SortOrder;
  1003. }
  1004. private QueryResult<ServerItem> GetItemsFromPerson(Person person, User user, int? startIndex, int? limit)
  1005. {
  1006. var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
  1007. {
  1008. PersonIds = new[] { person.Id.ToString("N") },
  1009. IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(Trailer).Name },
  1010. SortBy = new[] { ItemSortBy.SortName },
  1011. Limit = limit,
  1012. StartIndex = startIndex,
  1013. DtoOptions = GetDtoOptions()
  1014. });
  1015. var serverItems = itemsResult.Items.Select(i => new ServerItem(i)).ToArray(itemsResult.Items.Length);
  1016. return new QueryResult<ServerItem>
  1017. {
  1018. TotalRecordCount = itemsResult.TotalRecordCount,
  1019. Items = serverItems
  1020. };
  1021. }
  1022. private QueryResult<ServerItem> ApplyPaging(QueryResult<ServerItem> result, int? startIndex, int? limit)
  1023. {
  1024. result.Items = result.Items.Skip(startIndex ?? 0).Take(limit ?? int.MaxValue).ToArray();
  1025. return result;
  1026. }
  1027. private ServerItem GetItemFromObjectId(string id, User user)
  1028. {
  1029. return DidlBuilder.IsIdRoot(id)
  1030. ? new ServerItem(user.RootFolder)
  1031. : ParseItemId(id, user);
  1032. }
  1033. private ServerItem ParseItemId(string id, User user)
  1034. {
  1035. Guid itemId;
  1036. StubType? stubType = null;
  1037. // After using PlayTo, MediaMonkey sends a request to the server trying to get item info
  1038. const string paramsSrch = "Params=";
  1039. var paramsIndex = id.IndexOf(paramsSrch, StringComparison.OrdinalIgnoreCase);
  1040. if (paramsIndex != -1)
  1041. {
  1042. id = id.Substring(paramsIndex + paramsSrch.Length);
  1043. var parts = id.Split(';');
  1044. id = parts[23];
  1045. }
  1046. var enumNames = Enum.GetNames(typeof(StubType));
  1047. foreach (var name in enumNames)
  1048. {
  1049. if (id.StartsWith(name + "_", StringComparison.OrdinalIgnoreCase))
  1050. {
  1051. stubType = (StubType)Enum.Parse(typeof(StubType), name, true);
  1052. id = id.Split(new[] { '_' }, 2)[1];
  1053. break;
  1054. }
  1055. }
  1056. if (Guid.TryParse(id, out itemId))
  1057. {
  1058. var item = _libraryManager.GetItemById(itemId);
  1059. return new ServerItem(item)
  1060. {
  1061. StubType = stubType
  1062. };
  1063. }
  1064. Logger.Error("Error parsing item Id: {0}. Returning user root folder.", id);
  1065. return new ServerItem(user.RootFolder);
  1066. }
  1067. }
  1068. internal class ServerItem
  1069. {
  1070. public BaseItem Item { get; set; }
  1071. public StubType? StubType { get; set; }
  1072. public ServerItem(BaseItem item)
  1073. {
  1074. Item = item;
  1075. if (item is IItemByName && !(item is Folder))
  1076. {
  1077. StubType = Dlna.ContentDirectory.StubType.Folder;
  1078. }
  1079. }
  1080. }
  1081. public enum StubType
  1082. {
  1083. Folder = 0,
  1084. People = 1,
  1085. Latest = 2,
  1086. Playlists = 3,
  1087. Albums = 4,
  1088. AlbumArtists = 5,
  1089. Artists = 6,
  1090. Songs = 7,
  1091. Genres = 8,
  1092. FavoriteSongs = 9,
  1093. FavoriteArtists = 10,
  1094. FavoriteAlbums = 11,
  1095. ContinueWatching = 12,
  1096. Movies = 13,
  1097. Collections = 14,
  1098. Favorites = 15,
  1099. NextUp = 16,
  1100. Series = 17,
  1101. FavoriteSeries = 18,
  1102. FavoriteEpisodes = 19
  1103. }
  1104. }