PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/Sources/WifiRemote/PluginConnection/TVSeriesHelper.cs

https://github.com/Kucheek/WifiRemote
C# | 494 lines | 283 code | 61 blank | 150 comment | 73 complexity | b922ab766140176cd5a3028bb0d8034b MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using WindowPlugins.GUITVSeries;
  6. using MediaPortal.GUI.Library;
  7. using System.Threading;
  8. using MediaPortal.Player;
  9. using WifiRemote.PluginConnection;
  10. namespace WifiRemote
  11. {
  12. /// <summary>
  13. /// Helper class for MpTvSeries actions
  14. /// </summary>
  15. class TVSeriesHelper
  16. {
  17. static VideoHandler player = null;
  18. static PlayListPlayer playlistPlayer;
  19. protected delegate void PlayEpisodeAsyncDelegate(DBEpisode episode, bool resume, int startPosition);
  20. protected delegate void PlaySeasonAsyncDelegate(int seriesId, int seasonNumber, bool autostart, int offset, bool onlyUnwatched, bool switchToPlaylistView);
  21. protected delegate void PlaySeriesAsyncDelegate(int seriesId, bool autostart, int offset, bool onlyUnwatched, bool switchToPlaylistView);
  22. /// <summary>
  23. /// Get a series id by show name
  24. /// </summary>
  25. /// <param name="seriesName">Name of the series to look for</param>
  26. /// <returns>A series id or null if none was found</returns>
  27. public static int? GetSeriesIdByName(string seriesName)
  28. {
  29. SQLCondition conditions = new SQLCondition();
  30. conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cPrettyName, seriesName, SQLConditionType.Like);
  31. List<DBSeries> seriesList = DBSeries.Get(conditions);
  32. // Return best matching series or null if no result was found
  33. if (seriesList.Count == 1)
  34. {
  35. return seriesList[0][DBOnlineSeries.cID];
  36. }
  37. else if (seriesList.Count > 1)
  38. {
  39. foreach (DBSeries series in seriesList)
  40. {
  41. if (series[DBOnlineSeries.cPrettyName].Equals(seriesName))
  42. {
  43. return series[DBOnlineSeries.cID];
  44. }
  45. }
  46. return seriesList[0][DBOnlineSeries.cID];
  47. }
  48. else
  49. {
  50. return null;
  51. }
  52. }
  53. /// <summary>
  54. /// Playback the first unwatched episode for a series using TVSeries internal Video Handler
  55. /// If no Unwatched episodes exists, play the Most Recently Aired
  56. ///
  57. /// Taken from Trakt-for-MediaPortal:
  58. /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs
  59. /// </summary>
  60. /// <param name="seriesid">series id of episode</param>
  61. /// <param name="resume">Resume from last stop?</param>
  62. public static void PlayFirstUnwatchedEpisode(int seriesid, bool resume)
  63. {
  64. var episodes = DBEpisode.Get(seriesid);
  65. if (episodes == null || episodes.Count == 0) return;
  66. // filter out anything we can't play
  67. episodes.RemoveAll(e => string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  68. if (episodes.Count == 0) return;
  69. // sort episodes using DBEpisode sort comparer
  70. // this takes into consideration Aired/DVD order and Specials in-line sorting
  71. episodes.Sort();
  72. // get first episode unwatched, otherwise get most recently aired
  73. var episode = episodes.Where(e => e[DBOnlineEpisode.cWatched] == 0).FirstOrDefault();
  74. if (episode == null)
  75. {
  76. WifiRemote.LogMessage("No Unwatched episodes found, Playing most recent episode", WifiRemote.LogType.Info);
  77. episode = episodes.LastOrDefault();
  78. }
  79. if (episode != null)
  80. {
  81. PlayEpisode(episode, resume);
  82. }
  83. }
  84. /// <summary>
  85. /// Play a random episode of a series
  86. /// </summary>
  87. /// <param name="seriesId">ID of a series</param>
  88. /// <param name="resume">Resume from last stop?</param>
  89. public static void PlayRandomEpisode(int seriesId, bool resume)
  90. {
  91. List<DBEpisode> episodes = DBEpisode.Get(seriesId);
  92. if (episodes == null || episodes.Count == 0) return;
  93. // filter out anything we can't play
  94. episodes.RemoveAll(e => string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  95. if (episodes.Count == 0) return;
  96. DBEpisode episode = episodes.GetRandomElement<DBEpisode>();
  97. if (episode != null)
  98. {
  99. PlayEpisode(episode, resume);
  100. }
  101. }
  102. /// <summary>
  103. /// Play all episodes of a season
  104. /// </summary>
  105. /// <param name="seriesId">ID of a series</param>
  106. /// <param name="seasonNumber">Number of the season</param>
  107. /// <param name="onlyUnwatched">Play only unwatched episodes</param>
  108. /// <param name="autostart">If yes, automatically starts playback with the first episode</param>
  109. /// <param name="startIndex">Index of the item with which playback should start</param>
  110. /// <param name="switchToPlaylistView">If yes the playlistview will be shown</param>
  111. public static void PlaySeason(int seriesId, int seasonNumber, bool autostart, int startIndex, bool onlyUnwatched, bool switchToPlaylistView)
  112. {
  113. if (GUIGraphicsContext.form.InvokeRequired)
  114. {
  115. PlaySeasonAsyncDelegate d = new PlaySeasonAsyncDelegate(PlaySeason);
  116. GUIGraphicsContext.form.Invoke(d, new object[] { seriesId, seasonNumber, autostart, startIndex, onlyUnwatched, switchToPlaylistView });
  117. return;
  118. }
  119. List<DBEpisode> episodes = DBEpisode.Get(seriesId, seasonNumber);
  120. if (episodes == null || episodes.Count == 0) return;
  121. // filter out anything we can't play
  122. episodes.RemoveAll(e => string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  123. // filter out watched episodes
  124. if (onlyUnwatched)
  125. {
  126. episodes.RemoveAll(e => e[DBOnlineEpisode.cWatched] != 0);
  127. }
  128. if (episodes.Count == 0) return;
  129. // Sort episodes and add them to the MP-TVSeries playlist player
  130. // Setup playlist player
  131. if (playlistPlayer == null)
  132. {
  133. playlistPlayer = PlayListPlayer.SingletonPlayer;
  134. playlistPlayer.PlaylistAutoPlay = true;
  135. playlistPlayer.RepeatPlaylist = DBOption.GetOptions(DBOption.cRepeatPlaylist);
  136. }
  137. playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_TVSERIES).Clear();
  138. episodes.Sort();
  139. foreach (DBEpisode episode in episodes)
  140. {
  141. PlayListItem playlistItem = new PlayListItem(episode);
  142. playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_TVSERIES).Add(playlistItem);
  143. }
  144. //automatically start playing the playlist
  145. if (autostart)
  146. {
  147. // and activate the playlist window if its not activated yet
  148. if (switchToPlaylistView)
  149. {
  150. GUIWindowManager.ActivateWindow(GUITVSeriesPlayList.GetWindowID);
  151. }
  152. playlistPlayer.CurrentPlaylistType = PlayListType.PLAYLIST_TVSERIES;
  153. playlistPlayer.Reset();
  154. playlistPlayer.Play(0);
  155. }
  156. }
  157. /// <summary>
  158. /// Play all episodes of a series
  159. /// </summary>
  160. /// <param name="seriesId">ID of a series</param>
  161. /// <param name="onlyUnwatched">Play only unwatched episodes</param>
  162. /// <param name="autostart">If yes, automatically starts playback with the first episode</param>
  163. /// <param name="startIndex">Index of the item with which playback should start</param>
  164. /// <param name="switchToPlaylistView">If yes the playlistview will be shown</param>
  165. public static void PlaySeries(int seriesId, bool autostart, int startIndex, bool onlyUnwatched, bool switchToPlaylistView)
  166. {
  167. if (GUIGraphicsContext.form.InvokeRequired)
  168. {
  169. PlaySeriesAsyncDelegate d = new PlaySeriesAsyncDelegate(PlaySeries);
  170. GUIGraphicsContext.form.Invoke(d, new object[] { seriesId, autostart, startIndex, onlyUnwatched, switchToPlaylistView });
  171. return;
  172. }
  173. List<DBEpisode> episodes = DBEpisode.Get(seriesId);
  174. if (episodes == null || episodes.Count == 0) return;
  175. // filter out anything we can't play
  176. episodes.RemoveAll(e => string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  177. // filter out watched episodes
  178. if (onlyUnwatched)
  179. {
  180. episodes.RemoveAll(e => e[DBOnlineEpisode.cWatched] != 0);
  181. }
  182. if (episodes.Count == 0) return;
  183. // Sort episodes and add them to the MP-TVSeries playlist player
  184. // Setup playlist player
  185. if (playlistPlayer == null)
  186. {
  187. playlistPlayer = PlayListPlayer.SingletonPlayer;
  188. playlistPlayer.PlaylistAutoPlay = true;
  189. playlistPlayer.RepeatPlaylist = DBOption.GetOptions(DBOption.cRepeatPlaylist);
  190. }
  191. playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_TVSERIES).Clear();
  192. episodes.Sort();
  193. foreach (DBEpisode episode in episodes)
  194. {
  195. PlayListItem playlistItem = new PlayListItem(episode);
  196. playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_TVSERIES).Add(playlistItem);
  197. }
  198. //automatically start playing the playlist
  199. if (autostart)
  200. {
  201. // and activate the playlist window if its not activated yet
  202. if (switchToPlaylistView)
  203. {
  204. GUIWindowManager.ActivateWindow(GUITVSeriesPlayList.GetWindowID);
  205. }
  206. playlistPlayer.CurrentPlaylistType = PlayListType.PLAYLIST_TVSERIES;
  207. playlistPlayer.Reset();
  208. playlistPlayer.Play(0);
  209. }
  210. }
  211. /// <summary>
  212. /// Play an episode of a specific series and season
  213. ///
  214. /// Thanks to Trakt-for-MediaPortal:
  215. /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs
  216. /// </summary>
  217. /// <param name="seriesId">ID of the series</param>
  218. /// <param name="seasonNumber">Number of the season</param>
  219. /// <param name="episodeNumber">Number of the episode</param>
  220. /// <paraparam name="resume">Resume from last stop?</paraparam>
  221. /// <param name="startPosition">Position from which the video should start in seconds (e.g. StartPosition=180 will start the episode 3 minutes into the video). Will be ignored if AskToResume is true.</param>
  222. public static void Play(int seriesId, int seasonNumer, int episodeNumber, bool resume, int startPosition = 0)
  223. {
  224. var episodes = DBEpisode.Get(seriesId, seasonNumer);
  225. var episode = episodes.FirstOrDefault(e => (e[DBEpisode.cEpisodeIndex] == episodeNumber || e[DBEpisode.cEpisodeIndex2] == episodeNumber) && !string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  226. if (episode == null) return;
  227. PlayEpisode(episode, resume, startPosition);
  228. }
  229. /// <summary>
  230. /// Play an episode of a specific series and season
  231. ///
  232. /// Thanks to Trakt-for-MediaPortal:
  233. /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs
  234. /// </summary>
  235. /// <param name="episodeId">ID of the episode</param>
  236. /// <paraparam name="resume">Resume from last stop?</paraparam>
  237. /// <param name="startPosition">Position from which the video should start in seconds (e.g. StartPosition=180 will start the episode 3 minutes into the video). Will be ignored if AskToResume is true.</param>
  238. public static void PlayEpisode(int episodeId, bool resume, int startPosition)
  239. {
  240. var episodes = DBEpisode.Get(new SQLCondition(new DBTable("online_episodes"), "EpisodeID", new DBValue(episodeId), SQLConditionType.Equal));
  241. var episode = episodes.FirstOrDefault(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  242. if (episode == null) return;
  243. PlayEpisode(episode, resume, startPosition);;
  244. }
  245. /// <summary>
  246. /// Play an episode of a specific series and season
  247. ///
  248. /// Thanks to Trakt-for-MediaPortal:
  249. /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs
  250. /// </summary>
  251. /// <param name="compositeId">Composite id of the episode</param>
  252. /// <paraparam name="resume">Resume from last stop?</paraparam>
  253. /// <param name="startPosition">Position from which the video should start in seconds (e.g. StartPosition=180 will start the episode 3 minutes into the video). Will be ignored if AskToResume is true.</param>
  254. public static void PlayEpisode(String compositeId, bool resume, int startPosition)
  255. {
  256. var episodes = DBEpisode.Get(new SQLCondition(new DBTable("online_episodes"), "CompositeID", new DBValue(compositeId), SQLConditionType.Equal));
  257. var episode = episodes.FirstOrDefault(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  258. if (episode == null) return;
  259. PlayEpisode(episode, resume, startPosition); ;
  260. }
  261. /// <summary>
  262. /// Play an episode
  263. ///
  264. /// Thanks to Trakt-for-MediaPortal:
  265. /// https://github.com/Technicolour/Trakt-for-Mediaportal/blob/master/TraktPlugin/TraktHandlers/TVSeries.cs
  266. /// </summary>
  267. /// <param name="episode">A valid tvseries episode</param>
  268. /// <param name="resume">Resume from last stop?</param>
  269. /// <param name="startPosition">Postion from where playback should be started (only valid if resum=false)</param>
  270. /// <returns></returns>
  271. private static void PlayEpisode(DBEpisode episode, bool resume, int startPosition = 0)
  272. {
  273. // Play on a new thread
  274. ThreadStart ts = delegate() { DoPlayEpisode(episode, resume, startPosition); };
  275. Thread playEpisodeAsync = new Thread(ts);
  276. playEpisodeAsync.Start();
  277. }
  278. /// <summary>
  279. /// Play episode async
  280. /// </summary>
  281. /// <param name="episode">Episode to play</param>
  282. /// <param name="startPosition">Postion from where playback should be started (only valid if resum=false)</param>
  283. /// <param name="resume">Resume from last stop?</param>
  284. private static void DoPlayEpisode(DBEpisode episode, bool resume, int startPosition)
  285. {
  286. if (GUIGraphicsContext.form.InvokeRequired)
  287. {
  288. PlayEpisodeAsyncDelegate d = new PlayEpisodeAsyncDelegate(DoPlayEpisode);
  289. GUIGraphicsContext.form.Invoke(d, new object[] { episode, resume, startPosition });
  290. return;
  291. }
  292. WifiRemote.LogMessage("Play episode (resume: " + resume + ", pos: " + startPosition, WifiRemote.LogType.Debug);
  293. if (player == null) player = new VideoHandler();
  294. // Reset stopTime if resume is false
  295. if (!resume)
  296. {
  297. episode[DBEpisode.cStopTime] = 0;
  298. }
  299. player.ResumeOrPlay((DBEpisode)episode);
  300. if (!resume && startPosition > 0)
  301. {
  302. g_Player.SeekAbsolute(startPosition);
  303. }
  304. }
  305. /// <summary>
  306. /// Is the dialog a series rating dialog
  307. /// </summary>
  308. /// <param name="dialog">Dialog</param>
  309. /// <returns>true if dialog is a pin dialog, false otherwise</returns>
  310. internal static bool IsTvSeriesRatingDialog(MediaPortal.Dialogs.GUIDialogWindow dialog)
  311. {
  312. if (dialog.GetType().Equals(typeof(WindowPlugins.GUITVSeries.GUIUserRating)))
  313. {
  314. return true;
  315. }
  316. else
  317. {
  318. return false;
  319. }
  320. }
  321. /// <summary>
  322. /// Is the dialog a series pin dialog
  323. /// </summary>
  324. /// <param name="dialog">Dialog</param>
  325. /// <returns>true if dialog is a pin dialog, false otherwise</returns>
  326. internal static bool IsTvSeriesPinDialog(MediaPortal.Dialogs.GUIDialogWindow dialog)
  327. {
  328. if (dialog.GetType().Equals(typeof(WindowPlugins.GUITVSeries.GUIPinCode)))
  329. {
  330. return true;
  331. }
  332. else
  333. {
  334. return false;
  335. }
  336. }
  337. /// <summary>
  338. /// Show episode details
  339. /// </summary>
  340. /// <param name="seriesId">Id of series</param>
  341. /// <param name="seasonId">Id of season</param>
  342. /// <param name="episodeId">Id of episode</param>
  343. internal static void ShowEpisodeDetails(int seriesId, int seasonId, int episodeId)
  344. {
  345. if (seriesId > 0)
  346. {
  347. WindowPluginHelper.ActivateWindow(9811, "seriesid:" + seriesId + "|seasonidx:" + seasonId + "|episodeidx:" + episodeId);
  348. }
  349. }
  350. /// <summary>
  351. /// Show season details
  352. /// </summary>
  353. /// <param name="seriesId">Id of series</param>
  354. /// <param name="seasonId">Id of season</param>
  355. internal static void ShowSeasonDetails(int seriesId, int seasonId)
  356. {
  357. if (seriesId > 0)
  358. {
  359. WindowPluginHelper.ActivateWindow(9811, "seriesid:" + seriesId + "|seasonidx:" + seasonId);
  360. }
  361. }
  362. /// <summary>
  363. /// Show series details
  364. /// </summary>
  365. /// <param name="seriesId">Id of series</param>
  366. internal static void ShowSeriesDetails(int seriesId)
  367. {
  368. if (seriesId > 0)
  369. {
  370. WindowPluginHelper.ActivateWindow(9811, "seriesid:" + seriesId.ToString());
  371. }
  372. }
  373. /// <summary>
  374. /// Create PlayListItem from TvSeries episode id
  375. /// </summary>
  376. /// <param name="compositeId">Composite id of episode</param>
  377. /// <returns>PlayListItem item</returns>
  378. internal static MediaPortal.Playlists.PlayListItem CreatePlaylistItemFromEpisode(String compositeId)
  379. {
  380. var episodes = DBEpisode.Get(new SQLCondition(new DBTable("online_episodes"), "CompositeID", new DBValue(compositeId), SQLConditionType.Equal));
  381. var episode = episodes.FirstOrDefault(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename]));
  382. return CreatePlaylistItemFromEpisode(episode);
  383. }
  384. /// <summary>
  385. /// Create PlayListItem from TvSeries DBEpisode
  386. /// </summary>
  387. /// <param name="episode">DBEpisode</param>
  388. /// <returns>PlayListItem item</returns>
  389. private static MediaPortal.Playlists.PlayListItem CreatePlaylistItemFromEpisode(DBEpisode episode)
  390. {
  391. if (episode != null)
  392. {
  393. MediaPortal.Playlists.PlayListItem item = new MediaPortal.Playlists.PlayListItem();
  394. item.FileName = episode[DBEpisode.cFilename];
  395. item.Duration = episode[DBEpisode.cLocalPlaytime] / 1000;
  396. item.Description = episode[DBOnlineEpisode.cEpisodeName];
  397. return item;
  398. }
  399. return null;
  400. }
  401. /// <summary>
  402. /// Create PlayListItem from TvSeries show and season number
  403. /// </summary>
  404. /// <param name="seriesId">Id of show</param>
  405. /// <param name="seasonNumber">Season number</param>
  406. /// <returns>PlayListItem item</returns>
  407. internal static List<MediaPortal.Playlists.PlayListItem> CreatePlaylistItemsFromSeason(int seriesId, int seasonNumber)
  408. {
  409. List<MediaPortal.Playlists.PlayListItem> returnList = new List<MediaPortal.Playlists.PlayListItem>();
  410. var episodes = DBEpisode.Get(seriesId, seasonNumber);
  411. foreach (DBEpisode e in episodes)
  412. {
  413. returnList.Add(CreatePlaylistItemFromEpisode(e));
  414. }
  415. return returnList;
  416. }
  417. /// <summary>
  418. /// Create PlayListItem from TvSeries show
  419. /// </summary>
  420. /// <param name="seriesId">Id of show</param>
  421. /// <returns>PlayListItem item</returns>
  422. internal static List<MediaPortal.Playlists.PlayListItem> CreatePlaylistItemsFromShow(int seriesId)
  423. {
  424. List<MediaPortal.Playlists.PlayListItem> returnList = new List<MediaPortal.Playlists.PlayListItem>();
  425. var episodes = DBEpisode.Get(seriesId);
  426. foreach (DBEpisode e in episodes)
  427. {
  428. returnList.Add(CreatePlaylistItemFromEpisode(e));
  429. }
  430. return returnList;
  431. }
  432. }
  433. }