DidlBuilder.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. using System.Collections.Generic;
  2. using MediaBrowser.Common.Net;
  3. using MediaBrowser.Controller.Drawing;
  4. using MediaBrowser.Controller.Dto;
  5. using MediaBrowser.Controller.Entities;
  6. using MediaBrowser.Controller.Entities.Audio;
  7. using MediaBrowser.Controller.Entities.Movies;
  8. using MediaBrowser.Controller.Entities.TV;
  9. using MediaBrowser.Model.Dlna;
  10. using MediaBrowser.Model.Drawing;
  11. using MediaBrowser.Model.Entities;
  12. using System;
  13. using System.Globalization;
  14. using System.Linq;
  15. using System.Xml;
  16. namespace MediaBrowser.Dlna.Didl
  17. {
  18. public class DidlBuilder
  19. {
  20. private readonly CultureInfo _usCulture = new CultureInfo("en-US");
  21. private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
  22. private const string NS_DC = "http://purl.org/dc/elements/1.1/";
  23. private const string NS_UPNP = "urn:schemas-upnp-org:metadata-1-0/upnp/";
  24. private const string NS_DLNA = "urn:schemas-dlna-org:metadata-1-0/";
  25. private readonly DeviceProfile _profile;
  26. private readonly IImageProcessor _imageProcessor;
  27. private readonly string _serverAddress;
  28. private readonly IDtoService _dtoService;
  29. public DidlBuilder(DeviceProfile profile, IImageProcessor imageProcessor, string serverAddress, IDtoService dtoService)
  30. {
  31. _profile = profile;
  32. _imageProcessor = imageProcessor;
  33. _serverAddress = serverAddress;
  34. _dtoService = dtoService;
  35. }
  36. public string GetItemDidl(BaseItem item, string deviceId, Filter filter)
  37. {
  38. var result = new XmlDocument();
  39. var didl = result.CreateElement(string.Empty, "DIDL-Lite", NS_DIDL);
  40. didl.SetAttribute("xmlns:dc", NS_DC);
  41. didl.SetAttribute("xmlns:dlna", NS_DLNA);
  42. didl.SetAttribute("xmlns:upnp", NS_UPNP);
  43. //didl.SetAttribute("xmlns:sec", NS_SEC);
  44. foreach (var att in _profile.XmlRootAttributes)
  45. {
  46. didl.SetAttribute(att.Name, att.Value);
  47. }
  48. result.AppendChild(didl);
  49. result.DocumentElement.AppendChild(GetItemElement(result, item, deviceId, filter));
  50. return result.DocumentElement.OuterXml;
  51. }
  52. public XmlElement GetItemElement(XmlDocument doc, BaseItem item, string deviceId, Filter filter)
  53. {
  54. var element = doc.CreateElement(string.Empty, "item", NS_DIDL);
  55. element.SetAttribute("restricted", "1");
  56. element.SetAttribute("id", item.Id.ToString("N"));
  57. if (item.Parent != null)
  58. {
  59. element.SetAttribute("parentID", item.Parent.Id.ToString("N"));
  60. }
  61. //AddBookmarkInfo(item, user, element);
  62. AddGeneralProperties(item, element, filter);
  63. // refID?
  64. // storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
  65. var audio = item as Audio;
  66. if (audio != null)
  67. {
  68. AddAudioResource(element, audio, deviceId, filter);
  69. }
  70. var video = item as Video;
  71. if (video != null)
  72. {
  73. AddVideoResource(element, video, deviceId, filter);
  74. }
  75. AddCover(item, element);
  76. return element;
  77. }
  78. private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter)
  79. {
  80. var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
  81. var sources = _dtoService.GetMediaSources(video);
  82. int? maxBitrateSetting = null;
  83. var streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
  84. {
  85. ItemId = video.Id.ToString("N"),
  86. MediaSources = sources,
  87. Profile = _profile,
  88. DeviceId = deviceId,
  89. MaxBitrate = maxBitrateSetting
  90. });
  91. var url = streamInfo.ToDlnaUrl(_serverAddress);
  92. //res.AppendChild(container.OwnerDocument.CreateCDataSection(url));
  93. res.InnerText = url;
  94. var mediaSource = sources.First(i => string.Equals(i.Id, streamInfo.MediaSourceId));
  95. if (mediaSource.RunTimeTicks.HasValue)
  96. {
  97. res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
  98. }
  99. if (filter.Contains("res@size"))
  100. {
  101. if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength)
  102. {
  103. var size = streamInfo.TargetSize;
  104. if (size.HasValue)
  105. {
  106. res.SetAttribute("size", size.Value.ToString(_usCulture));
  107. }
  108. }
  109. }
  110. var totalBitrate = streamInfo.TargetTotalBitrate;
  111. var targetSampleRate = streamInfo.TargetAudioSampleRate;
  112. var targetChannels = streamInfo.TargetAudioChannels;
  113. var targetWidth = streamInfo.TargetWidth;
  114. var targetHeight = streamInfo.TargetHeight;
  115. if (targetChannels.HasValue)
  116. {
  117. res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
  118. }
  119. if (filter.Contains("res@resolution"))
  120. {
  121. if (targetWidth.HasValue && targetHeight.HasValue)
  122. {
  123. res.SetAttribute("resolution", string.Format("{0}x{1}", targetWidth.Value, targetHeight.Value));
  124. }
  125. }
  126. if (targetSampleRate.HasValue)
  127. {
  128. res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
  129. }
  130. if (totalBitrate.HasValue)
  131. {
  132. res.SetAttribute("bitrate", totalBitrate.Value.ToString(_usCulture));
  133. }
  134. var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container,
  135. streamInfo.AudioCodec,
  136. streamInfo.VideoCodec,
  137. streamInfo.TargetAudioBitrate,
  138. targetChannels,
  139. targetWidth,
  140. targetHeight,
  141. streamInfo.TargetVideoBitDepth,
  142. streamInfo.TargetVideoBitrate,
  143. streamInfo.TargetVideoProfile,
  144. streamInfo.TargetVideoLevel,
  145. streamInfo.TargetFramerate,
  146. streamInfo.TargetPacketLength,
  147. streamInfo.TargetTimestamp);
  148. var filename = url.Substring(0, url.IndexOf('?'));
  149. var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
  150. ? MimeTypes.GetMimeType(filename)
  151. : mediaProfile.MimeType;
  152. var contentFeatures = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container,
  153. streamInfo.VideoCodec,
  154. streamInfo.AudioCodec,
  155. targetWidth,
  156. targetHeight,
  157. streamInfo.TargetVideoBitDepth,
  158. streamInfo.TargetVideoBitrate,
  159. streamInfo.TargetAudioChannels,
  160. streamInfo.TargetAudioBitrate,
  161. streamInfo.TargetTimestamp,
  162. streamInfo.IsDirectStream,
  163. streamInfo.RunTimeTicks,
  164. streamInfo.TargetVideoProfile,
  165. streamInfo.TargetVideoLevel,
  166. streamInfo.TargetFramerate,
  167. streamInfo.TargetPacketLength,
  168. streamInfo.TranscodeSeekInfo);
  169. res.SetAttribute("protocolInfo", String.Format(
  170. "http-get:*:{0}:{1}",
  171. mimeType,
  172. contentFeatures
  173. ));
  174. container.AppendChild(res);
  175. }
  176. private void AddAudioResource(XmlElement container, Audio audio, string deviceId, Filter filter)
  177. {
  178. var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
  179. var sources = _dtoService.GetMediaSources(audio);
  180. var streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
  181. {
  182. ItemId = audio.Id.ToString("N"),
  183. MediaSources = sources,
  184. Profile = _profile,
  185. DeviceId = deviceId
  186. });
  187. var url = streamInfo.ToDlnaUrl(_serverAddress);
  188. //res.AppendChild(container.OwnerDocument.CreateCDataSection(url));
  189. res.InnerText = url;
  190. var mediaSource = sources.First(i => string.Equals(i.Id, streamInfo.MediaSourceId));
  191. if (mediaSource.RunTimeTicks.HasValue)
  192. {
  193. res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
  194. }
  195. if (filter.Contains("res@size"))
  196. {
  197. if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength)
  198. {
  199. var size = streamInfo.TargetSize;
  200. if (size.HasValue)
  201. {
  202. res.SetAttribute("size", size.Value.ToString(_usCulture));
  203. }
  204. }
  205. }
  206. var targetAudioBitrate = streamInfo.TargetAudioBitrate;
  207. var targetSampleRate = streamInfo.TargetAudioSampleRate;
  208. var targetChannels = streamInfo.TargetAudioChannels;
  209. if (targetChannels.HasValue)
  210. {
  211. res.SetAttribute("nrAudioChannels", targetChannels.Value.ToString(_usCulture));
  212. }
  213. if (targetSampleRate.HasValue)
  214. {
  215. res.SetAttribute("sampleFrequency", targetSampleRate.Value.ToString(_usCulture));
  216. }
  217. if (targetAudioBitrate.HasValue)
  218. {
  219. res.SetAttribute("bitrate", targetAudioBitrate.Value.ToString(_usCulture));
  220. }
  221. var mediaProfile = _profile.GetAudioMediaProfile(streamInfo.Container,
  222. streamInfo.AudioCodec,
  223. targetChannels,
  224. targetAudioBitrate);
  225. var filename = url.Substring(0, url.IndexOf('?'));
  226. var mimeType = mediaProfile == null || string.IsNullOrEmpty(mediaProfile.MimeType)
  227. ? MimeTypes.GetMimeType(filename)
  228. : mediaProfile.MimeType;
  229. var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(streamInfo.Container,
  230. streamInfo.TargetAudioCodec,
  231. targetAudioBitrate,
  232. targetSampleRate,
  233. targetChannels,
  234. streamInfo.IsDirectStream,
  235. streamInfo.RunTimeTicks,
  236. streamInfo.TranscodeSeekInfo);
  237. res.SetAttribute("protocolInfo", String.Format(
  238. "http-get:*:{0}:{1}",
  239. mimeType,
  240. contentFeatures
  241. ));
  242. container.AppendChild(res);
  243. }
  244. public XmlElement GetFolderElement(XmlDocument doc, Folder folder, int childCount, Filter filter)
  245. {
  246. var container = doc.CreateElement(string.Empty, "container", NS_DIDL);
  247. container.SetAttribute("restricted", "0");
  248. container.SetAttribute("searchable", "1");
  249. container.SetAttribute("childCount", childCount.ToString(_usCulture));
  250. container.SetAttribute("id", folder.Id.ToString("N"));
  251. var parent = folder.Parent;
  252. if (parent == null)
  253. {
  254. container.SetAttribute("parentID", "0");
  255. }
  256. else
  257. {
  258. container.SetAttribute("parentID", parent.Id.ToString("N"));
  259. }
  260. AddCommonFields(folder, container, filter);
  261. AddCover(folder, container);
  262. return container;
  263. }
  264. //private void AddBookmarkInfo(BaseItem item, User user, XmlElement element)
  265. //{
  266. // var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
  267. // if (userdata.PlaybackPositionTicks > 0)
  268. // {
  269. // var dcmInfo = element.OwnerDocument.CreateElement("sec", "dcmInfo", NS_SEC);
  270. // dcmInfo.InnerText = string.Format("BM={0}", Convert.ToInt32(TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds).ToString(_usCulture));
  271. // element.AppendChild(dcmInfo);
  272. // }
  273. //}
  274. /// <summary>
  275. /// Adds fields used by both items and folders
  276. /// </summary>
  277. /// <param name="item">The item.</param>
  278. /// <param name="element">The element.</param>
  279. /// <param name="filter">The filter.</param>
  280. private void AddCommonFields(BaseItem item, XmlElement element, Filter filter)
  281. {
  282. if (filter.Contains("dc:title"))
  283. {
  284. AddValue(element, "dc", "title", item.Name, NS_DC);
  285. }
  286. element.AppendChild(CreateObjectClass(element.OwnerDocument, item));
  287. if (filter.Contains("dc:date"))
  288. {
  289. if (item.PremiereDate.HasValue)
  290. {
  291. AddValue(element, "dc", "date", item.PremiereDate.Value.ToString("o"), NS_DC);
  292. }
  293. }
  294. foreach (var genre in item.Genres)
  295. {
  296. AddValue(element, "upnp", "genre", genre, NS_UPNP);
  297. }
  298. foreach (var studio in item.Studios)
  299. {
  300. AddValue(element, "upnp", "publisher", studio, NS_UPNP);
  301. }
  302. if (filter.Contains("dc:description"))
  303. {
  304. if (!string.IsNullOrWhiteSpace(item.Overview))
  305. {
  306. AddValue(element, "dc", "description", item.Overview, NS_DC);
  307. }
  308. }
  309. if (filter.Contains("upnp:longDescription"))
  310. {
  311. if (!string.IsNullOrWhiteSpace(item.Overview))
  312. {
  313. AddValue(element, "upnp", "longDescription", item.Overview, NS_UPNP);
  314. }
  315. }
  316. if (!string.IsNullOrEmpty(item.OfficialRating))
  317. {
  318. if (filter.Contains("dc:rating"))
  319. {
  320. AddValue(element, "dc", "rating", item.OfficialRating, NS_DC);
  321. }
  322. if (filter.Contains("upnp:rating"))
  323. {
  324. AddValue(element, "upnp", "rating", item.OfficialRating, NS_UPNP);
  325. }
  326. }
  327. AddPeople(item, element);
  328. }
  329. private XmlElement CreateObjectClass(XmlDocument result, BaseItem item)
  330. {
  331. var objectClass = result.CreateElement("upnp", "class", NS_UPNP);
  332. if (item.IsFolder)
  333. {
  334. string classType = null;
  335. if (!_profile.RequiresPlainFolders)
  336. {
  337. if (item is MusicAlbum)
  338. {
  339. classType = "object.container.album.musicAlbum";
  340. }
  341. else if (item is MusicArtist)
  342. {
  343. classType = "object.container.person.musicArtist";
  344. }
  345. else if (item is Series || item is Season || item is BoxSet)
  346. {
  347. classType = "object.container.album.videoAlbum";
  348. }
  349. }
  350. objectClass.InnerText = classType ?? "object.container.storageFolder";
  351. }
  352. else if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
  353. {
  354. objectClass.InnerText = "object.item.audioItem.musicTrack";
  355. }
  356. else if (string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase))
  357. {
  358. objectClass.InnerText = "object.item.imageItem.photo";
  359. }
  360. else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
  361. {
  362. if (!_profile.RequiresPlainVideoItems && item is Movie)
  363. {
  364. objectClass.InnerText = "object.item.videoItem.movie";
  365. }
  366. else
  367. {
  368. objectClass.InnerText = "object.item.videoItem";
  369. }
  370. }
  371. else
  372. {
  373. throw new NotSupportedException();
  374. }
  375. return objectClass;
  376. }
  377. private void AddPeople(BaseItem item, XmlElement element)
  378. {
  379. var types = new[] { PersonType.Director, PersonType.Writer, PersonType.Producer, PersonType.Composer, "Creator" };
  380. foreach (var actor in item.People)
  381. {
  382. var type = types.FirstOrDefault(i => string.Equals(i, actor.Type, StringComparison.OrdinalIgnoreCase) || string.Equals(i, actor.Role, StringComparison.OrdinalIgnoreCase))
  383. ?? PersonType.Actor;
  384. AddValue(element, "upnp", type.ToLower(), actor.Name, NS_UPNP);
  385. }
  386. }
  387. private void AddGeneralProperties(BaseItem item, XmlElement element, Filter filter)
  388. {
  389. AddCommonFields(item, element, filter);
  390. var audio = item as Audio;
  391. if (audio != null)
  392. {
  393. foreach (var artist in audio.Artists)
  394. {
  395. AddValue(element, "upnp", "artist", artist, NS_UPNP);
  396. }
  397. if (!string.IsNullOrEmpty(audio.Album))
  398. {
  399. AddValue(element, "upnp", "album", audio.Album, NS_UPNP);
  400. }
  401. if (!string.IsNullOrEmpty(audio.AlbumArtist))
  402. {
  403. AddValue(element, "upnp", "albumArtist", audio.AlbumArtist, NS_UPNP);
  404. }
  405. }
  406. var album = item as MusicAlbum;
  407. if (album != null)
  408. {
  409. if (!string.IsNullOrEmpty(album.AlbumArtist))
  410. {
  411. AddValue(element, "upnp", "artist", album.AlbumArtist, NS_UPNP);
  412. AddValue(element, "upnp", "albumArtist", album.AlbumArtist, NS_UPNP);
  413. }
  414. }
  415. var musicVideo = item as MusicVideo;
  416. if (musicVideo != null)
  417. {
  418. if (!string.IsNullOrEmpty(musicVideo.Artist))
  419. {
  420. AddValue(element, "upnp", "artist", musicVideo.Artist, NS_UPNP);
  421. }
  422. if (!string.IsNullOrEmpty(musicVideo.Album))
  423. {
  424. AddValue(element, "upnp", "album", musicVideo.Album, NS_UPNP);
  425. }
  426. }
  427. if (item.IndexNumber.HasValue)
  428. {
  429. AddValue(element, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(_usCulture), NS_UPNP);
  430. }
  431. }
  432. private void AddValue(XmlElement elem, string prefix, string name, string value, string namespaceUri)
  433. {
  434. try
  435. {
  436. var date = elem.OwnerDocument.CreateElement(prefix, name, namespaceUri);
  437. date.InnerText = value;
  438. elem.AppendChild(date);
  439. }
  440. catch (XmlException)
  441. {
  442. //_logger.Error("Error adding xml value: " + value);
  443. }
  444. }
  445. private void AddCover(BaseItem item, XmlElement element)
  446. {
  447. var imageInfo = GetImageInfo(item);
  448. if (imageInfo == null)
  449. {
  450. return;
  451. }
  452. var result = element.OwnerDocument;
  453. var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight);
  454. var icon = result.CreateElement("upnp", "albumArtURI", NS_UPNP);
  455. var profile = result.CreateAttribute("dlna", "profileID", NS_DLNA);
  456. profile.InnerText = _profile.AlbumArtPn;
  457. icon.SetAttributeNode(profile);
  458. icon.InnerText = albumartUrlInfo.Url;
  459. element.AppendChild(icon);
  460. var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth, _profile.MaxIconHeight);
  461. icon = result.CreateElement("upnp", "icon", NS_UPNP);
  462. profile = result.CreateAttribute("dlna", "profileID", NS_DLNA);
  463. profile.InnerText = _profile.AlbumArtPn;
  464. icon.SetAttributeNode(profile);
  465. icon.InnerText = iconUrlInfo.Url;
  466. element.AppendChild(icon);
  467. if (!_profile.EnableAlbumArtInDidl)
  468. {
  469. return;
  470. }
  471. var res = result.CreateElement(string.Empty, "res", NS_DIDL);
  472. res.InnerText = albumartUrlInfo.Url;
  473. var width = albumartUrlInfo.Width;
  474. var height = albumartUrlInfo.Height;
  475. var contentFeatures = new ContentFeatureBuilder(_profile).BuildImageHeader("jpg", width, height);
  476. res.SetAttribute("protocolInfo", String.Format(
  477. "http-get:*:{0}:{1}",
  478. "image/jpeg",
  479. contentFeatures
  480. ));
  481. if (width.HasValue && height.HasValue)
  482. {
  483. res.SetAttribute("resolution", string.Format("{0}x{1}", width.Value, height.Value));
  484. }
  485. element.AppendChild(res);
  486. }
  487. private ImageDownloadInfo GetImageInfo(BaseItem item)
  488. {
  489. if (item.HasImage(ImageType.Primary))
  490. {
  491. return GetImageInfo(item, ImageType.Primary);
  492. }
  493. if (item.HasImage(ImageType.Thumb))
  494. {
  495. return GetImageInfo(item, ImageType.Thumb);
  496. }
  497. if (item is Audio || item is Episode)
  498. {
  499. item = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Primary));
  500. if (item != null)
  501. {
  502. return GetImageInfo(item, ImageType.Primary);
  503. }
  504. }
  505. return null;
  506. }
  507. private ImageDownloadInfo GetImageInfo(BaseItem item, ImageType type)
  508. {
  509. var imageInfo = item.GetImageInfo(type, 0);
  510. string tag = null;
  511. try
  512. {
  513. tag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
  514. }
  515. catch
  516. {
  517. }
  518. int? width = null;
  519. int? height = null;
  520. try
  521. {
  522. var size = _imageProcessor.GetImageSize(imageInfo.Path, imageInfo.DateModified);
  523. width = Convert.ToInt32(size.Width);
  524. height = Convert.ToInt32(size.Height);
  525. }
  526. catch
  527. {
  528. }
  529. return new ImageDownloadInfo
  530. {
  531. ItemId = item.Id.ToString("N"),
  532. Type = ImageType.Primary,
  533. ImageTag = tag,
  534. Width = width,
  535. Height = height
  536. };
  537. }
  538. class ImageDownloadInfo
  539. {
  540. internal string ItemId;
  541. internal string ImageTag;
  542. internal ImageType Type;
  543. internal int? Width;
  544. internal int? Height;
  545. }
  546. class ImageUrlInfo
  547. {
  548. internal string Url;
  549. internal int? Width;
  550. internal int? Height;
  551. }
  552. private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int? maxWidth, int? maxHeight)
  553. {
  554. var url = string.Format("{0}/Items/{1}/Images/{2}?params=",
  555. _serverAddress,
  556. info.ItemId,
  557. info.Type);
  558. var options = new List<string>
  559. {
  560. info.ImageTag,
  561. "jpg"
  562. };
  563. if (maxWidth.HasValue)
  564. {
  565. options.Add(maxWidth.Value.ToString(_usCulture));
  566. }
  567. if (maxHeight.HasValue)
  568. {
  569. options.Add(maxHeight.Value.ToString(_usCulture));
  570. }
  571. url += string.Join(";", options.ToArray());
  572. var width = info.Width;
  573. var height = info.Height;
  574. if (width.HasValue && height.HasValue)
  575. {
  576. if (maxWidth.HasValue || maxHeight.HasValue)
  577. {
  578. var newSize = DrawingUtils.Resize(new ImageSize
  579. {
  580. Height = height.Value,
  581. Width = width.Value
  582. }, null, null, maxWidth, maxHeight);
  583. width = Convert.ToInt32(newSize.Width);
  584. height = Convert.ToInt32(newSize.Height);
  585. }
  586. }
  587. return new ImageUrlInfo
  588. {
  589. Url = url,
  590. Width = width,
  591. Height = height
  592. };
  593. }
  594. }
  595. }