ControlHandler.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  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 MediaBrowser.Controller.Localization;
  10. using MediaBrowser.Dlna.Didl;
  11. using MediaBrowser.Dlna.Server;
  12. using MediaBrowser.Dlna.Service;
  13. using MediaBrowser.Model.Configuration;
  14. using MediaBrowser.Model.Dlna;
  15. using MediaBrowser.Model.Entities;
  16. using MediaBrowser.Model.Logging;
  17. using MediaBrowser.Model.Querying;
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Globalization;
  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.MediaEncoding;
  27. namespace MediaBrowser.Dlna.ContentDirectory
  28. {
  29. public class ControlHandler : BaseControlHandler
  30. {
  31. private readonly ILibraryManager _libraryManager;
  32. private readonly IChannelManager _channelManager;
  33. private readonly IUserDataManager _userDataManager;
  34. private readonly IServerConfigurationManager _config;
  35. private readonly User _user;
  36. private readonly IUserViewManager _userViewManager;
  37. private readonly IMediaEncoder _mediaEncoder;
  38. private const string NS_DC = "http://purl.org/dc/elements/1.1/";
  39. private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
  40. private const string NS_DLNA = "urn:schemas-dlna-org:metadata-1-0/";
  41. private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
  42. private readonly int _systemUpdateId;
  43. private readonly CultureInfo _usCulture = new CultureInfo("en-US");
  44. private readonly DidlBuilder _didlBuilder;
  45. private readonly DeviceProfile _profile;
  46. 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)
  47. : base(config, logger)
  48. {
  49. _libraryManager = libraryManager;
  50. _userDataManager = userDataManager;
  51. _user = user;
  52. _systemUpdateId = systemUpdateId;
  53. _channelManager = channelManager;
  54. _userViewManager = userViewManager;
  55. _mediaEncoder = mediaEncoder;
  56. _profile = profile;
  57. _config = config;
  58. _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager, _mediaEncoder);
  59. }
  60. protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams)
  61. {
  62. var deviceId = "test";
  63. var user = _user;
  64. if (string.Equals(methodName, "GetSearchCapabilities", StringComparison.OrdinalIgnoreCase))
  65. return HandleGetSearchCapabilities();
  66. if (string.Equals(methodName, "GetSortCapabilities", StringComparison.OrdinalIgnoreCase))
  67. return HandleGetSortCapabilities();
  68. if (string.Equals(methodName, "GetSortExtensionCapabilities", StringComparison.OrdinalIgnoreCase))
  69. return HandleGetSortExtensionCapabilities();
  70. if (string.Equals(methodName, "GetSystemUpdateID", StringComparison.OrdinalIgnoreCase))
  71. return HandleGetSystemUpdateID();
  72. if (string.Equals(methodName, "Browse", StringComparison.OrdinalIgnoreCase))
  73. return HandleBrowse(methodParams, user, deviceId).Result;
  74. if (string.Equals(methodName, "X_GetFeatureList", StringComparison.OrdinalIgnoreCase))
  75. return HandleXGetFeatureList();
  76. if (string.Equals(methodName, "GetFeatureList", StringComparison.OrdinalIgnoreCase))
  77. return HandleGetFeatureList();
  78. if (string.Equals(methodName, "X_SetBookmark", StringComparison.OrdinalIgnoreCase))
  79. return HandleXSetBookmark(methodParams, user);
  80. if (string.Equals(methodName, "Search", StringComparison.OrdinalIgnoreCase))
  81. return HandleSearch(methodParams, user, deviceId).Result;
  82. throw new ResourceNotFoundException("Unexpected control request name: " + methodName);
  83. }
  84. private IEnumerable<KeyValuePair<string, string>> HandleXSetBookmark(IDictionary<string, string> sparams, User user)
  85. {
  86. var id = sparams["ObjectID"];
  87. var serverItem = GetItemFromObjectId(id, user);
  88. var item = serverItem.Item;
  89. var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
  90. var userdata = _userDataManager.GetUserData(user, item);
  91. userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;
  92. _userDataManager.SaveUserData(user.Id, item, userdata, UserDataSaveReason.TogglePlayed,
  93. CancellationToken.None);
  94. return new Headers();
  95. }
  96. private IEnumerable<KeyValuePair<string, string>> HandleGetSearchCapabilities()
  97. {
  98. return new Headers(true) { { "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" } };
  99. }
  100. private IEnumerable<KeyValuePair<string, string>> HandleGetSortCapabilities()
  101. {
  102. return new Headers(true)
  103. {
  104. { "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" }
  105. };
  106. }
  107. private IEnumerable<KeyValuePair<string, string>> HandleGetSortExtensionCapabilities()
  108. {
  109. return new Headers(true)
  110. {
  111. { "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" }
  112. };
  113. }
  114. private IEnumerable<KeyValuePair<string, string>> HandleGetSystemUpdateID()
  115. {
  116. var headers = new Headers(true);
  117. headers.Add("Id", _systemUpdateId.ToString(_usCulture));
  118. return headers;
  119. }
  120. private IEnumerable<KeyValuePair<string, string>> HandleGetFeatureList()
  121. {
  122. return new Headers(true)
  123. {
  124. { "FeatureList", GetFeatureListXml() }
  125. };
  126. }
  127. private IEnumerable<KeyValuePair<string, string>> HandleXGetFeatureList()
  128. {
  129. return new Headers(true)
  130. {
  131. { "FeatureList", GetFeatureListXml() }
  132. };
  133. }
  134. private string GetFeatureListXml()
  135. {
  136. var builder = new StringBuilder();
  137. builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  138. 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\">");
  139. builder.Append("<Feature name=\"samsung.com_BASICVIEW\" version=\"1\">");
  140. builder.Append("<container id=\"I\" type=\"object.item.imageItem\"/>");
  141. builder.Append("<container id=\"A\" type=\"object.item.audioItem\"/>");
  142. builder.Append("<container id=\"V\" type=\"object.item.videoItem\"/>");
  143. builder.Append("</Feature>");
  144. builder.Append("</Features>");
  145. return builder.ToString();
  146. }
  147. private async Task<IEnumerable<KeyValuePair<string, string>>> HandleBrowse(Headers sparams, User user, string deviceId)
  148. {
  149. var id = sparams["ObjectID"];
  150. var flag = sparams["BrowseFlag"];
  151. var filter = new Filter(sparams.GetValueOrDefault("Filter", "*"));
  152. var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
  153. var provided = 0;
  154. // Default to null instead of 0
  155. // Upnp inspector sends 0 as requestedCount when it wants everything
  156. int? requestedCount = null;
  157. int? start = 0;
  158. int requestedVal;
  159. if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
  160. {
  161. requestedCount = requestedVal;
  162. }
  163. int startVal;
  164. if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
  165. {
  166. start = startVal;
  167. }
  168. //var root = GetItem(id) as IMediaFolder;
  169. var result = new XmlDocument();
  170. var didl = result.CreateElement(string.Empty, "DIDL-Lite", NS_DIDL);
  171. didl.SetAttribute("xmlns:dc", NS_DC);
  172. didl.SetAttribute("xmlns:dlna", NS_DLNA);
  173. didl.SetAttribute("xmlns:upnp", NS_UPNP);
  174. //didl.SetAttribute("xmlns:sec", NS_SEC);
  175. result.AppendChild(didl);
  176. var serverItem = GetItemFromObjectId(id, user);
  177. var item = serverItem.Item;
  178. int totalCount;
  179. if (string.Equals(flag, "BrowseMetadata"))
  180. {
  181. totalCount = 1;
  182. if (item.IsFolder || serverItem.StubType.HasValue)
  183. {
  184. var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount).ConfigureAwait(false));
  185. result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, item, serverItem.StubType, null, childrenResult.TotalRecordCount, filter, id));
  186. }
  187. else
  188. {
  189. result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(_config.GetDlnaConfiguration(), result, item, null, null, deviceId, filter));
  190. }
  191. provided++;
  192. }
  193. else
  194. {
  195. var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount).ConfigureAwait(false));
  196. totalCount = childrenResult.TotalRecordCount;
  197. provided = childrenResult.Items.Length;
  198. foreach (var i in childrenResult.Items)
  199. {
  200. var childItem = i.Item;
  201. var displayStubType = i.StubType;
  202. if (childItem.IsFolder || displayStubType.HasValue)
  203. {
  204. var childCount = (await GetUserItems(childItem, displayStubType, user, sortCriteria, null, 0).ConfigureAwait(false))
  205. .TotalRecordCount;
  206. result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, childItem, displayStubType, item, childCount, filter));
  207. }
  208. else
  209. {
  210. result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(_config.GetDlnaConfiguration(), result, childItem, item, serverItem.StubType, deviceId, filter));
  211. }
  212. }
  213. }
  214. var resXML = result.OuterXml;
  215. return new List<KeyValuePair<string, string>>
  216. {
  217. new KeyValuePair<string,string>("Result", resXML),
  218. new KeyValuePair<string,string>("NumberReturned", provided.ToString(_usCulture)),
  219. new KeyValuePair<string,string>("TotalMatches", totalCount.ToString(_usCulture)),
  220. new KeyValuePair<string,string>("UpdateID", _systemUpdateId.ToString(_usCulture))
  221. };
  222. }
  223. private async Task<IEnumerable<KeyValuePair<string, string>>> HandleSearch(Headers sparams, User user, string deviceId)
  224. {
  225. var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", ""));
  226. var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
  227. var filter = new Filter(sparams.GetValueOrDefault("Filter", "*"));
  228. // sort example: dc:title, dc:date
  229. // Default to null instead of 0
  230. // Upnp inspector sends 0 as requestedCount when it wants everything
  231. int? requestedCount = null;
  232. int? start = 0;
  233. int requestedVal;
  234. if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
  235. {
  236. requestedCount = requestedVal;
  237. }
  238. int startVal;
  239. if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
  240. {
  241. start = startVal;
  242. }
  243. //var root = GetItem(id) as IMediaFolder;
  244. var result = new XmlDocument();
  245. var didl = result.CreateElement(string.Empty, "DIDL-Lite", NS_DIDL);
  246. didl.SetAttribute("xmlns:dc", NS_DC);
  247. didl.SetAttribute("xmlns:dlna", NS_DLNA);
  248. didl.SetAttribute("xmlns:upnp", NS_UPNP);
  249. foreach (var att in _profile.XmlRootAttributes)
  250. {
  251. didl.SetAttribute(att.Name, att.Value);
  252. }
  253. result.AppendChild(didl);
  254. var serverItem = GetItemFromObjectId(sparams["ContainerID"], user);
  255. var item = serverItem.Item;
  256. var childrenResult = (await GetChildrenSorted(item, user, searchCriteria, sortCriteria, start, requestedCount).ConfigureAwait(false));
  257. var totalCount = childrenResult.TotalRecordCount;
  258. var provided = childrenResult.Items.Length;
  259. foreach (var i in childrenResult.Items)
  260. {
  261. if (i.IsFolder)
  262. {
  263. var childCount = (await GetChildrenSorted(i, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
  264. .TotalRecordCount;
  265. result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, i, null, item, childCount, filter));
  266. }
  267. else
  268. {
  269. result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(_config.GetDlnaConfiguration(), result, i, item, serverItem.StubType, deviceId, filter));
  270. }
  271. }
  272. var resXML = result.OuterXml;
  273. return new List<KeyValuePair<string, string>>
  274. {
  275. new KeyValuePair<string,string>("Result", resXML),
  276. new KeyValuePair<string,string>("NumberReturned", provided.ToString(_usCulture)),
  277. new KeyValuePair<string,string>("TotalMatches", totalCount.ToString(_usCulture)),
  278. new KeyValuePair<string,string>("UpdateID", _systemUpdateId.ToString(_usCulture))
  279. };
  280. }
  281. private Task<QueryResult<BaseItem>> GetChildrenSorted(BaseItem item, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
  282. {
  283. var folder = (Folder)item;
  284. var sortOrders = new List<string>();
  285. if (!folder.IsPreSorted)
  286. {
  287. sortOrders.Add(ItemSortBy.SortName);
  288. }
  289. var mediaTypes = new List<string>();
  290. bool? isFolder = null;
  291. if (search.SearchType == SearchType.Audio)
  292. {
  293. mediaTypes.Add(MediaType.Audio);
  294. isFolder = false;
  295. }
  296. else if (search.SearchType == SearchType.Video)
  297. {
  298. mediaTypes.Add(MediaType.Video);
  299. isFolder = false;
  300. }
  301. else if (search.SearchType == SearchType.Image)
  302. {
  303. mediaTypes.Add(MediaType.Photo);
  304. isFolder = false;
  305. }
  306. else if (search.SearchType == SearchType.Playlist)
  307. {
  308. //items = items.OfType<Playlist>();
  309. isFolder = true;
  310. }
  311. else if (search.SearchType == SearchType.MusicAlbum)
  312. {
  313. //items = items.OfType<MusicAlbum>();
  314. isFolder = true;
  315. }
  316. return folder.GetItems(new InternalItemsQuery
  317. {
  318. Limit = limit,
  319. StartIndex = startIndex,
  320. SortBy = sortOrders.ToArray(),
  321. SortOrder = sort.SortOrder,
  322. User = user,
  323. Recursive = true,
  324. Filter = FilterUnsupportedContent,
  325. IsFolder = isFolder,
  326. MediaTypes = mediaTypes.ToArray()
  327. });
  328. }
  329. private async Task<QueryResult<ServerItem>> GetUserItems(BaseItem item, StubType? stubType, User user, SortCriteria sort, int? startIndex, int? limit)
  330. {
  331. if (stubType.HasValue)
  332. {
  333. if (stubType.Value == StubType.People)
  334. {
  335. var items = _libraryManager.GetPeopleItems(new InternalPeopleQuery
  336. {
  337. ItemId = item.Id
  338. }).ToArray();
  339. var result = new QueryResult<ServerItem>
  340. {
  341. Items = items.Select(i => new ServerItem { Item = i, StubType = StubType.Folder }).ToArray(),
  342. TotalRecordCount = items.Length
  343. };
  344. return ApplyPaging(result, startIndex, limit);
  345. }
  346. if (stubType.Value == StubType.Folder)
  347. {
  348. var movie = item as Movie;
  349. if (movie != null)
  350. {
  351. return ApplyPaging(await GetMovieItems(movie).ConfigureAwait(false), startIndex, limit);
  352. }
  353. }
  354. var person = item as Person;
  355. if (person != null)
  356. {
  357. return GetItemsFromPerson(person, user, startIndex, limit);
  358. }
  359. return ApplyPaging(new QueryResult<ServerItem>(), startIndex, limit);
  360. }
  361. var folder = (Folder)item;
  362. var sortOrders = new List<string>();
  363. if (!folder.IsPreSorted)
  364. {
  365. sortOrders.Add(ItemSortBy.SortName);
  366. }
  367. var queryResult = await folder.GetItems(new InternalItemsQuery
  368. {
  369. Limit = limit,
  370. StartIndex = startIndex,
  371. SortBy = sortOrders.ToArray(),
  372. SortOrder = sort.SortOrder,
  373. User = user,
  374. Filter = FilterUnsupportedContent,
  375. PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music }
  376. }).ConfigureAwait(false);
  377. var options = _config.GetDlnaConfiguration();
  378. var serverItems = queryResult
  379. .Items
  380. .Select(i => new ServerItem
  381. {
  382. Item = i,
  383. StubType = GetDisplayStubType(i, item, options)
  384. })
  385. .ToArray();
  386. return new QueryResult<ServerItem>
  387. {
  388. TotalRecordCount = queryResult.TotalRecordCount,
  389. Items = serverItems
  390. };
  391. }
  392. private QueryResult<ServerItem> GetItemsFromPerson(Person person, User user, int? startIndex, int? limit)
  393. {
  394. var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
  395. {
  396. Person = person.Name,
  397. IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(Trailer).Name },
  398. SortBy = new[] { ItemSortBy.SortName },
  399. Limit = limit,
  400. StartIndex = startIndex
  401. });
  402. var serverItems = itemsResult.Items.Select(i => new ServerItem
  403. {
  404. Item = i,
  405. StubType = null
  406. })
  407. .ToArray();
  408. return new QueryResult<ServerItem>
  409. {
  410. TotalRecordCount = itemsResult.TotalRecordCount,
  411. Items = serverItems
  412. };
  413. }
  414. private QueryResult<ServerItem> ApplyPaging(QueryResult<ServerItem> result, int? startIndex, int? limit)
  415. {
  416. result.Items = result.Items.Skip(startIndex ?? 0).Take(limit ?? int.MaxValue).ToArray();
  417. return result;
  418. }
  419. private StubType? GetDisplayStubType(BaseItem item, BaseItem context, DlnaOptions options)
  420. {
  421. if (context == null || context.IsFolder)
  422. {
  423. var movie = item as Movie;
  424. if (movie != null && options.EnableMovieFolders)
  425. {
  426. if (movie.GetTrailerIds().Count > 0 ||
  427. movie.SpecialFeatureIds.Count > 0)
  428. {
  429. return StubType.Folder;
  430. }
  431. if (EnablePeopleDisplay(item))
  432. {
  433. return StubType.Folder;
  434. }
  435. }
  436. }
  437. return null;
  438. }
  439. private bool EnablePeopleDisplay(BaseItem item)
  440. {
  441. if (_libraryManager.GetPeopleNames(new InternalPeopleQuery
  442. {
  443. ItemId = item.Id
  444. }).Count > 0)
  445. {
  446. return item is Movie;
  447. }
  448. return false;
  449. }
  450. private Task<QueryResult<ServerItem>> GetMovieItems(Movie item)
  451. {
  452. var list = new List<BaseItem>();
  453. list.Add(item);
  454. list.AddRange(item.GetTrailerIds().Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
  455. list.AddRange(item.SpecialFeatureIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null));
  456. var serverItems = list.Select(i => new ServerItem { Item = i, StubType = null })
  457. .ToList();
  458. serverItems.Add(new ServerItem
  459. {
  460. Item = item,
  461. StubType = StubType.People
  462. });
  463. return Task.FromResult(new QueryResult<ServerItem>
  464. {
  465. Items = serverItems.ToArray(),
  466. TotalRecordCount = serverItems.Count
  467. });
  468. }
  469. private bool FilterUnsupportedContent(BaseItem i)
  470. {
  471. // Unplayable
  472. if (i.LocationType == LocationType.Virtual && !i.IsFolder)
  473. {
  474. return false;
  475. }
  476. // Unplayable
  477. var supportsPlaceHolder = i as ISupportsPlaceHolders;
  478. if (supportsPlaceHolder != null && supportsPlaceHolder.IsPlaceHolder)
  479. {
  480. return false;
  481. }
  482. if (i is Game || i is Book)
  483. {
  484. //return false;
  485. }
  486. return true;
  487. }
  488. private ServerItem GetItemFromObjectId(string id, User user)
  489. {
  490. return DidlBuilder.IsIdRoot(id)
  491. ? new ServerItem { Item = user.RootFolder }
  492. : ParseItemId(id, user);
  493. }
  494. private ServerItem ParseItemId(string id, User user)
  495. {
  496. Guid itemId;
  497. StubType? stubType = null;
  498. // After using PlayTo, MediaMonkey sends a request to the server trying to get item info
  499. const string paramsSrch = "Params=";
  500. var paramsIndex = id.IndexOf(paramsSrch, StringComparison.OrdinalIgnoreCase);
  501. if (paramsIndex != -1)
  502. {
  503. id = id.Substring(paramsIndex + paramsSrch.Length);
  504. var parts = id.Split(';');
  505. id = parts[24];
  506. }
  507. if (id.StartsWith("folder_", StringComparison.OrdinalIgnoreCase))
  508. {
  509. stubType = StubType.Folder;
  510. id = id.Split(new[] { '_' }, 2)[1];
  511. }
  512. else if (id.StartsWith("people_", StringComparison.OrdinalIgnoreCase))
  513. {
  514. stubType = StubType.People;
  515. id = id.Split(new[] { '_' }, 2)[1];
  516. }
  517. if (Guid.TryParse(id, out itemId))
  518. {
  519. var item = _libraryManager.GetItemById(itemId);
  520. return new ServerItem
  521. {
  522. Item = item,
  523. StubType = stubType
  524. };
  525. }
  526. Logger.Error("Error parsing item Id: {0}. Returning user root folder.", id);
  527. return new ServerItem { Item = user.RootFolder };
  528. }
  529. }
  530. internal class ServerItem
  531. {
  532. public BaseItem Item { get; set; }
  533. public StubType? StubType { get; set; }
  534. }
  535. public enum StubType
  536. {
  537. Folder = 0,
  538. People = 1
  539. }
  540. }