PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/animeplugin3/MyAnimePlugin3/Windows/MainWindow.cs

https://bitbucket.org/gibwar/jmm-test
C# | 6383 lines | 4770 code | 1172 blank | 441 comment | 1268 complexity | 2668427969cd4f7a48e0ceea8b6abd0b MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows.Forms;
  4. using ConsoleApplication2.com.amazon.webservices;
  5. using MediaPortal.GUI.Library;
  6. using MediaPortal.Dialogs;
  7. using MyAnimePlugin3.ConfigFiles;
  8. using MyAnimePlugin3.DataHelpers;
  9. using System.IO;
  10. using Cornerstone.MP;
  11. using System.ComponentModel;
  12. using System.Threading;
  13. using System.Xml;
  14. using BinaryNorthwest;
  15. using System.Runtime.InteropServices;
  16. using MyAnimePlugin3.Downloads;
  17. using Action = MediaPortal.GUI.Library.Action;
  18. using System.Collections;
  19. using MyAnimePlugin3.ViewModel;
  20. using MyAnimePlugin3.ImageManagement;
  21. using MyAnimePlugin3.MultiSortLib;
  22. using MediaPortal.Player;
  23. namespace MyAnimePlugin3
  24. {
  25. public class MainWindow : GUIWindow, ISetupForm
  26. {
  27. #region GUI Controls
  28. [SkinControlAttribute(2)]
  29. protected GUIButtonControl btnDisplayOptions = null;
  30. //[SkinControlAttribute(3)] protected GUIButtonControl btnLayout = null;
  31. [SkinControlAttribute(4)]
  32. protected GUIButtonControl btnSettings = null;
  33. [SkinControlAttribute(11)]
  34. protected GUIButtonControl btnChangeLayout = null;
  35. [SkinControlAttribute(12)]
  36. protected GUIButtonControl btnSwitchUser = null;
  37. [SkinControlAttribute(920)] protected GUIButtonControl btnWindowContinueWatching = null;
  38. [SkinControlAttribute(921)] protected GUIButtonControl btnWindowUtilities = null;
  39. [SkinControlAttribute(922)] protected GUIButtonControl btnWindowCalendar = null;
  40. [SkinControlAttribute(923)] protected GUIButtonControl btnWindowDownloads = null;
  41. //[SkinControlAttribute(924)] protected GUIButtonControl btnWindowCollectionStats = null;
  42. [SkinControlAttribute(925)] protected GUIButtonControl btnWindowRecommendations = null;
  43. [SkinControlAttribute(926)] protected GUIButtonControl btnWindowRandom = null;
  44. [SkinControlAttribute(927)] protected GUIButtonControl btnWindowPlaylists = null;
  45. [SkinControlAttribute(50)]
  46. protected GUIFacadeControl m_Facade = null;
  47. //[SkinControlAttribute(51)]
  48. //protected GUIListControl test = null;
  49. //[SkinControlAttribute(526)] protected GUIImage loadingImage = null;
  50. // let the skins react to what we are displaying
  51. // all these controls are imported from Anime3_Dummy.xml
  52. [SkinControlAttribute(1232)]
  53. protected GUILabelControl dummyIsFanartLoaded = null;
  54. [SkinControlAttribute(1233)]
  55. protected GUILabelControl dummyIsDarkFanartLoaded = null;
  56. [SkinControlAttribute(1234)]
  57. protected GUILabelControl dummyIsLightFanartLoaded = null;
  58. [SkinControlAttribute(1235)]
  59. protected GUILabelControl dummyLayoutListMode = null;
  60. [SkinControlAttribute(1236)]
  61. protected GUILabelControl dummyLayoutFilmstripMode = null;
  62. [SkinControlAttribute(1242)]
  63. protected GUILabelControl dummyLayoutWideBanners = null;
  64. [SkinControlAttribute(1237)]
  65. protected GUILabelControl dummyIsSeries = null;
  66. [SkinControlAttribute(1238)]
  67. protected GUILabelControl dummyIsGroups = null;
  68. [SkinControlAttribute(1250)]
  69. protected GUILabelControl dummyIsGroupFilters = null;
  70. [SkinControlAttribute(1239)]
  71. protected GUILabelControl dummyIsEpisodes = null;
  72. [SkinControlAttribute(1240)]
  73. protected GUILabelControl dummyIsEpisodeTypes = null;
  74. [SkinControlAttribute(1241)]
  75. protected GUILabelControl dummyIsFanartColorAvailable = null;
  76. [SkinControlAttribute(1243)]
  77. protected GUILabelControl dummyIsWatched = null;
  78. [SkinControlAttribute(1244)]
  79. protected GUILabelControl dummyIsAvailable = null;
  80. [SkinControlAttribute(1245)]
  81. protected GUILabelControl dummyFave = null;
  82. [SkinControlAttribute(1246)]
  83. protected GUILabelControl dummyMissingEps = null;
  84. [SkinControlAttribute(1247)]
  85. protected GUILabelControl dummyUserHasVotedSeries = null;
  86. [SkinControlAttribute(3401)]
  87. protected GUILabelControl dummyQueueAniDB = null;
  88. [SkinControlAttribute(3402)]
  89. protected GUILabelControl dummyQueueHasher = null;
  90. [SkinControlAttribute(3403)]
  91. protected GUILabelControl dummyQueueImages = null;
  92. [SkinControlAttribute(3463)]
  93. protected GUIControl dummyFindActive = null;
  94. [SkinControlAttribute(3464)]
  95. protected GUIControl dummyFindModeT9 = null;
  96. [SkinControlAttribute(3465)]
  97. protected GUIControl dummyFindModeText = null;
  98. #endregion
  99. public static Listlevel listLevel = Listlevel.GroupFilter;
  100. public static object parentLevelObject = null;
  101. private static Random groupRandom = new Random();
  102. public static RandomSeriesEpisodeLevel RandomWindow_RandomLevel = RandomSeriesEpisodeLevel.All;
  103. public static RandomObjectType RandomWindow_RandomType = RandomObjectType.Series;
  104. public static object RandomWindow_LevelObject = null;
  105. public static AnimeSeriesVM RandomWindow_CurrentSeries = null;
  106. public static AnimeEpisodeVM RandomWindow_CurrentEpisode = null;
  107. public static int RandomWindow_MatchesFound = 0;
  108. public static bool RandomWindow_SeriesWatched = true;
  109. public static bool RandomWindow_SeriesUnwatched = true;
  110. public static bool RandomWindow_SeriesPartiallyWatched = true;
  111. public static bool RandomWindow_SeriesOnlyComplete = true;
  112. public static bool RandomWindow_SeriesAllCategories = true;
  113. public static string RandomWindow_SeriesCategories = "";
  114. public static bool RandomWindow_EpisodeWatched = true;
  115. public static bool RandomWindow_EpisodeUnwatched = true;
  116. public static bool RandomWindow_EpisodeAllCategories = true;
  117. public static string RandomWindow_EpisodeCategories = "";
  118. //private bool fanartSet = false;
  119. private readonly int artworkDelay = 5;
  120. private System.Timers.Timer displayGrpFilterTimer = null;
  121. private System.Timers.Timer displayGrpTimer = null;
  122. public static int? animeSeriesIDToBeRated = null;
  123. public static AnimePluginSettings settings = null;
  124. public static JMMServerHelper ServerHelper = new JMMServerHelper();
  125. public static List<string> completedTorrents = new List<string>();
  126. public static DownloadSearchCriteria currentDownloadSearch = null;
  127. public static List<DownloadSearchCriteria> downloadSearchHistory = new List<DownloadSearchCriteria>();
  128. public static List<List<TorrentLink>> downloadSearchResultsHistory = new List<List<TorrentLink>>();
  129. public static int LastFocusType = -1; //
  130. public static int LastFocusID = -1; //
  131. public static int GlobalSeriesID = -1; // either AnimeSeriesID
  132. public static int GlobalAnimeID = -1; // AnimeID
  133. public static int GlobalSeiyuuID = -1; // SeiyuuID
  134. public static int CurrentCalendarMonth = DateTime.Now.Month;
  135. public static int CurrentCalendarYear = DateTime.Now.Year;
  136. public static int CurrentCalendarButton = 4;
  137. public static VideoHandler vidHandler;
  138. public static UTorrentHelper uTorrent = new UTorrentHelper();
  139. public static View currentView = null;
  140. public static ViewClassification currentViewClassification = ViewClassification.Views;
  141. public static string currentStaticViewID = ""; // used to stored current year, genre etc in static views
  142. private GUIFacadeControl.Layout groupViewMode = GUIFacadeControl.Layout.List; // Poster List
  143. private GUIFacadeControl.Layout seriesViewMode = GUIFacadeControl.Layout.List;
  144. //private GUIFacadeControl.Layout episodeTypesViewMode = GUIFacadeControl.Layout.List; // List
  145. private GUIFacadeControl.Layout episodesViewMode = GUIFacadeControl.Layout.List; // List
  146. private List<GUIListItem> itemsForDelayedImgLoading = null;
  147. private BackgroundWorker workerFacade = null;
  148. private BackgroundWorker downloadImagesWorker = new BackgroundWorker();
  149. public static ImageDownloader imageHelper = null;
  150. private AsyncImageResource listPoster = null;
  151. private AsyncImageResource fanartTexture = null;
  152. //private bool isInitialGroupLoad = true;
  153. public static GroupFilterVM curGroupFilter = null;
  154. public static GroupFilterVM curGroupFilterSub = null;
  155. public static GroupFilterVM curGroupFilterSub2 = null;
  156. public static AnimeGroupVM curAnimeGroup = null;
  157. public static AnimeGroupVM curAnimeGroupViewed = null;
  158. public static AnimeSeriesVM curAnimeSeries = null;
  159. public static AnimeEpisodeTypeVM curAnimeEpisodeType = null;
  160. private AnimeEpisodeVM curAnimeEpisode = null;
  161. Dictionary<int, QuickSort> GroupFilterQuickSorts = null;
  162. private System.Timers.Timer searchTimer = null;
  163. private System.Timers.Timer autoUpdateTimer = null;
  164. private SearchCollection search = null;
  165. private List<GUIListItem> lstFacadeItems = null;
  166. private string searchSound = "click.wav";
  167. public delegate void OnToggleWatchedHandler(List<AnimeEpisodeVM> episodes, bool state);
  168. public event OnToggleWatchedHandler OnToggleWatched;
  169. protected void ToggleWatchedEvent(List<AnimeEpisodeVM> episodes, bool state)
  170. {
  171. if (OnToggleWatched != null)
  172. {
  173. OnToggleWatched(episodes, state);
  174. }
  175. }
  176. public delegate void OnRateSeriesHandler(AnimeSeriesVM series, string rateValue);
  177. public event OnRateSeriesHandler OnRateSeries;
  178. protected void RateSeriesEvent(AnimeSeriesVM series, string rateValue)
  179. {
  180. if (OnRateSeries != null)
  181. {
  182. OnRateSeries(series, rateValue);
  183. }
  184. }
  185. public MainWindow()
  186. {
  187. // get ID of windowplugin belonging to this setup
  188. // enter your own unique code
  189. GetID = Constants.PlugInInfo.ID;
  190. try
  191. {
  192. settings = new AnimePluginSettings();
  193. imageHelper = new ImageDownloader();
  194. imageHelper.Init();
  195. listPoster = new AsyncImageResource();
  196. listPoster.Property = "#Anime3.GroupSeriesPoster";
  197. listPoster.Delay = artworkDelay;
  198. fanartTexture = new AsyncImageResource();
  199. fanartTexture.Property = "#Anime3.Fanart.1";
  200. fanartTexture.Delay = artworkDelay;
  201. GroupFilterQuickSorts = new Dictionary<int, QuickSort>();
  202. //searching
  203. searchTimer = new System.Timers.Timer();
  204. searchTimer.AutoReset = true;
  205. searchTimer.Interval = settings.FindTimeout_s * 1000;
  206. searchTimer.Elapsed += new System.Timers.ElapsedEventHandler(searchTimer_Elapsed);
  207. //set the search key sound to the same sound for the REMOTE_1 key
  208. Key key = new Key('1', (int)Keys.D1);
  209. MediaPortal.GUI.Library.Action action = new MediaPortal.GUI.Library.Action();
  210. ActionTranslator.GetAction(GetID, key, ref action);
  211. searchSound = action.SoundFileName;
  212. // timer for automatic updates
  213. autoUpdateTimer = new System.Timers.Timer();
  214. autoUpdateTimer.AutoReset = true;
  215. autoUpdateTimer.Interval = 5 * 60 * 1000; // 5 minutes * 60 seconds
  216. autoUpdateTimer.Elapsed += new System.Timers.ElapsedEventHandler(autoUpdateTimer_Elapsed);
  217. downloadImagesWorker.DoWork += new DoWorkEventHandler(downloadImagesWorker_DoWork);
  218. this.OnToggleWatched += new OnToggleWatchedHandler(MainWindow_OnToggleWatched);
  219. g_Player.PlayBackEnded += new g_Player.EndedHandler(g_Player_PlayBackEnded);
  220. }
  221. catch (Exception ex)
  222. {
  223. BaseConfig.MyAnimeLog.Write(ex.ToString());
  224. throw;
  225. }
  226. }
  227. void MainWindow_OnToggleWatched(List<AnimeEpisodeVM> episodes, bool state)
  228. {
  229. string msg = string.Format("OnToggleWatched: {0} / {1}", episodes.Count, state);
  230. BaseConfig.MyAnimeLog.Write(msg);
  231. }
  232. private void DownloadAllImages()
  233. {
  234. //if (!downloadImagesWorker.IsBusy)
  235. // downloadImagesWorker.RunWorkerAsync();
  236. }
  237. void downloadImagesWorker_DoWork(object sender, DoWorkEventArgs e)
  238. {
  239. // 1. Download posters from AniDB
  240. List<JMMServerBinary.Contract_AniDBAnime> contracts = JMMServerVM.Instance.clientBinaryHTTP.GetAllAnime();
  241. int i = 0;
  242. foreach (JMMServerBinary.Contract_AniDBAnime anime in contracts)
  243. {
  244. //Thread.Sleep(5); // don't use too many resources
  245. imageHelper.DownloadAniDBCover(new AniDB_AnimeVM(anime), false);
  246. i++;
  247. //if (i == 80) break;
  248. }
  249. // 2. Download posters from TvDB
  250. List<JMMServerBinary.Contract_TvDB_ImagePoster> posters = JMMServerVM.Instance.clientBinaryHTTP.GetAllTvDBPosters(null);
  251. foreach (JMMServerBinary.Contract_TvDB_ImagePoster poster in posters)
  252. {
  253. //Thread.Sleep(5); // don't use too many resources
  254. imageHelper.DownloadTvDBPoster(new TvDB_ImagePosterVM(poster), false);
  255. }
  256. // 2a. Download posters from MovieDB
  257. List<JMMServerBinary.Contract_MovieDB_Poster> moviePosters = JMMServerVM.Instance.clientBinaryHTTP.GetAllMovieDBPosters(null);
  258. foreach (JMMServerBinary.Contract_MovieDB_Poster poster in moviePosters)
  259. {
  260. //Thread.Sleep(5); // don't use too many resources
  261. imageHelper.DownloadMovieDBPoster(new MovieDB_PosterVM(poster), false);
  262. }
  263. // 3. Download wide banners from TvDB
  264. List<JMMServerBinary.Contract_TvDB_ImageWideBanner> banners = JMMServerVM.Instance.clientBinaryHTTP.GetAllTvDBWideBanners(null);
  265. foreach (JMMServerBinary.Contract_TvDB_ImageWideBanner banner in banners)
  266. {
  267. //Thread.Sleep(5); // don't use too many resources
  268. imageHelper.DownloadTvDBWideBanner(new TvDB_ImageWideBannerVM(banner), false);
  269. }
  270. // 4. Download fanart from TvDB
  271. List<JMMServerBinary.Contract_TvDB_ImageFanart> fanarts = JMMServerVM.Instance.clientBinaryHTTP.GetAllTvDBFanart(null);
  272. foreach (JMMServerBinary.Contract_TvDB_ImageFanart fanart in fanarts)
  273. {
  274. //Thread.Sleep(5); // don't use too many resources
  275. imageHelper.DownloadTvDBFanart(new TvDB_ImageFanartVM(fanart), false);
  276. }
  277. // 4a. Download fanart from MovieDB
  278. List<JMMServerBinary.Contract_MovieDB_Fanart> movieFanarts = JMMServerVM.Instance.clientBinaryHTTP.GetAllMovieDBFanart(null);
  279. foreach (JMMServerBinary.Contract_MovieDB_Fanart fanart in movieFanarts)
  280. {
  281. //Thread.Sleep(5); // don't use too many resources
  282. imageHelper.DownloadMovieDBFanart(new MovieDB_FanartVM(fanart), false);
  283. }
  284. // 5. Download episode images from TvDB
  285. List<JMMServerBinary.Contract_TvDB_Episode> eps = JMMServerVM.Instance.clientBinaryHTTP.GetAllTvDBEpisodes(null);
  286. foreach (JMMServerBinary.Contract_TvDB_Episode episode in eps)
  287. {
  288. //Thread.Sleep(5); // don't use too many resources
  289. imageHelper.DownloadTvDBEpisode(new TvDB_EpisodeVM(episode), false);
  290. }
  291. // 6. Download posters from Trakt
  292. List<JMMServerBinary.Contract_Trakt_ImagePoster> traktPosters = JMMServerVM.Instance.clientBinaryHTTP.GetAllTraktPosters(null);
  293. foreach (JMMServerBinary.Contract_Trakt_ImagePoster traktposter in traktPosters)
  294. {
  295. //Thread.Sleep(5); // don't use too many resources
  296. if (string.IsNullOrEmpty(traktposter.ImageURL)) continue;
  297. imageHelper.DownloadTraktPoster(new Trakt_ImagePosterVM(traktposter), false);
  298. }
  299. // 7. Download fanart from Trakt
  300. List<JMMServerBinary.Contract_Trakt_ImageFanart> traktFanarts = JMMServerVM.Instance.clientBinaryHTTP.GetAllTraktFanart(null);
  301. foreach (JMMServerBinary.Contract_Trakt_ImageFanart traktFanart in traktFanarts)
  302. {
  303. //Thread.Sleep(5); // don't use too many resources
  304. if (string.IsNullOrEmpty(traktFanart.ImageURL)) continue;
  305. imageHelper.DownloadTraktFanart(new Trakt_ImageFanartVM(traktFanart), false);
  306. }
  307. // 8. Download episode images from Trakt
  308. List<JMMServerBinary.Contract_Trakt_Episode> traktEpisodes = JMMServerVM.Instance.clientBinaryHTTP.GetAllTraktEpisodes(null);
  309. foreach (JMMServerBinary.Contract_Trakt_Episode traktEp in traktEpisodes)
  310. {
  311. //Thread.Sleep(5); // don't use too many resources
  312. if (string.IsNullOrEmpty(traktEp.EpisodeImage)) continue;
  313. // special case for trak episodes
  314. // Trakt will return the fanart image when no episode image exists, but we don't want this
  315. int pos = traktEp.EpisodeImage.IndexOf(@"episodes/");
  316. if (pos <= 0) continue;
  317. imageHelper.DownloadTraktEpisode(new Trakt_EpisodeVM(traktEp), false);
  318. }
  319. }
  320. #region External Event Handlers
  321. #endregion
  322. public override bool Init()
  323. {
  324. try
  325. {
  326. BaseConfig.MyAnimeLog.Write("INIT MAIN WINDOW");
  327. vidHandler = new VideoHandler();
  328. vidHandler.DefaultAudioLanguage = settings.DefaultAudioLanguage;
  329. vidHandler.DefaultSubtitleLanguage = settings.DefaultSubtitleLanguage;
  330. }
  331. catch (Exception ex)
  332. {
  333. BaseConfig.MyAnimeLog.Write("Error on init: {0}", ex.ToString());
  334. }
  335. return Load(GUIGraphicsContext.Skin + @"\Anime3_Main.xml");
  336. }
  337. void Instance_ServerStatusEvent(Events.ServerStatusEventArgs ev)
  338. {
  339. setGUIProperty("HasherQueueCount", ev.HasherQueueCount.ToString());
  340. setGUIProperty("HasherQueueState", ev.HasherQueueState);
  341. setGUIProperty("HasherQueueRunning", ev.HasherQueueRunning ? "Running" : "Paused");
  342. setGUIProperty("GeneralQueueCount", ev.GeneralQueueCount.ToString());
  343. setGUIProperty("GeneralQueueState", ev.GeneralQueueState);
  344. setGUIProperty("GeneralQueueRunning", ev.GeneralQueueRunning ? "Running" : "Paused");
  345. setGUIProperty("ImagesQueueCount", ev.ImagesQueueCount.ToString());
  346. setGUIProperty("ImagesQueueState", ev.ImagesQueueState);
  347. setGUIProperty("ImagesQueueRunning", ev.ImagesQueueRunning ? "Running" : "Paused");
  348. if (dummyQueueAniDB != null) dummyQueueAniDB.Visible = ev.GeneralQueueCount >= 0;
  349. if (dummyQueueHasher != null) dummyQueueHasher.Visible = ev.HasherQueueCount >= 0;
  350. if (dummyQueueImages != null) dummyQueueImages.Visible = ev.ImagesQueueCount >= 0;
  351. }
  352. #region ISetupForm Members
  353. // Returns the name of the plugin which is shown in the plugin menu
  354. public string PluginName()
  355. {
  356. return Constants.PlugInInfo.NAME;
  357. }
  358. // Returns the description of the plugin is shown in the plugin menu
  359. public string Description()
  360. {
  361. return Constants.PlugInInfo.DESCRIPTION;
  362. }
  363. // Returns the author of the plugin which is shown in the plugin menu
  364. public string Author()
  365. {
  366. return Constants.PlugInInfo.AUTHOR;
  367. }
  368. // show the setup dialog
  369. public void ShowPlugin()
  370. {
  371. frmConfig cfg = new frmConfig();
  372. cfg.ShowDialog();
  373. }
  374. // Indicates whether plugin can be enabled/disabled
  375. public bool CanEnable()
  376. {
  377. return true;
  378. }
  379. // Enter the id number here again
  380. public int GetWindowId()
  381. {
  382. return Constants.PlugInInfo.ID;
  383. }
  384. // Indicates if plugin is enabled by default;
  385. public bool DefaultEnabled()
  386. {
  387. return true;
  388. }
  389. // indicates if a plugin has it's own setup screen
  390. public bool HasSetup()
  391. {
  392. return true;
  393. }
  394. /// <summary>
  395. /// If the plugin should have it's own button on the main menu of MediaPortal then it
  396. /// should return true to this method, otherwise if it should not be on home
  397. /// it should return false
  398. /// </summary>
  399. /// <param name="strButtonText">text the button should have</param>
  400. /// <param name="strButtonImage">image for the button, or empty for default</param>
  401. /// <param name="strButtonImageFocus">image for the button, or empty for default</param>
  402. /// <param name="strPictureImage">subpicture for the button or empty for none</param>
  403. /// <returns>true : plugin needs it's own button on home
  404. /// false : plugin does not need it's own button on home</returns>
  405. public bool GetHome(out string strButtonText, out string strButtonImage, out string strButtonImageFocus, out string strPictureImage)
  406. {
  407. AnimePluginSettings sett = new AnimePluginSettings();
  408. strButtonText = sett.PluginName;
  409. strButtonImage = String.Empty;
  410. strButtonImageFocus = String.Empty;
  411. strPictureImage = "hover_my anime3.jpg";
  412. return true;
  413. }
  414. #endregion
  415. private void EvaluateVisibility()
  416. {
  417. bool fave = false;
  418. bool missing = false;
  419. if (curAnimeGroup != null)
  420. {
  421. if (curAnimeGroup.IsFave == 1)
  422. fave = true;
  423. //BaseConfig.MyAnimeLog.Write("settings.ShowMissing: {0}", settings.ShowMissing);
  424. bool missingVisible = false;
  425. if (settings.ShowMissing && listLevel == Listlevel.Series && curAnimeSeries != null)
  426. {
  427. missingVisible = curAnimeSeries.HasMissingEpisodesGroups;
  428. }
  429. if (settings.ShowMissing && listLevel == Listlevel.Group)
  430. {
  431. missingVisible = curAnimeGroup.HasMissingEpisodes;
  432. }
  433. if (settings.ShowMissing)
  434. {
  435. missing = missingVisible;
  436. }
  437. if (dummyFave != null) dummyFave.Visible = fave;
  438. if (dummyMissingEps != null) dummyMissingEps.Visible = missing;
  439. //BaseConfig.MyAnimeLog.Write("EvaluateVisibility:: {0} - {1} - {2}", imgListFave != null, curAnimeGroup.IsFave, dummyLayoutListMode.Visible);
  440. }
  441. //EvaluateServerStatus();
  442. }
  443. protected override void OnPageDestroy(int new_windowId)
  444. {
  445. hook.IsEnabled = false;
  446. hook.UnHook();
  447. hook = null;
  448. UnSubClass();
  449. base.OnPageDestroy(new_windowId);
  450. }
  451. #region Detect application focus
  452. const int GWL_WNDPROC = (-4);
  453. const int WM_ACTIVATEAPP = 0x1C;
  454. // This static method is required because legacy OSes do not support
  455. // SetWindowLongPtr
  456. public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
  457. {
  458. if (IntPtr.Size == 8)
  459. return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
  460. else
  461. return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
  462. }
  463. [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
  464. private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
  465. [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
  466. private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
  467. [DllImport("user32.dll", EntryPoint = "CallWindowProc")]
  468. private static extern int CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hwnd, int msg, int wParam, int lParam);
  469. private delegate int WindowProc(IntPtr hwnd, int msg, int wParam, int lParam);
  470. IntPtr DefWindowProc = IntPtr.Zero;
  471. WindowProc NewWindowProc = null;
  472. void SubClass()
  473. {
  474. IntPtr hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
  475. NewWindowProc = new WindowProc(MyWindowProc);
  476. DefWindowProc = SetWindowLongPtr(hWnd, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(NewWindowProc));
  477. }
  478. void UnSubClass()
  479. {
  480. IntPtr hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
  481. DefWindowProc = SetWindowLongPtr(hWnd, GWL_WNDPROC, DefWindowProc);
  482. DefWindowProc = IntPtr.Zero;
  483. }
  484. int MyWindowProc(System.IntPtr hWnd, int msg, int wParam, int lParam)
  485. {
  486. if (msg == WM_ACTIVATEAPP)
  487. {
  488. //disable keyboard hook if app is inactive
  489. // wParam=1 when activating, 0 when desactivating
  490. hook.IsEnabled = (wParam == 1);
  491. }
  492. return CallWindowProc(DefWindowProc, hWnd, msg, wParam, lParam);
  493. }
  494. #endregion
  495. protected override void OnPageLoad()
  496. {
  497. BaseConfig.MyAnimeLog.Write("Starting page load...");
  498. SubClass();
  499. hook = new KeyboardHook();
  500. hook.KeyDown += new KeyEventHandlerEx(hook_KeyDown);
  501. hook.KeyUp += new KeyEventHandlerEx(hook_KeyUp);
  502. hook.IsEnabled = true;
  503. if (!isFirstInitDone)
  504. OnFirstStart();
  505. currentViewClassification = settings.LastViewClassification;
  506. currentStaticViewID = settings.LastStaticViewID;
  507. currentView = settings.LastView;
  508. groupViewMode = settings.LastGroupViewMode;
  509. m_Facade.CurrentLayout = groupViewMode;
  510. //backdrop.LoadingImage = loadingImage;
  511. Console.Write(JMMServerVM.Instance.ServerOnline.ToString());
  512. LoadFacade();
  513. m_Facade.Focus = true;
  514. SkinSettings.Load();
  515. //MainWindow.anidbProcessor.UpdateVotesHTTP(MainWindow.settings.Username, MainWindow.settings.Password);
  516. autoUpdateTimer.Start();
  517. BaseConfig.MyAnimeLog.Write("Thumbs Setting Folder: {0}", settings.ThumbsFolder);
  518. //searching
  519. setGUIProperty(guiProperty.FindInput, " ");
  520. setGUIProperty(guiProperty.FindText, " ");
  521. setGUIProperty(guiProperty.FindMatch, " ");
  522. search = new SearchCollection();
  523. search.List = m_Facade;
  524. search.ListItemSearchProperty = "DVDLabel";
  525. search.Mode = settings.FindMode;
  526. search.StartWord = settings.FindStartWord;
  527. UpdateSearchPanel(false);
  528. DownloadAllImages();
  529. }
  530. void autoUpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  531. {
  532. }
  533. private void AddFacadeItem(GUIListItem item)
  534. {
  535. int selectedIndex = m_Facade.SelectedListItemIndex;
  536. SaveOrRestoreFacadeItems(false);
  537. m_Facade.Add(item);
  538. if (searchTimer.Enabled)
  539. DoSearch(selectedIndex);
  540. }
  541. private void LoadFacade()
  542. {
  543. try
  544. {
  545. if (workerFacade == null)
  546. {
  547. workerFacade = new BackgroundWorker();
  548. workerFacade.WorkerReportsProgress = true;
  549. workerFacade.WorkerSupportsCancellation = true;
  550. workerFacade.DoWork += new DoWorkEventHandler(workerFacade_DoWork);
  551. workerFacade.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerFacade_RunWorkerCompleted);
  552. workerFacade.ProgressChanged += new ProgressChangedEventHandler(workerFacade_ProgressChanged);
  553. }
  554. lock (workerFacade)
  555. {
  556. if (workerFacade.IsBusy) // we have to wait - complete method will call LoadFacade again
  557. {
  558. if (!workerFacade.CancellationPending)
  559. workerFacade.CancelAsync();
  560. return;
  561. }
  562. prepareLoadFacade();
  563. workerFacade.RunWorkerAsync();
  564. }
  565. }
  566. catch (Exception ex)
  567. {
  568. BaseConfig.MyAnimeLog.Write("LoadFacade ERROR:: {0}", ex);
  569. }
  570. }
  571. void prepareLoadFacade()
  572. {
  573. try
  574. {
  575. GUIControl.ClearControl(this.GetID, m_Facade.GetID);
  576. SetFacade();
  577. this.m_Facade.ListLayout.Clear();
  578. if (this.m_Facade.ThumbnailLayout != null)
  579. this.m_Facade.ThumbnailLayout.Clear();
  580. if (this.m_Facade.FilmstripLayout != null)
  581. this.m_Facade.FilmstripLayout.Clear();
  582. if (this.m_Facade.CoverFlowLayout != null)
  583. this.m_Facade.CoverFlowLayout.Clear();
  584. if (m_Facade != null) m_Facade.Focus = true;
  585. }
  586. catch (Exception ex)
  587. {
  588. BaseConfig.MyAnimeLog.Write(ex.ToString());
  589. }
  590. }
  591. void workerFacade_ProgressChanged(object sender, ProgressChangedEventArgs e)
  592. {
  593. try
  594. {
  595. BackgroundFacadeLoadingArgument arg = e.UserState as BackgroundFacadeLoadingArgument;
  596. if (workerFacade.CancellationPending)
  597. {
  598. BaseConfig.MyAnimeLog.Write("bg_ProgressChanged cancelled");
  599. return;
  600. }
  601. if (arg == null || arg.Type == BackGroundLoadingArgumentType.None) return;
  602. switch (arg.Type)
  603. {
  604. case BackGroundLoadingArgumentType.ListFullElement:
  605. case BackGroundLoadingArgumentType.ListElementForDelayedImgLoading:
  606. List<GUIListItem> ls = arg.Argument as List<GUIListItem>;
  607. if (m_Facade != null && ls != null && ls.Count > 0)
  608. {
  609. foreach (GUIListItem gli in ls)
  610. {
  611. //BaseConfig.MyAnimeLog.Write("workerFacade_ProgressChanged - ListElementForDelayedImgLoading");
  612. // Messages are not recieved in OnMessage for Filmstrip, instead subscribe to OnItemSelected
  613. if (m_Facade.CurrentLayout == GUIFacadeControl.Layout.Filmstrip || m_Facade.CurrentLayout == GUIFacadeControl.Layout.CoverFlow)
  614. gli.OnItemSelected += new GUIListItem.ItemSelectedHandler(onFacadeItemSelected);
  615. AddFacadeItem(gli);
  616. if (arg.Type == BackGroundLoadingArgumentType.ListElementForDelayedImgLoading)
  617. {
  618. if (itemsForDelayedImgLoading == null)
  619. itemsForDelayedImgLoading = new List<GUIListItem>();
  620. itemsForDelayedImgLoading.Add(gli);
  621. }
  622. }
  623. if (this.m_Facade.SelectedListItemIndex < 1)
  624. {
  625. this.m_Facade.Focus = true;
  626. SelectItem(arg.IndexArgument);
  627. }
  628. }
  629. break;
  630. case BackGroundLoadingArgumentType.DelayedImgLoading:
  631. {
  632. if (itemsForDelayedImgLoading != null && itemsForDelayedImgLoading.Count > arg.IndexArgument)
  633. {
  634. string image = arg.Argument as string;
  635. itemsForDelayedImgLoading[arg.IndexArgument].IconImageBig = image;
  636. }
  637. }
  638. break;
  639. case BackGroundLoadingArgumentType.DelayedImgInit:
  640. itemsForDelayedImgLoading = null;
  641. break;
  642. case BackGroundLoadingArgumentType.SetFacadeMode:
  643. GUIFacadeControl.Layout viewMode = (GUIFacadeControl.Layout)arg.Argument;
  644. //setFacadeMode(viewMode);
  645. break;
  646. case BackGroundLoadingArgumentType.ElementSelection:
  647. {
  648. // thread told us which element it'd like to select
  649. // however the user might have already started moving around
  650. // if that is the case, we don't select anything
  651. if (this.m_Facade != null && this.m_Facade.SelectedListItemIndex < 1)
  652. {
  653. this.m_Facade.Focus = true;
  654. SelectItem(arg.IndexArgument);
  655. }
  656. }
  657. break;
  658. }
  659. }
  660. catch (Exception ex)
  661. {
  662. BaseConfig.MyAnimeLog.Write(string.Format("Error in bg_ProgressChanged: {0}: {1}", ex.Message, ex.InnerException));
  663. }
  664. }
  665. bool m_bQuickSelect = false;
  666. void SelectItem(int index)
  667. {
  668. //BaseConfig.MyAnimeLog.Write("SelectItem: {0}", index.ToString());
  669. // Hack for 'set' SelectedListItemIndex not being implemented in Filmstrip View
  670. // Navigate to selected using OnAction instead
  671. if (m_Facade.CurrentLayout == GUIFacadeControl.Layout.Filmstrip || m_Facade.CurrentLayout == GUIFacadeControl.Layout.CoverFlow)
  672. {
  673. if (listLevel == Listlevel.Series || listLevel == Listlevel.Group)
  674. {
  675. int currentIndex = m_Facade.SelectedListItemIndex;
  676. if (index >= 0 && index < m_Facade.Count && index != currentIndex)
  677. {
  678. m_bQuickSelect = true;
  679. int increment = (currentIndex < index) ? 1 : -1;
  680. MediaPortal.GUI.Library.Action.ActionType actionType = (currentIndex < index) ? MediaPortal.GUI.Library.Action.ActionType.ACTION_MOVE_RIGHT : MediaPortal.GUI.Library.Action.ActionType.ACTION_MOVE_LEFT;
  681. for (int i = currentIndex; i != index; i += increment)
  682. {
  683. // Now push fields to skin
  684. if (i == (index - increment))
  685. m_bQuickSelect = false;
  686. m_Facade.OnAction(new MediaPortal.GUI.Library.Action(actionType, 0, 0));
  687. }
  688. m_bQuickSelect = false;
  689. }
  690. else
  691. {
  692. if (listLevel == Listlevel.Group && m_Facade.Count > 0)
  693. {
  694. Group_OnItemSelected(m_Facade.SelectedListItem);
  695. }
  696. }
  697. }
  698. }
  699. else
  700. m_Facade.SelectedListItemIndex = index;
  701. }
  702. void workerFacade_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  703. {
  704. // ZF - seems to be crashing because of facade being null sometimes, before getting inside the plugin
  705. if (m_Facade == null)
  706. return;
  707. if (e.Cancelled)
  708. {
  709. LoadFacade(); // we only cancel if the user clicked something while we were still loading
  710. // whatever was selected we will enter (this is because m_selected whatever will not get updated
  711. // even if the user selects somethign else while we wait for cancellation due to it being a different listlevel)
  712. return;
  713. }
  714. if (m_Facade == null)
  715. return;
  716. m_Facade.Focus = true;
  717. }
  718. void workerFacade_DoWork(object sender, DoWorkEventArgs e)
  719. {
  720. bgLoadFacade();
  721. if (workerFacade.CancellationPending)
  722. e.Cancel = true;
  723. }
  724. void ReportFacadeLoadingProgress(BackGroundLoadingArgumentType type, int indexArgument, object state)
  725. {
  726. if (!workerFacade.CancellationPending)
  727. {
  728. BackgroundFacadeLoadingArgument Arg = new BackgroundFacadeLoadingArgument();
  729. Arg.Type = type;
  730. Arg.IndexArgument = indexArgument;
  731. Arg.Argument = state;
  732. workerFacade.ReportProgress(0, Arg);
  733. }
  734. }
  735. void bgLoadFacade()
  736. {
  737. try
  738. {
  739. GUIListItem item = null;
  740. int selectedIndex = -1;
  741. int count = 0;
  742. bool delayedImageLoading = false;
  743. List<AnimeGroupVM> groups = null;
  744. List<GroupFilterVM> groupFilters = null;
  745. List<GUIListItem> list = new List<GUIListItem>();
  746. BackGroundLoadingArgumentType type = BackGroundLoadingArgumentType.None;
  747. switch (listLevel)
  748. {
  749. #region Group Filters
  750. case Listlevel.GroupFilter:
  751. {
  752. // List/Poster/Banner
  753. setGUIProperty("SimpleCurrentView", "Group Filters");
  754. if (groupViewMode != GUIFacadeControl.Layout.List)
  755. {
  756. // reinit the itemsList
  757. delayedImageLoading = true;
  758. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.DelayedImgInit, 0, null);
  759. }
  760. // text as usual
  761. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.SetFacadeMode, 0, GUIFacadeControl.Layout.List);
  762. if (workerFacade.CancellationPending)
  763. return;
  764. BaseConfig.MyAnimeLog.Write("bgLoadFacde: Group Filters");
  765. groupFilters = FacadeHelper.GetGroupFilters();
  766. type = BackGroundLoadingArgumentType.ListFullElement;
  767. setGUIProperty(guiProperty.GroupCount, groupFilters.Count.ToString());
  768. foreach (GroupFilterVM grpFilter in groupFilters)
  769. {
  770. if (workerFacade.CancellationPending) return;
  771. try
  772. {
  773. item = null;
  774. SetGroupFilterListItem(ref item, grpFilter);
  775. if (curGroupFilter != null)
  776. {
  777. if (grpFilter.GroupFilterID.Value == curGroupFilter.GroupFilterID.Value)
  778. {
  779. selectedIndex = count;
  780. }
  781. }
  782. else
  783. {
  784. if (selectedIndex == -1)
  785. selectedIndex = count;
  786. }
  787. if (workerFacade.CancellationPending) return;
  788. else
  789. {
  790. list.Add(item);
  791. }
  792. }
  793. catch (Exception ex)
  794. {
  795. string msg = string.Format("The 'LoadFacade' function has generated an error displaying list items: {0} - {1}", listLevel, ex.ToString());
  796. BaseConfig.MyAnimeLog.Write(msg);
  797. }
  798. count++;
  799. }
  800. }
  801. break;
  802. #endregion
  803. #region Group Filters - Sub
  804. case Listlevel.GroupFilterSub:
  805. {
  806. // List/Poster/Banner
  807. setGUIProperty("SimpleCurrentView", curGroupFilter.GroupFilterName);
  808. if (groupViewMode != GUIFacadeControl.Layout.List)
  809. {
  810. // reinit the itemsList
  811. delayedImageLoading = true;
  812. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.DelayedImgInit, 0, null);
  813. }
  814. // text as usual
  815. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.SetFacadeMode, 0, GUIFacadeControl.Layout.List);
  816. if (workerFacade.CancellationPending)
  817. return;
  818. BaseConfig.MyAnimeLog.Write("bgLoadFacde: Group Filters");
  819. groupFilters = FacadeHelper.GetGroupFilters();
  820. type = BackGroundLoadingArgumentType.ListFullElement;
  821. setGUIProperty(guiProperty.GroupCount, "0");
  822. foreach (GroupFilterVM grpFilter in FacadeHelper.GetTopLevelPredefinedGroupFilters())
  823. {
  824. if (workerFacade.CancellationPending) return;
  825. try
  826. {
  827. item = null;
  828. SetGroupFilterListItem(ref item, grpFilter);
  829. if (curGroupFilter != null)
  830. {
  831. if (grpFilter.GroupFilterID.Value == curGroupFilter.GroupFilterID.Value)
  832. {
  833. selectedIndex = count;
  834. }
  835. }
  836. else
  837. {
  838. if (selectedIndex == -1)
  839. selectedIndex = count;
  840. }
  841. if (workerFacade.CancellationPending) return;
  842. else
  843. {
  844. list.Add(item);
  845. }
  846. }
  847. catch (Exception ex)
  848. {
  849. string msg = string.Format("The 'LoadFacade' function has generated an error displaying list items: {0} - {1}", listLevel, ex.ToString());
  850. BaseConfig.MyAnimeLog.Write(msg);
  851. }
  852. count++;
  853. }
  854. }
  855. break;
  856. #endregion
  857. #region Group Filters - Sub2
  858. case Listlevel.GroupFilterSub2:
  859. {
  860. // List/Poster/Banner
  861. setGUIProperty("SimpleCurrentView", curGroupFilter.GroupFilterName);
  862. if (groupViewMode != GUIFacadeControl.Layout.List)
  863. {
  864. // reinit the itemsList
  865. delayedImageLoading = true;
  866. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.DelayedImgInit, 0, null);
  867. }
  868. // text as usual
  869. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.SetFacadeMode, 0, GUIFacadeControl.Layout.List);
  870. if (workerFacade.CancellationPending)
  871. return;
  872. BaseConfig.MyAnimeLog.Write("bgLoadFacde: Group Filters");
  873. groupFilters = FacadeHelper.GetGroupFilters();
  874. type = BackGroundLoadingArgumentType.ListFullElement;
  875. setGUIProperty(guiProperty.GroupCount, "0");
  876. foreach (GroupFilterVM grpFilter in FacadeHelper.GetGroupFiltersForPredefined(curGroupFilterSub))
  877. {
  878. if (workerFacade.CancellationPending) return;
  879. try
  880. {
  881. item = null;
  882. SetGroupFilterListItem(ref item, grpFilter);
  883. if (curGroupFilter != null)
  884. {
  885. if (grpFilter.GroupFilterID.Value == curGroupFilter.GroupFilterID.Value)
  886. {
  887. selectedIndex = count;
  888. }
  889. }
  890. else
  891. {
  892. if (selectedIndex == -1)
  893. selectedIndex = count;
  894. }
  895. if (workerFacade.CancellationPending) return;
  896. else
  897. {
  898. list.Add(item);
  899. }
  900. }
  901. catch (Exception ex)
  902. {
  903. string msg = string.Format("The 'LoadFacade' function has generated an error displaying list items: {0} - {1}", listLevel, ex.ToString());
  904. BaseConfig.MyAnimeLog.Write(msg);
  905. }
  906. count++;
  907. }
  908. }
  909. break;
  910. #endregion
  911. #region Groups
  912. case Listlevel.Group:
  913. {
  914. // List/Poster/Banner
  915. setGUIProperty("SimpleCurrentView", curGroupFilter.GroupFilterName);
  916. if (groupViewMode != GUIFacadeControl.Layout.List)
  917. {
  918. // reinit the itemsList
  919. delayedImageLoading = true;
  920. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.DelayedImgInit, 0, null);
  921. }
  922. if (groupViewMode != GUIFacadeControl.Layout.List)
  923. {
  924. // graphical
  925. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.SetFacadeMode, 0, GUIFacadeControl.Layout.AlbumView);
  926. }
  927. else
  928. {
  929. // text as usual
  930. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.SetFacadeMode, 0, GUIFacadeControl.Layout.List);
  931. }
  932. if (workerFacade.CancellationPending)
  933. return;
  934. if (curGroupFilterSub2 == null)
  935. groups = JMMServerHelper.GetAnimeGroupsForFilter(curGroupFilter);
  936. else
  937. {
  938. groups = new List<AnimeGroupVM>();
  939. List<AnimeGroupVM> tempGroups = JMMServerHelper.GetAnimeGroupsForFilter(GroupFilterHelper.AllGroupsFilter);
  940. foreach (AnimeGroupVM grp in tempGroups)
  941. {
  942. if (curGroupFilterSub2.GroupFilterID.Value == Constants.StaticGF.Predefined_Categories_Child)
  943. {
  944. if (grp.Categories.Contains(curGroupFilterSub2.PredefinedCriteria))
  945. groups.Add(grp);
  946. }
  947. if (curGroupFilterSub2.GroupFilterID.Value == Constants.StaticGF.Predefined_Years_Child)
  948. {
  949. // find all the groups that qualify by this year
  950. int startYear = 0;
  951. if (!grp.Stat_AirDate_Min.HasValue) continue;
  952. startYear = grp.Stat_AirDate_Min.Value.Year;
  953. int endYear = int.MaxValue;
  954. if (grp.Stat_AirDate_Max.HasValue) endYear = grp.Stat_AirDate_Max.Value.Year;
  955. int critYear = 0;
  956. if (!int.TryParse(curGroupFilterSub2.PredefinedCriteria, out critYear)) continue;
  957. if (critYear >= startYear && critYear <= endYear) groups.Add(grp);
  958. }
  959. }
  960. }
  961. // re-sort if user has set a quick sort
  962. if (GroupFilterQuickSorts.ContainsKey(curGroupFilter.GroupFilterID.Value))
  963. {
  964. BaseConfig.MyAnimeLog.Write("APPLYING QUICK SORT");
  965. GroupFilterSorting sortType = GroupFilterHelper.GetEnumForText_Sorting(GroupFilterQuickSorts[curGroupFilter.GroupFilterID.Value].SortType);
  966. SortPropOrFieldAndDirection sortProp = GroupFilterHelper.GetSortDescription(sortType, GroupFilterQuickSorts[curGroupFilter.GroupFilterID.Value].SortDirection);
  967. List<SortPropOrFieldAndDirection> sortCriteria = new List<SortPropOrFieldAndDirection>();
  968. sortCriteria.Add(sortProp);
  969. groups = Sorting.MultiSort<AnimeGroupVM>(groups, sortCriteria);
  970. }
  971. // Update Series Count Property
  972. setGUIProperty(guiProperty.GroupCount, groups.Count.ToString());
  973. type = (groupViewMode != GUIFacadeControl.Layout.List) ? BackGroundLoadingArgumentType.ListElementForDelayedImgLoading : BackGroundLoadingArgumentType.ListFullElement;
  974. int seriesCount = 0;
  975. double totalTime = 0;
  976. DateTime start = DateTime.Now;
  977. BaseConfig.MyAnimeLog.Write("Building groups: " + curGroupFilter.GroupFilterName);
  978. foreach (AnimeGroupVM grp in groups)
  979. {
  980. if (workerFacade.CancellationPending) return;
  981. try
  982. {
  983. item = null;
  984. //BaseConfig.MyAnimeLog.Write(string.Format("{0} - {1}", grp.GroupName, grp.AniDBRating));
  985. SetGroupListItem(ref item, grp);
  986. if (settings.HideWatchedFiles && grp.UnwatchedEpisodeCount <= 0)
  987. {
  988. //watched files should be hidden and entire group is watched
  989. // -> hide entire group
  990. continue;
  991. }
  992. seriesCount += grp.AllSeriesCount;
  993. if (curAnimeGroup != null)
  994. {
  995. if (grp.AnimeGroupID == curAnimeGroup.AnimeGroupID)
  996. {
  997. selectedIndex = count;
  998. }
  999. }
  1000. else
  1001. {
  1002. if (selectedIndex == -1)
  1003. selectedIndex = count;
  1004. }
  1005. if (workerFacade.CancellationPending) return;
  1006. else
  1007. {
  1008. list.Add(item);
  1009. }
  1010. }
  1011. catch (Exception ex)
  1012. {
  1013. string msg = string.Format("The 'LoadFacade' function has generated an error displaying list items: {0} - {1}", listLevel, ex.ToString());
  1014. BaseConfig.MyAnimeLog.Write(msg);
  1015. }
  1016. count++;
  1017. }
  1018. TimeSpan ts2 = DateTime.Now - start;
  1019. totalTime += ts2.TotalMilliseconds;
  1020. BaseConfig.MyAnimeLog.Write("Total time for rendering groups: {0}-{1}", groups.Count, totalTime);
  1021. setGUIProperty(guiProperty.SeriesCount, seriesCount.ToString());
  1022. }
  1023. break;
  1024. #endregion
  1025. #region Series
  1026. case Listlevel.Series:
  1027. {
  1028. // this level includes series as well as sub-groups
  1029. if (seriesViewMode != GUIFacadeControl.Layout.List)
  1030. {
  1031. // reinit the itemsList
  1032. delayedImageLoading = true;
  1033. ReportFacadeLoadingProgress(BackGroundLoadingArgumentType.DelayedImgInit, 0, null);
  1034. }
  1035. if (workerFacade.CancellationPending) return;
  1036. List<SortPropOrFieldAndDirection> sortCriteria = null;
  1037. List<AnimeGroupVM> subGroups = curAnimeGroupViewed.SubGroups;
  1038. if (subGroups.Count > 0)
  1039. {
  1040. sortCriteria = new List<SortPropOrFieldAndDirection>();
  1041. sortCriteria.Add(new SortPropOrFieldAndDirection("SortName", false, SortType.eString));
  1042. subGroups = Sorting.MultiSort<AnimeGroupVM>(subGroups, sortCriteria);
  1043. }
  1044. // get the series for this group
  1045. List<AnimeSeriesVM> seriesList = curAnimeGroupViewed.ChildSeries;
  1046. if (seriesList.Count > 0)
  1047. {
  1048. sortCriteria = new List<SortPropOrFieldAndDirection>();
  1049. sortCriteria.Add(new SortPropOrFieldAndDirection("AirDate", false, SortType.eDateTime));
  1050. seriesList = Sorting.MultiSort<AnimeSeriesVM>(seriesList, sortCriteria);
  1051. }
  1052. //if (seriesList.Count == 0)
  1053. // bFacadeEmpty = true;
  1054. // Update Series Count Property
  1055. setGUIProperty(guiProperty.SeriesCount, seriesList.Count.ToString());
  1056. // now sort the groups by air date
  1057. type = BackGroundLoadingArgumentType.ListFullElement;
  1058. foreach (AnimeGroupVM grp in subGroups)
  1059. {
  1060. if (workerFacade.CancellationPending) return;
  1061. try
  1062. {
  1063. item = null;
  1064. SetGroupListItem(ref item, grp);
  1065. if (settings.HideWatchedFiles && grp.UnwatchedEpisodeCount <= 0)
  1066. {
  1067. //watched files should be hidden and entire group is watched
  1068. // -> hide entire group
  1069. continue;
  1070. }
  1071. if (workerFacade.CancellationPending) return;
  1072. else
  1073. {
  1074. list.Add(item);
  1075. }
  1076. }
  1077. catch (Exception ex)
  1078. {
  1079. string msg = string.Format("The 'LoadFacade' function has generated an error displaying list items: {0} - {1}", listLevel, ex.ToString());
  1080. BaseConfig.MyAnimeLog.Write(msg);
  1081. }
  1082. }
  1083. foreach (AnimeSeriesVM ser in seriesList)
  1084. {
  1085. //BaseConfig.MyAnimeLog.Write("LoadFacade-Series:: {0}", ser);
  1086. if (workerFacade.CancellationPending) return;
  1087. try
  1088. {
  1089. item = null;
  1090. SetSeriesListItem(ref item, ser);
  1091. if (settings.HideWatchedFiles && ser.UnwatchedEpisodeCount <= 0)
  1092. {
  1093. //watched files should be hidden and entire series is watched
  1094. // -> hide entire series
  1095. continue;
  1096. }
  1097. if (workerFacade.CancellationPending) return;
  1098. else
  1099. {
  1100. list.Add(item);
  1101. }
  1102. }
  1103. catch (Exception ex)
  1104. {
  1105. string msg = string.Format("The 'LoadFacade' function has generated an error displaying list items: {0} - {1}", listLevel, ex.ToString());
  1106. BaseConfig.MyAnimeLog.Write(msg);
  1107. }
  1108. count++;
  1109. }
  1110. }
  1111. break;
  1112. #endregion
  1113. #region Episode Types
  1114. case Listlevel.EpisodeTypes:
  1115. {
  1116. if (workerFacade.CancellationPending) return;
  1117. //List<AnimeEpisodeType> anEpTypes = AnimeSeries.GetEpisodeTypes(curAnimeSeries.AnimeSeriesID.Value);
  1118. type = BackGroundLoadingArgumentType.ListFullElement;
  1119. foreach (AnimeEpisodeTypeVM anEpType in curAnimeSeries.EpisodeTypesToDisplay)
  1120. {
  1121. item = null;
  1122. SetEpisodeTypeListItem(ref item, anEpType);
  1123. if (workerFacade.CancellationPending) return;
  1124. else
  1125. {
  1126. list.Add(item);
  1127. }
  1128. count++;
  1129. }
  1130. }
  1131. break;
  1132. #endregion
  1133. #region Episodes
  1134. case Listlevel.Episode:
  1135. {
  1136. if (workerFacade.CancellationPending) return;
  1137. if (curAnimeSeries == null) return;
  1138. // get the episodes for this series / episode types
  1139. //BaseConfig.MyAnimeLog.Write("GetEpisodes:: {0}", curAnimeSeries.AnimeSeriesID.Value);
  1140. //List<AnimeEpisode> episodeList = AnimeSeries.GetEpisodes(curAnimeSeries.AnimeSeriesID.Value);
  1141. curAnimeSeries.RefreshEpisodes();
  1142. List<AnimeEpisodeVM> episodeList = curAnimeSeries.GetEpisodesToDisplay(curAnimeEpisodeType.EpisodeType);
  1143. // Update Series Count Property
  1144. //setGUIProperty(guiProperty.SeriesCount, episodeList.Count.ToString());
  1145. bool foundFirstUnwatched = false;
  1146. type = BackGroundLoadingArgumentType.ListFullElement;
  1147. foreach (AnimeEpisodeVM ep in episodeList)
  1148. {
  1149. //BaseConfig.MyAnimeLog.Write("LoadFacade-Episodes:: {0}", ep);
  1150. if (workerFacade.CancellationPending) return;
  1151. try
  1152. {
  1153. item = null;
  1154. bool isWatched = SetEpisodeListItem(ref item, ep);
  1155. if (isWatched && settings.HideWatchedFiles)
  1156. continue;
  1157. if (!foundFirstUnwatched && !isWatched && ep.LocalFileCount > 0)
  1158. {
  1159. selectedIndex = count;
  1160. foundFirstUnwatched = true;
  1161. }
  1162. if (workerFacade.CancellationPending) return;
  1163. else
  1164. {
  1165. list.Add(item);
  1166. }
  1167. }
  1168. catch (Exception ex)
  1169. {
  1170. string msg = string.Format("The 'LoadFacade' function has generated an error displaying list items: {0} - {1}", listLevel, ex.ToString());
  1171. BaseConfig.MyAnimeLog.Write(msg);
  1172. }
  1173. count++;
  1174. }
  1175. SetFanartForEpisodes();
  1176. }
  1177. setGUIProperty(guiProperty.EpisodeCount, count.ToString());
  1178. break;
  1179. #endregion
  1180. }
  1181. #region Report ItemToAutoSelect
  1182. if (selectedIndex == -1)
  1183. selectedIndex = 0;
  1184. BaseConfig.MyAnimeLog.Write("Report ItemToAutoSelect: {0}", selectedIndex.ToString());
  1185. #endregion
  1186. ReportFacadeLoadingProgress(type, selectedIndex, list);
  1187. SetFacade();
  1188. #region DelayedImageLoading
  1189. // we only use delayed image loading for the main groups view
  1190. // since the other views will not have enough items to be concerned about
  1191. if (delayedImageLoading && groups != null)
  1192. {
  1193. BaseConfig.MyAnimeLog.Write("delayedImageLoading: Started");
  1194. // This is a perfect oportunity to use all cores on the machine
  1195. // we queue each image up to be loaded, resize and put them into memory in parallel
  1196. // Set the amount of threads to the amount of CPU cores in the machine.
  1197. int MaxThreads = Environment.ProcessorCount;
  1198. // This keeps track of how many of the threads have terminated
  1199. int done = 0;
  1200. // Pool of threads.
  1201. List<Thread> ImageLoadThreadPool = new List<Thread>();
  1202. // List of Groups in theā€¦

Large files files are truncated, but you can click here to view the full file