LiveTvDtoService.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. using MediaBrowser.Common;
  2. using MediaBrowser.Common.Extensions;
  3. using MediaBrowser.Controller.Drawing;
  4. using MediaBrowser.Controller.Dto;
  5. using MediaBrowser.Controller.Entities;
  6. using MediaBrowser.Controller.Library;
  7. using MediaBrowser.Controller.LiveTv;
  8. using MediaBrowser.Model.Entities;
  9. using MediaBrowser.Model.LiveTv;
  10. using MediaBrowser.Model.Logging;
  11. using System;
  12. using System.Linq;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. using MediaBrowser.Controller.Entities.TV;
  16. using MediaBrowser.Model.Dto;
  17. using MediaBrowser.Model.Extensions;
  18. namespace Emby.Server.Implementations.LiveTv
  19. {
  20. public class LiveTvDtoService
  21. {
  22. private readonly ILogger _logger;
  23. private readonly IImageProcessor _imageProcessor;
  24. private readonly IDtoService _dtoService;
  25. private readonly IApplicationHost _appHost;
  26. private readonly ILibraryManager _libraryManager;
  27. public LiveTvDtoService(IDtoService dtoService, IImageProcessor imageProcessor, ILogger logger, IApplicationHost appHost, ILibraryManager libraryManager)
  28. {
  29. _dtoService = dtoService;
  30. _imageProcessor = imageProcessor;
  31. _logger = logger;
  32. _appHost = appHost;
  33. _libraryManager = libraryManager;
  34. }
  35. public TimerInfoDto GetTimerInfoDto(TimerInfo info, ILiveTvService service, LiveTvProgram program, LiveTvChannel channel)
  36. {
  37. var dto = new TimerInfoDto
  38. {
  39. Id = GetInternalTimerId(service.Name, info.Id).ToString("N"),
  40. Overview = info.Overview,
  41. EndDate = info.EndDate,
  42. Name = info.Name,
  43. StartDate = info.StartDate,
  44. ExternalId = info.Id,
  45. ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"),
  46. Status = info.Status,
  47. SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) ? null : GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"),
  48. PrePaddingSeconds = info.PrePaddingSeconds,
  49. PostPaddingSeconds = info.PostPaddingSeconds,
  50. IsPostPaddingRequired = info.IsPostPaddingRequired,
  51. IsPrePaddingRequired = info.IsPrePaddingRequired,
  52. KeepUntil = info.KeepUntil,
  53. ExternalChannelId = info.ChannelId,
  54. ExternalSeriesTimerId = info.SeriesTimerId,
  55. ServiceName = service.Name,
  56. ExternalProgramId = info.ProgramId,
  57. Priority = info.Priority,
  58. RunTimeTicks = (info.EndDate - info.StartDate).Ticks,
  59. ServerId = _appHost.SystemId
  60. };
  61. if (!string.IsNullOrEmpty(info.ProgramId))
  62. {
  63. dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N");
  64. }
  65. if (program != null)
  66. {
  67. dto.ProgramInfo = _dtoService.GetBaseItemDto(program, new DtoOptions());
  68. if (info.Status != RecordingStatus.Cancelled && info.Status != RecordingStatus.Error)
  69. {
  70. dto.ProgramInfo.TimerId = dto.Id;
  71. dto.ProgramInfo.Status = info.Status.ToString();
  72. }
  73. dto.ProgramInfo.SeriesTimerId = dto.SeriesTimerId;
  74. if (!string.IsNullOrWhiteSpace(info.SeriesTimerId))
  75. {
  76. FillImages(dto.ProgramInfo, info.Name, info.SeriesId);
  77. }
  78. }
  79. if (channel != null)
  80. {
  81. dto.ChannelName = channel.Name;
  82. if (channel.HasImage(ImageType.Primary))
  83. {
  84. dto.ChannelPrimaryImageTag = GetImageTag(channel);
  85. }
  86. }
  87. return dto;
  88. }
  89. public SeriesTimerInfoDto GetSeriesTimerInfoDto(SeriesTimerInfo info, ILiveTvService service, string channelName)
  90. {
  91. var dto = new SeriesTimerInfoDto
  92. {
  93. Id = GetInternalSeriesTimerId(service.Name, info.Id).ToString("N"),
  94. Overview = info.Overview,
  95. EndDate = info.EndDate,
  96. Name = info.Name,
  97. StartDate = info.StartDate,
  98. ExternalId = info.Id,
  99. PrePaddingSeconds = info.PrePaddingSeconds,
  100. PostPaddingSeconds = info.PostPaddingSeconds,
  101. IsPostPaddingRequired = info.IsPostPaddingRequired,
  102. IsPrePaddingRequired = info.IsPrePaddingRequired,
  103. Days = info.Days.ToArray(),
  104. Priority = info.Priority,
  105. RecordAnyChannel = info.RecordAnyChannel,
  106. RecordAnyTime = info.RecordAnyTime,
  107. SkipEpisodesInLibrary = info.SkipEpisodesInLibrary,
  108. KeepUpTo = info.KeepUpTo,
  109. KeepUntil = info.KeepUntil,
  110. RecordNewOnly = info.RecordNewOnly,
  111. ExternalChannelId = info.ChannelId,
  112. ExternalProgramId = info.ProgramId,
  113. ServiceName = service.Name,
  114. ChannelName = channelName,
  115. ServerId = _appHost.SystemId
  116. };
  117. if (!string.IsNullOrEmpty(info.ChannelId))
  118. {
  119. dto.ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N");
  120. }
  121. if (!string.IsNullOrEmpty(info.ProgramId))
  122. {
  123. dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N");
  124. }
  125. dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days.ToArray(info.Days.Count));
  126. FillImages(dto, info.Name, info.SeriesId);
  127. return dto;
  128. }
  129. private void FillImages(BaseItemDto dto, string seriesName, string programSeriesId)
  130. {
  131. var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
  132. {
  133. IncludeItemTypes = new string[] { typeof(Series).Name },
  134. Name = seriesName,
  135. Limit = 1,
  136. ImageTypes = new ImageType[] { ImageType.Thumb },
  137. DtoOptions = new DtoOptions(false)
  138. }).FirstOrDefault();
  139. if (librarySeries != null)
  140. {
  141. var image = librarySeries.GetImageInfo(ImageType.Thumb, 0);
  142. if (image != null)
  143. {
  144. try
  145. {
  146. dto.ParentThumbImageTag = _imageProcessor.GetImageCacheTag(librarySeries, image);
  147. dto.ParentThumbItemId = librarySeries.Id.ToString("N");
  148. }
  149. catch (Exception ex)
  150. {
  151. }
  152. }
  153. image = librarySeries.GetImageInfo(ImageType.Backdrop, 0);
  154. if (image != null)
  155. {
  156. try
  157. {
  158. dto.ParentBackdropImageTags = new string[]
  159. {
  160. _imageProcessor.GetImageCacheTag(librarySeries, image)
  161. };
  162. dto.ParentBackdropItemId = librarySeries.Id.ToString("N");
  163. }
  164. catch (Exception ex)
  165. {
  166. }
  167. }
  168. }
  169. if (!string.IsNullOrWhiteSpace(programSeriesId))
  170. {
  171. var program = _libraryManager.GetItemList(new InternalItemsQuery
  172. {
  173. IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
  174. ExternalSeriesId = programSeriesId,
  175. Limit = 1,
  176. ImageTypes = new ImageType[] { ImageType.Primary },
  177. DtoOptions = new DtoOptions(false)
  178. }).FirstOrDefault();
  179. if (program != null)
  180. {
  181. var image = program.GetImageInfo(ImageType.Primary, 0);
  182. if (image != null)
  183. {
  184. try
  185. {
  186. dto.ParentPrimaryImageTag = _imageProcessor.GetImageCacheTag(program, image);
  187. dto.ParentPrimaryImageItemId = program.Id.ToString("N");
  188. }
  189. catch (Exception ex)
  190. {
  191. }
  192. }
  193. if (dto.ParentBackdropImageTags == null || dto.ParentBackdropImageTags.Length == 0)
  194. {
  195. image = program.GetImageInfo(ImageType.Backdrop, 0);
  196. if (image != null)
  197. {
  198. try
  199. {
  200. dto.ParentBackdropImageTags = new string[]
  201. {
  202. _imageProcessor.GetImageCacheTag(program, image)
  203. };
  204. dto.ParentBackdropItemId = program.Id.ToString("N");
  205. }
  206. catch (Exception ex)
  207. {
  208. }
  209. }
  210. }
  211. }
  212. }
  213. }
  214. private void FillImages(SeriesTimerInfoDto dto, string seriesName, string programSeriesId)
  215. {
  216. var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
  217. {
  218. IncludeItemTypes = new string[] { typeof(Series).Name },
  219. Name = seriesName,
  220. Limit = 1,
  221. ImageTypes = new ImageType[] { ImageType.Thumb },
  222. DtoOptions = new DtoOptions(false)
  223. }).FirstOrDefault();
  224. if (librarySeries != null)
  225. {
  226. var image = librarySeries.GetImageInfo(ImageType.Thumb, 0);
  227. if (image != null)
  228. {
  229. try
  230. {
  231. dto.ParentThumbImageTag = _imageProcessor.GetImageCacheTag(librarySeries, image);
  232. dto.ParentThumbItemId = librarySeries.Id.ToString("N");
  233. }
  234. catch (Exception ex)
  235. {
  236. }
  237. }
  238. image = librarySeries.GetImageInfo(ImageType.Backdrop, 0);
  239. if (image != null)
  240. {
  241. try
  242. {
  243. dto.ParentBackdropImageTags = new string[]
  244. {
  245. _imageProcessor.GetImageCacheTag(librarySeries, image)
  246. };
  247. dto.ParentBackdropItemId = librarySeries.Id.ToString("N");
  248. }
  249. catch (Exception ex)
  250. {
  251. }
  252. }
  253. }
  254. if (!string.IsNullOrWhiteSpace(programSeriesId))
  255. {
  256. var program = _libraryManager.GetItemList(new InternalItemsQuery
  257. {
  258. IncludeItemTypes = new string[] { typeof(Series).Name },
  259. Name = seriesName,
  260. Limit = 1,
  261. ImageTypes = new ImageType[] { ImageType.Primary },
  262. DtoOptions = new DtoOptions(false)
  263. }).FirstOrDefault() ?? _libraryManager.GetItemList(new InternalItemsQuery
  264. {
  265. IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
  266. ExternalSeriesId = programSeriesId,
  267. Limit = 1,
  268. ImageTypes = new ImageType[] { ImageType.Primary },
  269. DtoOptions = new DtoOptions(false)
  270. }).FirstOrDefault();
  271. if (program != null)
  272. {
  273. var image = program.GetImageInfo(ImageType.Primary, 0);
  274. if (image != null)
  275. {
  276. try
  277. {
  278. dto.ParentPrimaryImageTag = _imageProcessor.GetImageCacheTag(program, image);
  279. dto.ParentPrimaryImageItemId = program.Id.ToString("N");
  280. }
  281. catch (Exception ex)
  282. {
  283. }
  284. }
  285. if (dto.ParentBackdropImageTags == null || dto.ParentBackdropImageTags.Length == 0)
  286. {
  287. image = program.GetImageInfo(ImageType.Backdrop, 0);
  288. if (image != null)
  289. {
  290. try
  291. {
  292. dto.ParentBackdropImageTags = new string[]
  293. {
  294. _imageProcessor.GetImageCacheTag(program, image)
  295. };
  296. dto.ParentBackdropItemId = program.Id.ToString("N");
  297. }
  298. catch (Exception ex)
  299. {
  300. }
  301. }
  302. }
  303. }
  304. }
  305. }
  306. public DayPattern? GetDayPattern(DayOfWeek[] days)
  307. {
  308. DayPattern? pattern = null;
  309. if (days.Length > 0)
  310. {
  311. if (days.Length == 7)
  312. {
  313. pattern = DayPattern.Daily;
  314. }
  315. else if (days.Length == 2)
  316. {
  317. if (days.Contains(DayOfWeek.Saturday) && days.Contains(DayOfWeek.Sunday))
  318. {
  319. pattern = DayPattern.Weekends;
  320. }
  321. }
  322. else if (days.Length == 5)
  323. {
  324. if (days.Contains(DayOfWeek.Monday) && days.Contains(DayOfWeek.Tuesday) && days.Contains(DayOfWeek.Wednesday) && days.Contains(DayOfWeek.Thursday) && days.Contains(DayOfWeek.Friday))
  325. {
  326. pattern = DayPattern.Weekdays;
  327. }
  328. }
  329. }
  330. return pattern;
  331. }
  332. public LiveTvTunerInfoDto GetTunerInfoDto(string serviceName, LiveTvTunerInfo info, string channelName)
  333. {
  334. var dto = new LiveTvTunerInfoDto
  335. {
  336. Name = info.Name,
  337. Id = info.Id,
  338. Clients = info.Clients.ToArray(),
  339. ProgramName = info.ProgramName,
  340. SourceType = info.SourceType,
  341. Status = info.Status,
  342. ChannelName = channelName,
  343. Url = info.Url,
  344. CanReset = info.CanReset
  345. };
  346. if (!string.IsNullOrEmpty(info.ChannelId))
  347. {
  348. dto.ChannelId = GetInternalChannelId(serviceName, info.ChannelId).ToString("N");
  349. }
  350. if (!string.IsNullOrEmpty(info.RecordingId))
  351. {
  352. dto.RecordingId = GetInternalRecordingId(serviceName, info.RecordingId).ToString("N");
  353. }
  354. return dto;
  355. }
  356. internal string GetImageTag(IHasMetadata info)
  357. {
  358. try
  359. {
  360. return _imageProcessor.GetImageCacheTag(info, ImageType.Primary);
  361. }
  362. catch (Exception ex)
  363. {
  364. _logger.ErrorException("Error getting image info for {0}", ex, info.Name);
  365. }
  366. return null;
  367. }
  368. private const string InternalVersionNumber = "4";
  369. public Guid GetInternalChannelId(string serviceName, string externalId)
  370. {
  371. var name = serviceName + externalId + InternalVersionNumber;
  372. return _libraryManager.GetNewItemId(name.ToLower(), typeof(LiveTvChannel));
  373. }
  374. public Guid GetInternalTimerId(string serviceName, string externalId)
  375. {
  376. var name = serviceName + externalId + InternalVersionNumber;
  377. return name.ToLower().GetMD5();
  378. }
  379. public Guid GetInternalSeriesTimerId(string serviceName, string externalId)
  380. {
  381. var name = serviceName + externalId + InternalVersionNumber;
  382. return name.ToLower().GetMD5();
  383. }
  384. public Guid GetInternalProgramId(string serviceName, string externalId)
  385. {
  386. var name = serviceName + externalId + InternalVersionNumber;
  387. return _libraryManager.GetNewItemId(name.ToLower(), typeof(LiveTvProgram));
  388. }
  389. public Guid GetInternalRecordingId(string serviceName, string externalId)
  390. {
  391. var name = serviceName + externalId + InternalVersionNumber + "0";
  392. return _libraryManager.GetNewItemId(name.ToLower(), typeof(ILiveTvRecording));
  393. }
  394. private string GetItemExternalId(BaseItem item)
  395. {
  396. var externalId = item.ExternalId;
  397. if (string.IsNullOrWhiteSpace(externalId))
  398. {
  399. externalId = item.GetProviderId("ProviderExternalId");
  400. }
  401. return externalId;
  402. }
  403. public async Task<TimerInfo> GetTimerInfo(TimerInfoDto dto, bool isNew, LiveTvManager liveTv, CancellationToken cancellationToken)
  404. {
  405. var info = new TimerInfo
  406. {
  407. Overview = dto.Overview,
  408. EndDate = dto.EndDate,
  409. Name = dto.Name,
  410. StartDate = dto.StartDate,
  411. Status = dto.Status,
  412. PrePaddingSeconds = dto.PrePaddingSeconds,
  413. PostPaddingSeconds = dto.PostPaddingSeconds,
  414. IsPostPaddingRequired = dto.IsPostPaddingRequired,
  415. IsPrePaddingRequired = dto.IsPrePaddingRequired,
  416. KeepUntil = dto.KeepUntil,
  417. Priority = dto.Priority,
  418. SeriesTimerId = dto.ExternalSeriesTimerId,
  419. ProgramId = dto.ExternalProgramId,
  420. ChannelId = dto.ExternalChannelId,
  421. Id = dto.ExternalId
  422. };
  423. // Convert internal server id's to external tv provider id's
  424. if (!isNew && !string.IsNullOrEmpty(dto.Id) && string.IsNullOrEmpty(info.Id))
  425. {
  426. var timer = await liveTv.GetSeriesTimer(dto.Id, cancellationToken).ConfigureAwait(false);
  427. info.Id = timer.ExternalId;
  428. }
  429. if (!string.IsNullOrEmpty(dto.ChannelId) && string.IsNullOrEmpty(info.ChannelId))
  430. {
  431. var channel = liveTv.GetInternalChannel(dto.ChannelId);
  432. if (channel != null)
  433. {
  434. info.ChannelId = GetItemExternalId(channel);
  435. }
  436. }
  437. if (!string.IsNullOrEmpty(dto.ProgramId) && string.IsNullOrEmpty(info.ProgramId))
  438. {
  439. var program = liveTv.GetInternalProgram(dto.ProgramId);
  440. if (program != null)
  441. {
  442. info.ProgramId = GetItemExternalId(program);
  443. }
  444. }
  445. if (!string.IsNullOrEmpty(dto.SeriesTimerId) && string.IsNullOrEmpty(info.SeriesTimerId))
  446. {
  447. var timer = await liveTv.GetSeriesTimer(dto.SeriesTimerId, cancellationToken).ConfigureAwait(false);
  448. if (timer != null)
  449. {
  450. info.SeriesTimerId = timer.ExternalId;
  451. }
  452. }
  453. return info;
  454. }
  455. public async Task<SeriesTimerInfo> GetSeriesTimerInfo(SeriesTimerInfoDto dto, bool isNew, LiveTvManager liveTv, CancellationToken cancellationToken)
  456. {
  457. var info = new SeriesTimerInfo
  458. {
  459. Overview = dto.Overview,
  460. EndDate = dto.EndDate,
  461. Name = dto.Name,
  462. StartDate = dto.StartDate,
  463. PrePaddingSeconds = dto.PrePaddingSeconds,
  464. PostPaddingSeconds = dto.PostPaddingSeconds,
  465. IsPostPaddingRequired = dto.IsPostPaddingRequired,
  466. IsPrePaddingRequired = dto.IsPrePaddingRequired,
  467. Days = dto.Days.ToList(),
  468. Priority = dto.Priority,
  469. RecordAnyChannel = dto.RecordAnyChannel,
  470. RecordAnyTime = dto.RecordAnyTime,
  471. SkipEpisodesInLibrary = dto.SkipEpisodesInLibrary,
  472. KeepUpTo = dto.KeepUpTo,
  473. KeepUntil = dto.KeepUntil,
  474. RecordNewOnly = dto.RecordNewOnly,
  475. ProgramId = dto.ExternalProgramId,
  476. ChannelId = dto.ExternalChannelId,
  477. Id = dto.ExternalId
  478. };
  479. // Convert internal server id's to external tv provider id's
  480. if (!isNew && !string.IsNullOrEmpty(dto.Id) && string.IsNullOrEmpty(info.Id))
  481. {
  482. var timer = await liveTv.GetSeriesTimer(dto.Id, cancellationToken).ConfigureAwait(false);
  483. info.Id = timer.ExternalId;
  484. }
  485. if (!string.IsNullOrEmpty(dto.ChannelId) && string.IsNullOrEmpty(info.ChannelId))
  486. {
  487. var channel = liveTv.GetInternalChannel(dto.ChannelId);
  488. if (channel != null)
  489. {
  490. info.ChannelId = GetItemExternalId(channel);
  491. }
  492. }
  493. if (!string.IsNullOrEmpty(dto.ProgramId) && string.IsNullOrEmpty(info.ProgramId))
  494. {
  495. var program = liveTv.GetInternalProgram(dto.ProgramId);
  496. if (program != null)
  497. {
  498. info.ProgramId = GetItemExternalId(program);
  499. }
  500. }
  501. return info;
  502. }
  503. }
  504. }